代码之家  ›  专栏  ›  技术社区  ›  Marin

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

  •  2
  • Marin  · 技术社区  · 15 年前

    我创建通知图标时使用:

    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_ButtonDown和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”,Bot菜单将出现,只有单击某个项目,我的菜单才会自动消失。

    有什么想法吗?

    谢谢。。。

    4 回复  |  直到 10 年前
        1
  •  3
  •   Stefan    15 年前

    不要捕获wm_buttonDown,而是捕获wm_buttonup。当然,不要同时处理wm_buttonup和wm_contextmenu,因为它们会 二者都 处理好后,每单击一次右键,就会显示两次上下文菜单。 将菜单显示两次会产生您描述的效果:菜单会出现,但似乎不会消失(因为它会立即再次出现)。

        2
  •  8
  •   Jack    10 年前

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

    SetForegroundWindow(hDlg);
    
    TrackPopupMenu(   hSubMenu,
                     TPM_RIGHTBUTTON,
                     pt.x,
                     pt.y,
                     0,
                     hDlg,
                     NULL);
    
        3
  •  1
  •   Hans Passant    15 年前

    有一些应用程序试图绕过通知区域(托盘)API的限制。他们将挂接浏览器窗口并监听Windows消息。这让他们做一些原本不可能做的事情,但不可避免地会破坏其他应用程序的稳定性。得到两个上下文菜单肯定是这种麻烦的征兆。

    你已经很好地了解了什么样的程序可以做到这一点,它有一个图标。把他们一个一个地杀了,直到你找到了作恶的人。除了不运行它或向供应商抱怨之外,您可能无法对它做太多的事情。

        4
  •  0
  •   Anders    15 年前

    您似乎已经有了两个有文档记录的错误修复(setForegroundWindow&wm_空),我想说的是,除了这一点,Windows中还有一个错误。

    如果你真的想做一些骇人的事情,你可以在wm-initmenu*中得到菜单窗口句柄(我不是指hmenu,而是指菜单的hwnd)并隐藏该窗口。