一般而言,当我们的程序被意外关闭后,托盘就会残留一个无效图标。必须我们手动用鼠标移动过去才会消失,在网上找了很多方法,其核心内容就是模拟我们的鼠标移动操作,每次这样重新打开时都会执行一次,确保只会出现一个图标,这里将我试起来能用的整理下。
首先,系统托盘似乎分为两部分,及右下角的横条及倒三角里的隐藏区,因为我的电脑默认会把图标加入隐藏区,所以只对此部分进行了测试,以下代码。
//溢出窗口
HWND overHabdle = FindWindowEx(0, 0, L"NotifyIconOverflowWindow", NULL);
HWND NotifyOverHandle = FindWindowEx(overHabdle, 0, L"ToolbarWindow32", NULL);
if (NotifyOverHandle)
{
RECT r;
::GetWindowRect(NotifyOverHandle, &r);
int width = r.right - r.left;
int height = r.bottom - r.top;
//从任务栏中间从左到右 MOUSEMOVE一遍,所有图标状态会被更新
for (int x = 0; x < r.right; x += 5)
{
for (int y = 0; y < r.bottom; y += 5)
{
::SendMessage(NotifyOverHandle, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
}
}
}
注意:执行以上操作在我的电脑上测试,会耗时5s左右,并且移动坐标那里似乎还并不是很精准,有待优化。
2022-10-8更新:
经查看,每一个图标是一个占位50px的正方形,将上面循环的x+=5和y+=5改为25。轮询一遍200ms左右,可以接受。
后面为其他位置的代码,还未进行测试:
//任务栏窗口
HWND hShellTrayWnd = ::FindWindow(L"Shell_TrayWnd", NULL);
//任务栏右边托盘图标+时间区
HWND hTrayNotifyWnd = ::FindWindowEx(hShellTrayWnd, 0, L"TrayNotifyWnd", NULL);
//不同系统可能有可能没有这层
HWND hSysPager = ::FindWindowEx(hTrayNotifyWnd, 0, L"SysPager", NULL);
//托盘图标窗口
HWND hToolbarWindow32;
if (hSysPager)
{
hToolbarWindow32 = ::FindWindowEx(hSysPager, 0, L"ToolbarWindow32", NULL);
}
else
{
hToolbarWindow32 = ::FindWindowEx(hTrayNotifyWnd, 0, L"ToolbarWindow32", NULL);
}
if (hToolbarWindow32)
{
RECT r;
::GetWindowRect(hToolbarWindow32, &r);
int width = r.right - r.left;
int height = r.bottom - r.top;
//从任务栏中间从左到右 MOUSEMOVE一遍,所有图标状态会被更新
for (int x = 1; x < width; x++)
{
::SendMessage(hToolbarWindow32, WM_MOUSEMOVE, 0, MAKELPARAM(x, height));
}
}