用户注销/登录后,创建托盘图标时出现罕见错误
Rare error on Tray icon creation, after a user log out / log in
>我创建一个系统托盘图标:
BOOL TrayMessage(HWND hWnd, DWORD dwMessage)
{
NOTIFYICONDATA nid;
nid.cbSize = sizeof(nid);
nid.hWnd = hWnd;
nid.uID = 1;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MYAPP));
lstrcpy(nid.szTip, L"MyApp");
nid.uCallbackMessage = WM_NOTIFYICON;
return Shell_NotifyIcon(dwMessage, &nid);
}
当应用启动/创建窗口时:
case WM_CREATE:
if (!TrayMessage(hWnd, NIM_ADD))
MessageBox(hMainWnd, L"Tray error.", 0, 0);
此错误消息框:
当我正常启动.exe时永远不会发生。
仅在用户注销/用户重新登录后发生,平均每 5次启动一次(我的应用程序在每次会话启动时自动启动
,并执行任务计划任务(
当然,当错误发生时,图标不会显示在任务栏中。
可能是什么原因?
系统托盘系统尚未准备就绪(用户注销/再次登录后很短(?
任务栏本身还没有准备好?
我应该将创作移动到
WM_CREATE
之外的地方吗?
编辑:在@RbMm的评论之后,我尝试了这个:
case WM_CREATE:
TrayMessage(hWnd, NIM_ADD);
// I removed MessageBox(...) from here
uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
...
break;
default:
if (message == uTaskbarRestart)
{
TrayMessage(hWnd, NIM_ADD);
MessageBox(hMainWnd, L"TaskbarRestart", 0, 0);
}
此测试的结果:无法显示托盘图标的情况正是未显示消息框TaskbarRestart
的情况,即当任务栏重启事件永远不会进入消息循环时...这很奇怪...
注意:这仅在用户注销/重新登录后发生。
MSDN Shell_NotifyIcon的当前版本不再显示它(真可惜!(,但幸运的是,这里有一个存档版本,提供了两个有趣的信息:
1.
如果成功,则返回 TRUE,否则返回 FALSE。[...] 您可以调用 GetLastError 以获取有关失败案例的更具体信息。失败的最常见原因是任务栏窗口不存在或无响应。在这种情况下,GetLastError 返回E_FILE_NOT_FOUND。
阿拉伯数字。
处理Shell_NotifyIcon故障Shell_NotifyIcon 在 Windows
启动期间调用时通常会失败(例如,如果您的应用程序列在 HKLM\Software\Microsoft\Windows\CurrentVersion\Run 中(。这似乎是因为系统正忙于启动应用程序。该故障在低规格计算机或安装了某些品牌防病毒软件的计算机上更为常见,这些计算机在启动时似乎非常密集。遗憾的是,您不能依赖 GetLastError 返回的错误代码。当Shell_NotifyIcon返回 false 时,GetLastError 返回的一些常见错误包括:
ERROR_FILE_NOT_FOUND (2) ERROR_TIMEOUT (1460) ERROR_SUCCESS (0)
对 Shell_NotifyIcon 返回的任何错误的最适当响应是休眠一段时间,然后重试。
Paul Baker解释了为什么错误代码可能不同,转述自 http://groups.google.com/group/microsoft.public.platformsdk.shell/msg/59235b293cbf5dfa 和 http://groups.google.com/group/microsoft.public.platformsdk.shell/msg/73973287f15c03fc:
Shell_NotifyIcon实际上最初调用 SetLastError(0(。之后,基本上它使用FindWindow来查找托盘通知窗口。如果此操作失败,它通常会返回ERROR_FILE_NOT_FOUND。否则,它会使用 SendMessageTimeout 将WM_COPYDATA消息发送到托盘通知窗口,超时时间仅为 4 秒。如果该消息返回零,则Shell_NotifyIcon将失败,GetLastError 返回零。
溶液:
case WM_CREATE:
...
if (!TrayMessage(hWnd, NIM_ADD))
SetTimer(hWnd, IDT_TIMER1, 4000, (TIMERPROC) NULL);
break;
case WM_TIMER:
TrayMessage(hWnd, NIM_ADD);
KillTimer(IDT_TIMER1);
break;
- Shell_NotifyIcon在系统托盘中创建空白、无响应的图标
- 用户注销/登录后,创建托盘图标时出现罕见错误
- 打开应用程序主窗口 在系统托盘图标中的其他应用程序之上
- 隐藏自定义应用程序窗口,但应在任务栏上显示应用程序图标(不是作为托盘图标)
- 无法使用 LoadIcon() 在可视C++中设置正确的托盘图标
- 右键单击系统托盘图标,然后单击C 中的上下文菜单
- 清除通知托盘图标,窗口外壳
- Qt-没有托盘图标的通知,可能
- 删除Wm6.5中的系统托盘图标
- 日食 CDT 显示错误图标
- Windows 7 上 Win32 应用程序的任务栏中的放大图标错误
- 托盘图标未在 Visual C++ 中播放图像
- 系统托盘图标没有响应
- 为什么不在用户帐户上添加托盘图标?
- 为什么系统托盘图标会清除之前显示的图标?
- Windows Mobile c++托盘图标
- Qt和Visual Studio.托盘图标消失
- 我能区分单次和双击系统托盘图标吗?
- Win32 API,系统托盘图标消失
- 所有者绘制的托盘图标(winapi)