You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Explorer重启时如何重启Windows通知区域图标?

解决Windows托盘图标在Explorer重启/崩溃后消失的问题

一、捕获Explorer重启的系统消息实现自动恢复

Windows提供了公开的系统消息可监听Explorer重启事件,最可靠的是WM_SETTINGCHANGE(消息ID:0x001A):

  • 当Explorer重启完成后,系统会向所有顶层窗口发送该消息,此时lParam参数会指向字符串"Shell"(需用lstrcmp判断)。
  • 在窗口的WndProc中处理该消息,触发托盘图标重新创建即可。

针对远程桌面场景,还可监听WM_WTSSESSION_CHANGE(消息ID:0x02B1),当用户通过远程桌面登录/切换会话时会触发此消息,此时也需重新初始化托盘图标——远程会话切换可能导致托盘资源关联失效。

二、定期检查并恢复托盘图标

没有直接API可查询托盘图标是否可见,但可通过"先删后加"的方式强制恢复:

  • 定期(比如每30秒)执行Shell_NotifyIcon(NIM_DELETE, &tnid),再调用你的systrayCreateIcon函数重新添加图标。
  • 这种方式无需判断图标是否存在:即使图标正常,NIM_DELETE仅在图标存在时生效;重新添加也不会产生重复图标(相同hWnd和uID的NIM_ADD会覆盖原图标)。

三、关于WndProc接收图标消失的消息

你提到的0xc0de、0xc081属于Windows Shell内部未公开的私有消息,绝对不能依赖——微软随时可能修改这些消息的含义或废弃它们。

要让WndProc接收合法的事件通知,只能依赖公开的API和消息:

  1. 利用WM_SETTINGCHANGE监听Shell重启
  2. 利用WM_WTSSESSION_CHANGE监听远程会话切换
  3. 你的托盘回调消息MYPROG_ONICON仅在用户与图标交互(点击、悬停)时触发,无法用来检测图标是否消失。

代码修改建议

在窗口WndProc中添加以下消息处理逻辑:

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        // 处理Shell重启消息
        case WM_SETTINGCHANGE:
            if (lParam != NULL && lstrcmp((LPCSTR)lParam, "Shell") == 0)
            {
                // 先删除旧图标(如果存在)
                Shell_NotifyIcon(NIM_DELETE, &tnid);
                // 重新创建托盘图标
                systrayCreateIcon(hwnd);
            }
            break;

        // 处理远程桌面会话切换
        case WM_WTSSESSION_CHANGE:
            // 会话激活、登录等事件触发恢复,可根据需求调整条件
            if (wParam == WTS_SESSION_LOGON || wParam == WTS_SESSION_UNLOCK)
            {
                Shell_NotifyIcon(NIM_DELETE, &tnid);
                systrayCreateIcon(hwnd);
            }
            break;

        // 其他现有消息处理...
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

同时修改systrayCreateIcon函数,确保每次调用都正确设置完整的uFlags:

LRESULT systrayCreateIcon(HWND hwnd)
{
    LRESULT res;

    tnid.cbSize = sizeof(NOTIFYICONDATA); 
    tnid.hWnd   = hwnd; 
    tnid.uID    = TRAY_ICON; 
    // 每次创建必须设置NIF_MESSAGE,否则回调消息不会生效
    tnid.uFlags = NIF_MESSAGE | NIF_TIP | NIF_ICON; 
    tnid.uCallbackMessage = MYPROG_ONICON;
    tnid.hIcon  = iconCurrent;
    lstrcpy(tnid.szTip, "myprog"); 
    
    res = Shell_NotifyIcon(NIM_ADD, &tnid); 

    // 后续update可只保留NIF_TIP | NIF_ICON
    tnid.uFlags = NIF_TIP | NIF_ICON; 

    return res;
}

额外提示

  • 远程桌面的/admin会话属于控制台会话,切换时可能导致原会话的托盘资源被释放,因此监听WM_WTSSESSION_CHANGE是必要的。
  • 部分专业软件采用"监听Shell窗口生命周期"的方式:通过查找Explorer主窗口(类名为Shell_TrayWnd),当该窗口销毁/创建时触发图标恢复,这种方式更精准,但需用到FindWindow和SetWinEventHook监听窗口创建事件,实现稍复杂。

内容的提问来源于stack exchange,提问作者Erik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:53:14