這篇講的很詳細~
曾經寫過一篇Windows下的工作列圖示程式設計 ,其實那篇文章講的是如何将我們自己的程式最小化到托盤并進行操作的程式設計方法。前兩天看到論壇 裡有人讨論如何隐藏托盤圖示,記得從前為朋友寫過一個隐藏大智慧軟體的程式,采用的方法就是将視窗最小化并隐藏大智慧在托盤上的圖示,但是因為涉及到鍵盤鈎子,最後并沒有這麼做,而是用添加一個虛拟桌面 的方法達到了效果。
看到這篇文章 ,依稀想起我曾經做過的一些嘗試,平時總是沒有動力整理一些零碎的代碼,這回碰到了也算給自己一個機會。
首先用Spy++查找一下系統托盤所在的視窗類:
可以看到我們需要的ToolbarWindow32其實是有層次的,但不能直接用FindWindow擷取ToolbarWindow32句柄,而應該像下面的代碼這樣一層層深入查找。
- hWnd = ::FindWindow( "Shell_TrayWnd" , NULL);
- hWnd = ::FindWindowEx(hWnd, 0, "TrayNotifyWnd" , NULL);
- hWndTmp = ::FindWindowEx(hWnd, 0, "SysPager" , NULL);
- if (!hWndTmp)
- hWnd = ::FindWindowEx(hWnd, 0, "ToolbarWindow32" , NULL);
- else
- hWnd = ::FindWindowEx(hWndTmp, 0, "ToolbarWindow32" , NULL);
我們的目标是隐藏系統托盤圖示,很明顯是一個跨程序操作,是以要明白是哪個程序在維護這些圖示,知道了視窗的句柄,擷取其背後的程序就比較容易了:
- ret = ::GetWindowThreadProcessId(hWnd, &lngPID);
- hProcess = ::OpenProcess(PROCESS_ALL_ACCESS
- |PROCESS_VM_OPERATION
- |PROCESS_VM_READ
- |PROCESS_VM_WRITE,
- 0,
- lngPID);
首先擷取程序ID,然後打開程序,擷取程序句柄。
接着在程序内配置設定一段記憶體:
(用VirtualAllocEx在目标程序中配置設定虛拟記憶體,SendMessage時用目标程序中的記憶體,通過ReadProcessMemory/WriteProcessMemory在程序間複制記憶體資料。)
- lngAddress = VirtualAllocEx(hProcess, 0, 0x4096, MEM_COMMIT, PAGE_READWRITE);
- ret = ::SendMessage(hWnd,TB_GETBUTTON,i, long (lngAddress));
并向視窗發送TB_GETBUTTON消息,獲得托盤Button的資訊,這裡的lngAddress中存儲的是TBBUTTON結構,其内容如下:
- typedef struct _TBBUTTON {
- int iBitmap; // zero-based index of button image
- int idCommand; // command to be sent when button pressed
- BYTE fsState; // button state--see below
- BYTE fsStyle; // button style--see below
- DWORD dwData; // application-defined value
- int iString; // zero-based index of button label string
- } TBBUTTON;
當滑鼠移動到系統托盤圖示上後,會有一些提示資訊,這些資訊儲存在dwData中,而idCommand則是TBBUTTON的id,我們要隐藏或者顯示圖示,都要針對這個圖示id進行操作:
- ret = ::ReadProcessMemory(hProcess, LPVOID (lngTextAdr), strBuff, 1024, 0);
- ret = ::ReadProcessMemory(hProcess, LPVOID ( long(lngAddress) + 4), &lngButtonID, 4, 0);
strBuffer中存放提示資訊,lngButtonID中存放id,有了這些資訊,要操作托盤圖示就非常簡單了,例如我可以
根據某些條件比對strBuffer,然後根據相應的lngButtonID隐藏圖示,隐藏或者顯示圖示是發送TB_HIDEBUTTON消息。
- ::SendMessage(hWnd, TB_HIDEBUTTON, BID, MAKELONG ( true , 0)); //隐藏圖示
- ::SendMessage(hWnd, TB_HIDEBUTTON, BID, MAKELONG ( false ,0)); //顯示圖示
當操作完成後,記得做清理工作:
- ::VirtualFreeEx( hProcess, lngAddress, 0x4096, MEM_RELEASE);
- ::CloseHandle(hProcess);
上面僅僅是針對一個圖示的操作,其實可以發送TB_BUTTONCOUNT消息,獲得圖示數量,然後循環處理。這裡是我寫的一個
sample,其中第一列顯示的是圖示id,第二列顯示的是圖示提示資訊,在ListBox上選取,然後可以點選隐藏,恢複。
總結一下,隐藏Windows系統托盤圖示基本步驟是這樣的:
1:擷取視窗句柄(此視窗裡面分布着所有的圖示button)
2:打開系統程序(管理系統所有托盤圖示的程序),對應一個大視窗
3:配置設定虛拟記憶體,讀取程序記憶體擷取相應資訊
4:操作
5:釋放記憶體,關閉程序句柄。
參考:http://blog.csdn.net/hailongchang/article/details/3454569
另可參考:http://blog.csdn.net/hailongchang/article/details/3490353