关于WinAPI:C ++ Win32动态菜单-选择了哪个菜单项

c++ win32 dynamic menu - which menu item was selected

我有一个Win32应用程序(c ++),该应用程序的上下文菜单绑定到右键单击通知图标。 菜单/子菜单项在运行时动态创建和更改。

1
2
3
4
5
 InsertMenu(hSettings, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR) hDevices, L"Setting 1");
 InsertMenu(hSettings, 1, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR) hChannels, L"Setting 2");

 InsertMenu(hMainMenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR) hSettings, L"Settings");
 InsertMenu(hMainMenu, 1, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");

在上面的代码中,hDevices和hChannels是动态生成的子菜单。
动态菜单是这样生成的:

1
2
3
   InsertMenu(hDevices, i, style, IDM_DEVICE, L"Test 1");
   InsertMenu(hDevices, i, style, IDM_DEVICE, L"Test 2");
   InsertMenu(hDevices, i, style, IDM_DEVICE, L"Test 3");

有什么方法可以知道单击了哪个项目,而不必定义每个子菜单项自己的ID(上面的代码中的IDM_DEVICE)? In希望检测到用户单击了子菜单IDM_DEVICE,并且单击了该子菜单中的第一项(测试1)。

我想达到这样的目标:

1
2
3
4
5
6
7
8
9
10
11
  case WM_COMMAND:
    wmId    = LOWORD(wParam);
    wmEvent = HIWORD(wParam);
    // Parse the menu selections:
    switch (wmId)
    {
        case IDM_DEVICE: // user clicked on Test 1 or Test 2 or Test 3
            UINT index = getClickedMenuItem(); // get the index number of the clicked item (if you clicked on Test 1 it would be 0,..)
                            // change the style of the menu item with that index
            break;          
    }

请尝试以下操作:

1
2
3
4
5
6
MENUINFO mi;
memset(&mi, 0, sizeof(mi));
mi.cbSize = sizeof(mi);
mi.fMask = MIM_STYLE;
mi.dwStyle = MNS_NOTIFYBYPOS;
SetMenuInfo(hDevices, &mi);

现在,您将获得WM_MENUCOMMAND而不是WM_COMMAND。 菜单索引将位于wParam中,菜单句柄将位于lParam中。 请注意,仅收看已知菜单的消息,然后将其余消息传递到DefWindowProc。 该代码将类似于以下内容:

1
2
3
4
5
6
7
8
9
case WM_MENUCOMMAND:
    HMENU menu = (HMENU)lParam;
    int idx = wParam;
    if (menu == hDevices)
    {
       //Do useful things with device #idx
    }
    else
        break; //Ensure that after that there is a DefWindowProc call


还可以将TrackPopupMenuEx()与标志TPM_RETURNCMD | TPM_NONOTIFY一起使用,并获得所选菜单项的id,而不必通过WM_MENUCOMMAND