【问题标题】:Clean up NotifyIcons of non-existent processes in system tray清理系统托盘中不存在的进程的 NotifyIcons
【发布时间】:2015-11-09 16:19:43
【问题描述】:

有很多 NotifyIcon 属于已终止的进程。 (到目前为止,我已经看到了多达 24 个这样的图标。) 如果用户将鼠标光标移到这些图标上,它们就会消失。

如何以编程方式清除所有“死”的 NotifyIcon?

编辑 1:

一些深入的谷歌搜索表明可以枚举 NotifyIcons 的 HWND。

https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c4f60ce-3573-433d-994e-9c17f95187f0/finding-which-applications-and-services-are-listed-in-the-system-tray?forum=csharpgeneral

进一步的工作是微不足道的。稍后会尝试。

【问题讨论】:

  • 编写一个邮件客户端,当应用程序供应商的一个应用程序崩溃时,它会向其 CEO 发送一封电子邮件,并在任务栏通知区域留下一个图标。不过,这可能不会立即删除图标。
  • 通知图标没有窗口化。无论您的链接说什么,它都不会告诉您如何获取通知图标的窗口句柄,因为它们没有窗口句柄。

标签: c++ windows winapi windows-7


【解决方案1】:

这是适用于 Windows 7 的有效解决方案。 对于其他版本,窗口类和名称可能不同。 使用 spyxx.exe 工具检查窗口树。

   HWND Get_Notification_Area_1()
    {            
        HWND hWnd = ::FindWindowA("Shell_TrayWnd", NULL);
        if (hWnd)
            hWnd = ::FindWindowExA(hWnd, NULL, "TrayNotifyWnd", NULL);
        if (hWnd)
            hWnd = ::FindWindowExA(hWnd, NULL, "SysPager", NULL);
        if (hWnd)
            hWnd = ::FindWindowExA(hWnd, NULL, "ToolbarWindow32", "User Promoted Notification Area");
        return hWnd;
    }

    HWND Get_Notification_Area_2()
    {            
        HWND hWnd = ::FindWindowA("NotifyIconOverflowWindow", NULL);
        if (hWnd)
            hWnd = ::FindWindowExA(hWnd, NULL, "ToolbarWindow32", "Overflow Notification Area");
        return hWnd;
    }

    void Process_Notification_Area(HWND hWnd)
    {
        if(!hWnd)
            return;
        RECT rcClient;
        BOOL bRet = ::GetClientRect(hWnd, &rcClient);
        if(!bRet)
            return;
        for(int y = rcClient.bottom - 16; y >= 0; y -= 16)
            for(int x = rcClient.right - 16; x >= 0; x -= 16)
                ::PostMessageA(hWnd, WM_MOUSEMOVE, NULL, MAKELPARAM(x, y));
    }

    void Clean_Up_Notification_Area()
    {
        Process_Notification_Area( Get_Notification_Area_1() );
        Process_Notification_Area( Get_Notification_Area_2() );
    }

【讨论】:

  • 确认可以在 Windows 10 20H2 下正常工作
【解决方案2】:

如何以编程方式清除所有“死”的 NotifyIcon?

你不能。没有用于此的 API。我想你可以编写脚本将鼠标光标移动到屏幕的这一部分,但这只是你能做的最好的事情。

【讨论】:

  • 好吧,我想你在这个话题上有一些经验。你能更详细地解释你的答案吗?我可以枚举 NotifyIcons 的 HWND 并将它们发送到 WM_MOUSEHOVER 吗?我可以从 HWND 获取 ProcessHandle,检查它的存在并在进程不存在时关闭 NotifyIcon 吗?解释一下,为什么不呢。
  • 没有更多细节了。我说这不能通过公平的方式来完成。您无法获得通知图标的 HWND,它们不是窗口。您无法向他们发送消息,因为他们的所有者窗口已死。你所能做的就是假鼠标输入。用户将看到光标移动。
  • 让我们看看,这些 NotifyIcon 包含在属于 explorer.exe 的窗口(使用 Process Hacker 检查)的通知区域中。重新启动 explorer.exe 会清除通知区域。那么,我可以向通知区域的 HWND 发送一些 WM_MOUSEHOVER 吗?
  • 你可以这样做。 Shell 是否以您希望的方式响应这些消息?无论如何,我不确定我能不能再提供给你了。您似乎已经从最初的问题继续前进。很抱歉我帮不上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
相关资源
最近更新 更多