首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

清除系統托盤殭屍圖示:模擬滑鼠掃描法完整實作

     編輯:VC 教學

問題由來

應用程式異常終止時,托盤區(Notification Area)的圖示常殘留,直到滑鼠移過才消失。本文提供一個無需重啟 Explorer 的程式化清理解決方案。

核心原理

  1. 尋找托盤視窗句柄:Shell_TrayWnd → TrayNotifyWnd。
  2. 取得托盤區矩形範圍與系統小圖示尺寸(SM_CXSMICON, SM_CYSMICON)。
  3. 以網格方式逐點移動滑鼠游標覆蓋每個圖示位置(偏移 5px 避開邊緣)。
  4. 呼叫 Sleep(0) 讓出時間片,觸發系統重繪檢測。
  5. 還原滑鼠位置,強制重繪托盤視窗修正多行顯示殘影。

完整函數實作

void __fastcall RemoveDeadIcons()
{
    HWND hTrayWindow;
    RECT rctTrayIcon;
    int nIconWidth, nIconHeight;
    TPoint CursorPos;
    int nRow, nCol;

    // 1. 取得托盤視窗句柄
    hTrayWindow = FindWindowEx(
        FindWindow("Shell_TrayWnd", NULL), 
        0, "TrayNotifyWnd", NULL);
    if (!hTrayWindow) return;
    if (!GetWindowRect(hTrayWindow, &rctTrayIcon)) return;

    // 2. 系統小圖示度量
    nIconWidth  = GetSystemMetrics(SM_CXSMICON);
    nIconHeight = GetSystemMetrics(SM_CYSMICON);

    // 3. 保存當前滑鼠位置
    GetCursorPos(&CursorPos);

    // 4. 雙層迴圈掃描每個圖示格
    for (nRow = 0; nRow < (rctTrayIcon.bottom - rctTrayIcon.top) / nIconHeight; nRow++) {
        for (nCol = 0; nCol < (rctTrayIcon.right - rctTrayIcon.left) / nIconWidth; nCol++) {
            SetCursorPos(
                rctTrayIcon.left + nCol * nIconWidth + 5,
                rctTrayIcon.top  + nRow * nIconHeight + 5);
            Sleep(0); // 關鍵:讓系統處理訊息
        }
    }

    // 5. 還原滑鼠
    SetCursorPos(CursorPos.x, CursorPos.y);

    // 6. 強制重繪修正多行托盤殘影
    RedrawWindow(hTrayWindow, NULL, 0, 
                 RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW);
}

關鍵細節解析

步驟API說明
尋找托盤FindWindow/FindWindowEx層級:Shell_TrayWnd → TrayNotifyWnd
圖示尺寸GetSystemMetricsSM_CXSMICON/SM_CYSMICON 隨 DPI 變化
掃描策略雙層 for + SetCursorPos+5px 偏移避免落在格線邊緣
觸發重繪Sleep(0)讓出時間片,系統處理 WM_MOUSEMOVE 等
收尾RedrawWindowRDW_UPDATENOW 立即更新,修正多行 bug

適用場景與限制

  • ✅ 適用:Win9x/NT/2000/XP/2003 經典托盤架構。
  • ⚠️ 注意:Vista+ 引入 ITrayNotify 新架構,可能需改用 Shell_NotifyIcon(NIM_SETVERSION) 配合 NOTIFYICONDATA 正規清理。
  • ⚠️ 副作用:掃描過程滑鼠游標會閃動,建議在背景執行緒執行並暫時隱藏游標(ShowCursor(FALSE))。

替代方案:正規 API 清理

若目標為自家程式殘留圖示,優先在程式退出處呼叫:

NOTIFYICONDATA nid = { sizeof(nid) };
nid.hWnd = hWnd;
nid.uID  = MY_TRAY_ID;
Shell_NotifyIcon(NIM_DELETE, &nid);

托盤清理掃描示意圖

模擬滑鼠掃描法雖屬「暴力美學」,但在無法修改第三方程式碼時,是快速清除殭屍圖示的實用利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved