系统托盘上下文菜单不消失。

5

我使用以下方法创建通知图标:

notifyIcon.cbSize = sizeof(NOTIFYICONDATA);
notifyIcon.hWnd   = mainWnd;
notifyIcon.uID    = 100;
notifyIcon.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
notifyIcon.hIcon  = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LOGO));
notifyIcon.dwState = NIS_SHAREDICON;
notifyIcon.uVersion = NOTIFYICON_VERSION;
notifyIcon.uTimeout = 15000;
notifyIcon.uCallbackMessage = APP_MSG_TRAY;
wcscpy_s(notifyIcon.szTip, 127, WTXT_APP_TRAY_TOOLTIP);

Shell_NotifyIcon(NIM_ADD, &notifyIcon);
Shell_NotifyIcon(NIM_SETVERSION, &notifyIcon);

当WM_RBUTTONDOWN和WM_CONTEXTMENU事件发生时,弹出一个上下文菜单,如下所示:

MENUITEMINFO separatorBtn = {0};
separatorBtn.cbSize = sizeof(MENUITEMINFO);
separatorBtn.fMask = MIIM_FTYPE;
separatorBtn.fType = MFT_SEPARATOR;

HMENU hMenu = CreatePopupMenu();

if(hMenu) {
 InsertMenu(hMenu, -1, MF_BYPOSITION, APP_OPEN_OPTIONS, WTXT_OPTIONS);
 InsertMenuItem(hMenu, -1, FALSE, &separatorBtn);
 InsertMenu(hMenu, -1, MF_BYPOSITION, APP_MSG_EXIT, WTXT_EXIT);

 POINT pt;
 GetCursorPos(&pt);
 SetForegroundWindow(mainWnd);
 TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, mainWnd, NULL);
 PostMessage(mainWnd, WM_NULL, 0, 0);
 DestroyMenu(hMenu);
}

它运行良好,但上下文菜单并不总是消失。有时候(经常)如果您在系统托盘中有ie.Winamp和我的应用程序图标,并且您先右键单击我的应用程序,然后右键单击Winamp,两个菜单都会出现,直到您单击某个项目之前,我的菜单才会自动消失。

有什么想法吗?

谢谢...


1
我也经常在其他应用程序中发现这个问题,比如Spybot和AVG。我想知道这是否实际上是Win32的一个错误或缺陷。 - cdhowie
4个回答

15
为了显示通知图标的上下文菜单,应用程序在调用TrackPopupMenu或TrackPopupMenuEx之前,必须使当前窗口成为前台窗口。否则,当用户在菜单外面或创建菜单的窗口之外点击时,菜单将不会消失。
SetForegroundWindow(hDlg);

TrackPopupMenu(   hSubMenu,
                 TPM_RIGHTBUTTON,
                 pt.x,
                 pt.y,
                 0,
                 hDlg,
                 NULL);

1
六年后,真的吗? :) - Marin
7
我不关心时间,只想解决这个问题,哈哈。 - Jack
非常感谢您,它起作用了!!!这个错误在我的Qt/QML应用程序中发生,真是个谜。 - dev_null
1
这个深刻的答案应该被添加到已接受的答案中。 - Nibikibaba
在我的情况下,主对话框是否可见并没有什么区别。仅仅从系统托盘菜单中点击其他地方并不能使其消失。 - Andrew Truckle

5
不要捕获WM_RBUTTONDOWN而是捕获WM_RBUTTONUP。当然也不要同时处理WM_RBUTTONUP和WM_CONTEXTMENU,因为它们都会被处理并且每次右键单击都会显示两次上下文菜单。显示两次菜单会产生您所描述的效果:菜单弹出,但似乎不会消失(因为它会立即再次弹出第二次)。

谢谢,我明天会尝试并回复您。我认为这可能有帮助,因为如果我快速点击我的应用程序图标,同样的问题会出现 - 两个菜单会出现。 - Marin

1

有一些应用程序试图绕过通知区域(托盘)API的限制。它们会钩取资源管理器窗口并监听Windows消息。这使它们能够做一些本来不可能的事情,但不可避免地会破坏其他应用程序的稳定性。如果出现两个上下文菜单,那就是这种问题的明显迹象。

你已经找到了一个好的线索,可以确定哪种程序可能会这样做,因为它有一个图标。逐个杀死它们,直到找到罪犯。除了不运行它或向供应商投诉外,可能没有什么办法可以解决这个问题。


无论涉及哪些应用程序(包括Windows),我的这个错误都会出现,所以我猜测这可能是Stefan建议的问题或Windows的一个漏洞... - Marin

0

你似乎已经拥有了文档中提到的两个错误修复(SetForegroundWindow和WM_NULL),我认为除此之外的任何问题都是Windows的错误。

如果你真的想要做一些hacky的事情,你可能可以在WM_INITMENU*中获取菜单窗口句柄(我指的不是HMENU,而是菜单的HWND)并隐藏该窗口。


好的,我的老板希望这个问题得到解决,如果 Stefan 的修复方法不能解决这个问题,那么我就必须去处理,谢谢。 - Marin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接