[C++]隐藏/删除/显示托盘图标

本文详细解析了Windows系统的托盘API,包括如何获取托盘可见区域的句柄,获取进程ID,以及如何在进程中申请内存来保存数据。通过遍历托盘上的按钮,实现了对每个按钮的文本、图标、ID等信息的获取,并展示了如何在屏幕上打印图标,以及如何隐藏和显示托盘图标。最后,通过Shell_NotifyIcon函数实现了托盘图标的添加与删除操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

研究了一下Windows的托盘,发现是个Toolbar,于是我们就可以用常用的消息对其进行处理,只是需要在Explorer.exe进程申请一块内存来保存数据:

struct TRAYDATA
{
	HWND hWnd;
	UINT uID;
	UINT uCallbackMessage;
	DWORD Reserved1[2];
	HICON hIcon;
	DWORD Reserved2[3];
	TCHAR szExePath[MAX_PATH];
	TCHAR szTip[128]; 
};

//获取托盘可见区域句柄
HWND hWnd = NULL;
hWnd = ::FindWindow(_T("Shell_TrayWnd"), NULL);
hWnd = ::FindWindowEx(hWnd, NULL, _T("TrayNotifyWnd"), NULL);
//hWnd = ::FindWindowEx(hWnd, NULL, _T("ReBarWindow32"), NULL);
//hWnd = ::FindWindowEx(hWnd, NULL, _T("CiceroUIWndFrame"), NULL);
hWnd = ::FindWindowEx(hWnd, NULL, _T("SysPager"), NULL);
//hWnd = ::FindWindowEx(hWnd, NULL, _T("Button"), NULL);
hWnd = ::FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);

//获取进程 ID
DWORD dwPID = 0;
::GetWindowThreadProcessId(hWnd, &dwPID);
DWORD dwCount = ::SendMessage(hWnd, TB_BUTTONCOUNT, NULL, NULL);
printf("托盘可见区域当前存在 %u 个图标!PID = %u\n", dwCount, dwPID);

//获取托盘溢出区域句柄
//hWnd = ::FindWindow(_T("NotifyIconOverflowWindow"), NULL);
//hWnd = ::FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);

//::GetWindowThreadProcessId(hWnd, &dwPID);
//dwCount = ::SendMessage(hWnd, TB_BUTTONCOUNT, NULL, NULL);
//printf("托盘溢出区域当前存在 %u 个图标!PID = %u\n", dwCount, dwPID);

//打开进程
HANDLE hProc = ::OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwPID);

//申请内存
LPVOID pTB = ::VirtualAllocEx(hProc, NULL, sizeof(TBBUTTON), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

TBBUTTON tb;
TRAYDATA td;
NOTIFYICONDATA nid;
for (DWORD i = 0; i < dwCount; i++)
{
	printf("获取按钮 %u 信息...%u\n", i, ::SendMessage(hWnd, TB_GETBUTTON, i, (LPARAM)pTB));
	
	::ReadProcessMemory(hProc, pTB, &tb, sizeof(TBBUTTON), NULL);
	printf("按钮 %u TRAYDATA 图标信息地址:%08X\n", i, tb.dwData);

	//获取按钮文本

	//获取 TRAYDATA 信息
	::ReadProcessMemory(hProc, (LPVOID)tb.dwData, &td, sizeof(TRAYDATA), NULL);
	printf("句柄:0x%08X,ID:%u,回调消息:0x%08X,图标句柄:0x%08X\n图标提示:\n%s\n\n", td.hWnd, td.uID, td.uCallbackMessage, td.hIcon, (CStringA)CString(td.szTip));
	
	//在屏幕上打印图标
	printf("尝试在屏幕上打印图标...\n");
	//::InvalidateRect(::GetForegroundWindow(), &CRect(48 * (i / 8) + 10, 48 * (i % 8) + 10, 48, 48), TRUE);
	::DrawIcon(::GetDC(::GetForegroundWindow()), 48 * (i / 8) + 10, 48 * (i % 8) + 10, td.hIcon);
	::Sleep(2000);

	//显示 / 隐藏图标
	//方法一:发送消息至托盘工具条
	//printf("尝试隐藏托盘图标...\n");
	//::SendMessage(hWnd, TB_HIDEBUTTON, tb.idCommand, MAKELONG(TRUE, 0)); //隐藏图标(留下空白的占用位)
	//::Sleep(2000);
	//printf("尝试恢复托盘图标...\n");
	//::SendMessage(hWnd, TB_HIDEBUTTON, tb.idCommand, MAKELONG(FALSE, 0)); //显示图标

	//方法二:填充 NOTIFYICONDATA 结构体,调用 Shell_NotifyIcon 函数
	nid.cbSize = sizeof(NOTIFYICONDATA);
	nid.hWnd = td.hWnd;
	nid.uID = td.uID;
	nid.uCallbackMessage = td.uCallbackMessage;
	nid.hIcon = td.hIcon;
	memcpy(nid.szTip, td.szTip, sizeof(nid.szTip));
	nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
	printf("尝试删除托盘图标...\n");
	::Shell_NotifyIcon(NIM_DELETE, &nid); //删除图标(注意这里是删除而不是隐藏)
	::Sleep(2000);
	printf("尝试恢复托盘图标...\n");
	::Shell_NotifyIcon(NIM_ADD, &nid); //显示图标
}

//释放内存
::VirtualFreeEx(hProc, pTB, sizeof(TBBUTTON), MEM_FREE);

//关闭进程句柄
::CloseHandle(hProc);

system("Pause");


 

这个是控制台程序,VS2008+XP/Win7测试通过,请注意XP没有“溢出托盘区域”。。。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值