前兩天有朋友找我,讓幫忙寫個小工具,隱藏windows的托盤圖標,想想最近在家也不想做太復雜的事,也好幾年沒寫過windows上的小工具了,就答應了。想來挺簡單的事,沒想到還是有點小插曲的。特地來博客園上記錄一下,方便自己也方便大家。
隱藏托盤圖標主要有如下5個步驟:
1.獲取ToolbarWindow32窗口對象句柄,因為圖標都在這里面。(有兩個,用spy++找了好久才找全)
2.注入ToolbarWindow32進程,發送TB_BUTTONCOUNT/TB_GETBUTTON消息。
3.讀取TBBUTTON和TRAYDATA結構體數據。(64位和32位差異比較大,網上基本上都是32位的,查看了msdn才搞清楚TBBUTTON的結構體,TRAYDATA的結構體基本上就靠查資料和結合數據猜)
4.設置NOTIFYICONDATA結構體。
5.完工。
--------------------------------------------------------------------------------------------------------------------------------------
詳細過程,和示例代碼如下:
1.獲取ToolbarWindow32窗口句柄,ToolbarWindow32有2個,分別存在兩個不同的父窗口下,代碼如下:
a.“用戶升級的通知區域”,獲取代碼如下:
1 hWnd1 = FindWindow(TEXT("Shell_TrayWnd"), NULL); 2 hWnd1 = FindWindowEx(hWnd1, 0, TEXT("TrayNotifyWnd"), NULL); 3 hWnd1 = FindWindowEx(hWnd1, 0, TEXT("SysPager"), NULL); 4 hWnd1 = FindWindowEx(hWnd1, 0, TEXT("ToolbarWindow32"), NULL);
b.“溢出通知區域”,獲取代碼如下:
1 hWnd2 = FindWindow(TEXT("NotifyIconOverflowWindow"), NULL); 2 hWnd2 = FindWindowEx(hWnd2, 0, TEXT("ToolbarWindow32"), NULL);
2.注入ToolbarWindow32進程,發送TB_BUTTONCOUNT/TB_GETBUTTON消息。
a.注入,因為ToolbarWindow32進程和當前進程不是同一個進程,TB_BUTTONCOUNT/TB_GETBUTTON是沒法發送的,注入之后就可以發送了:
1 GetWindowThreadProcessId(hWnd, &dwProcessId); 2 hProcess = OpenProcess(PROCESS_ALL_ACCESS 3 |PROCESS_VM_OPERATION 4 |PROCESS_VM_READ 5 |PROCESS_VM_WRITE, 6 0, 7 dwProcessId); // 打開目標進程 8 lpAddress = VirtualAllocEx(hProcess,0, 0x4096, MEM_COMMIT, PAGE_READWRITE); //申請空間,發送消息之后,用來讀取獲取到的結構體數據
b.發送TB_BUTTONCOUNT/TB_GETBUTTON消息:
1 for(int i = 0 ; i < dwButtonCount; i++) 2 { 3 SendMessage(hWnd, TB_GETBUTTON, i, (LPARAM)lpAddress); // 遍歷發送TB_GETBUTTON消息,獲取對應信息 4 ... 5 }
3.讀取TBBUTTON和TRAYDATA結構體數據,代碼如下:
1 ReadProcessMemory(hProcess, lpAddress, &tb, sizeof(tb), 0); // 遠程讀取TBBUTTON結構體信息 2 3 if(tb.iString != -1) 4 { 5 TRAYDATA trayData; 6 WCHAR *pwsz = NULL; 7 ReadProcessMemory(hProcess, (LPVOID)tb.dwData, &trayData, sizeof(TRAYDATA), 0); // 遠程讀取TRAYDATA結構體信息 8 ... 9 }
4.設置NOTIFYICONDATA結構體:
1 NOTIFYICONDATA nid; 2 nid.cbSize = sizeof(NOTIFYICONDATA); 3 nid.hWnd = (HWND)trayData.hWnd; 4 nid.uID = trayData.uID; 5 nid.uFlags = NIF_STATE; 6 nid.dwState = bShow?NIS_SHAREDICON:NIS_HIDDEN; 7 nid.dwStateMask = NIS_HIDDEN; 8 Shell_NotifyIcon(NIM_MODIFY, &nid);
5.完成。
源碼下載地址:github
