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

时间:2010-11-10 14:37:26

标签: c++ windows winapi

我创建了一个通知图标:

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,将显示机器人菜单,并且在您单击某个项目之前我的菜单不会自动消失。

有什么想法吗?

感谢...

4 个答案:

答案 0 :(得分:8)

要显示通知图标的上下文菜单,当前窗口必须是应用程序调用TrackPopupMenu或TrackPopupMenuEx之前的前台窗口。否则,当用户点击菜单外部或创建菜单的窗口(如果可见)时,菜单不会消失。

SetForegroundWindow(hDlg);

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

答案 1 :(得分:3)

不要捕获WM_RBUTTONDOWN而是捕获WM_RBUTTONUP。当然不要同时处理WM_RBUTTONUP和WM_CONTEXTMENU,因为它们将两者得到处理,并且每次右键单击都会显示两次上下文菜单。 两次显示菜单会产生你描述的效果:菜单显示,但似乎没有消失(因为它会立即再次显示)。

答案 2 :(得分:1)

有些应用试图破解通知区域(托盘)API的限制。他们将挂钩资源管理器窗口并侦听Windows消息。这让他们可以做其他事情不可能的事情,但它不可避免地会破坏其他应用程序的稳定性。获得两个上下文菜单是这种麻烦的明确标志。

你有一个很好的领导,可以做什么样的程序,它有一个图标。一个接一个地杀死他们,直到你找到邪恶的行为者。除了没有运行它或向供应商抱怨之外,你可能做的不多。

答案 3 :(得分:0)

你似乎已经有两个记录的错误修正(SetForegroundWindow& WM_NULL)我会说除此之外的任何东西都是windows中的错误。

如果你真的想做hacky事情,你可能会得到WM_INITMENU *中的菜单窗口句柄(我不是指HMENU,而是菜单的HWND)并隐藏该窗口。