我用:
创建一个系统托盘图标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);
此错误消息框:
永远不会发生。
仅在用户注销/用户重新登录后发生,平均每5次启动一次(我的应用程序会在每次会话启动时使用TaskSchedular任务自动启动)
当然,当错误发生时,任务栏中不会显示图标。
可能是什么原因?
系统托盘系统还没有准备好(用户退出/再次登录后很短)?
任务栏本身还没准备好?
我应该将创作移到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);
}
此测试的结果:托盘图标无法显示的情况完全未显示MessageBox TaskbarRestart
的情况,即当TaskbarRestart事件永远不会出现时消息循环...这很奇怪......
注意:这仅在用户注销/重新登录后才会发生。
答案 0 :(得分:0)
当前版本的MSDN Shell_NotifyIcon不再显示它(真是太遗憾了!),但幸运的是,archived version here提供了两个有趣的信息:
1
如果成功则返回TRUE,否则返回FALSE。 [...] 您可以调用GetLastError以获取有关故障案例的更多特定信息。 失败的最常见原因是任务栏窗口不存在或无响应 。在这种情况下,GetLastError返回E_FILE_NOT_FOUND。
2
处理Shell_NotifyIcon失败
在Windows启动期间调用时,Shell_NotifyIcon通常会失败(例如,如果您的应用程序列在HKLM \ Software \ Microsoft \ Windows \ CurrentVersion \ Run中。这似乎是因为系统正忙于启动应用程序。失败在低启动时更常见-spec计算机或安装了某些品牌防病毒软件的计算机,在启动时似乎非常密集。不幸的是,您不能依赖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;