托盘图标管理器与跨进程SendMessage

通过Spy++可以看出,系统托盘图标是一个ToolbarWindow32控件,要对其进行控制,只要用FindWindow和FindWindowEx找到其句柄,并发送ToolbarWindow32支持的消息即可。

1.获取图标数量:TB_BUTTONCOUNT

?
1
DWORD dwCount=::SendMessage(hToolbarWindow32, TB_BUTTONCOUNT, NULL, NULL);

2.获取图标的具体信息:TB_GETBUTTON

?
1
2
::SendMessage(hToolbarWindow32, TB_GETBUTTON, iIndex, ( LPARAM )(LPTBBUTTON) lpButton);

难点在于,此处的SendMessage是跨进程操作,lpButton要在ToolbarWindow32所在的进程中申请。

具体代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//打开ToolbarWindow32所在的进程,就是explorer.exe
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,x_GetWndProcessId(hToolbarWindow32));
 
//在进程explorer.exe中申请内存
LPVOID lpButton=VirtualAllocEx(hProcess,NULL, sizeof (TBBUTTON),MEM_COMMIT, PAGE_READWRITE);
 
//执行TB_GETBUTTON
::SendMessage(hToolbarWindow32, TB_GETBUTTON, i, ( LPARAM )lpButton);
 
//从进程explorer.exe中读取需要的数据
TBBUTTON TButton;
::ReadProcessMemory(hProcess, lpButton, &TButton, sizeof (TBBUTTON), NULL);
 
TRAYDATA TrayData;
::ReadProcessMemory(hProcess, ( LPVOID )TButton.dwData, &TrayData, sizeof (TRAYDATA), NULL);
 
TCHAR szTips[1024];
::ReadProcessMemory(hProcess, ( LPVOID )TButton.iString, szTips, 1024, NULL);
 
//szTips是Unicode字符串,需要转换
USES_CONVERSION;
CString csTips=W2A(( WCHAR *)(szTips));
 
//释放在进程explorer.exe中申请的内存
::VirtualFreeEx(hProcess, lpButton, sizeof (TBBUTTON), MEM_FREE);
CloseHandle(hProcess);

备注,TBBUTTON.dwData的格式如下:

?
1
2
3
4
5
6
7
8
9
10
11
struct TRAYDATA
{
  HWND hWnd;
  UINT uID;
  UINT uCallbackMessage;
  DWORD Reserved1[2];
  HICON hIcon;
  DWORD Reserved2[3];
  TCHAR szExePath[MAX_PATH];
  TCHAR szTip[128];
};

3.删除或恢复图标
有了上面得到的信息,就可以使用Shell_NotifyIcon函数来操作图标了。

4.程序截图与源码
双击某行可实现托盘图标的隐藏或显示。



源码:点击下载系统托盘图标管理器源码与可执行程序

http://www.qingfengju.com/article.asp?id=294

你可能感兴趣的:(控件,托盘跨进程)