C ++ Win32 динамическое меню - какой пункт меню был выбран - PullRequest
5 голосов
/ 25 сентября 2011

У меня есть приложение win32 (c ++), которое имеет контекстное меню, связанное с правой кнопкой мыши на значке уведомления.Пункты меню / подменю динамически создаются и изменяются во время выполнения.

 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 являются динамически генерируемыми подменю.Динамические меню создаются следующим образом:

   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");

Есть ли способ узнать, по какому элементу щелкнули, без необходимости определять каждый элемент подменю со своим собственным идентификатором (IDM_DEVICE в коде выше)?Он хотел бы обнаружить, что пользователь щелкнул по подменю IDM_DEVICE и что он щелкнул по первому элементу (Тест 1) в этом подменю.

Я хотел бы добиться чего-то вроде этого:

  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;          
    }

Ответы [ 2 ]

7 голосов
/ 25 сентября 2011

Попробуйте следующее:

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. Код будет похож на этот:

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
0 голосов
/ 06 января 2017

Можно также использовать TrackPopupMenuEx() с флагами TPM_RETURNCMD | TPM_NONOTIFY и получить id выбранного пункта меню без необходимости проходить WM_MENUCOMMAND.

...