WM_INITMENUPOPUP и ресурс POPUP

Я пишу приложение для Windows Mobile 6 на C/C++. Как обычно, он имеет 2 софт-клавиши, одна из которых - меню. В этом меню есть всплывающее меню. Вот (раздетый) источник софт-клавиш от resources.rc и мало кто определяет из resource.h:

#define IDR_MAIN_MENU  130
#define IDM_LOCK       30006
#define IDM_MAIN_MENU  30007

IDR_MAIN_MENU RCDATA
{
    IDR_MAIN_MENU,
    2,
    I_IMAGENONE, IDM_LOCK     , TBSTATE_ENABLED, TBSTYLE_AUTOSIZE | TBSTYLE_BUTTON  , IDS_LOCK, 0, NOMENU,
    I_IMAGENONE, IDM_MAIN_MENU, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN, IDS_MENU, 0, 0,
}

IDR_MAIN_MENU MENU
{
    POPUP "Menu"
    {
        MENUITEM "Keep display"     IDM_KEEP_DISPLAY_TURNED_ON
        MENUITEM "Keep backlight"   IDM_KEEP_BACKLIGHT_TURNED_ON
        POPUP "Min battery level"
        {
            MENUITEM "None" 0
            MENUITEM SEPARATOR
            MENUITEM "5%"  0
            MENUITEM "10%" 0
            ...
        }
        MENUITEM "Exit"             IDM_EXIT
    }
}

Когда пользователь открывает меню, я хочу изменить его - проверить, снять флажок, включить, отключить элементы и т. Д. Поэтому я обрабатываю WM_INITMENUPOPUP сообщение в WndProc():

case WM_INITMENUPOPUP:        
    switch (LOWORD(lParam))
    {
    case IDM_MAIN_MENU:
        OnMainMenuInit(reinterpret_cast<HMENU>(wParam));
        break;
    }
    break;

Теперь, когда пользователь открывает главное меню, вызывается OnMainMenuInit(). Это отлично работает.

Теперь о проблеме. Я бы хотел обработать открытие подменю "Минимальный уровень заряда батареи" отдельно. я получил WM_INITMENUPOPUP При открытии подменю я также получаю дескриптор меню (например, 0x0A5B0B74 для главного меню, 0x0A5BA924 для подменю), но подменю "Минимальный уровень заряда батареи" не имеет "идентификатора команды", который можно использовать для его идентификации. я получил 2 как LOWORD(lParam), которая является позицией пункта "Минимальный уровень заряда батареи" в главном меню, но мне не нравится идея жесткого кодирования этого 2 для определения подменю "Минимальный уровень заряда батареи", потому что добавление пунктов меню будет означать, что я должен изменить это жестко 2 также.

Любые советы о том, как определить подменю "Минимальный уровень заряда батареи" в WM_INITMENUPOPUP? Под "определить" я подразумеваю "как узнать, что это меню предназначено для минимального уровня заряда батареи" (а не "что такое ручка подменю минимального уровня заряда батареи").

2 ответа

Вы можете использовать 2 для восстановления идентификатора пункта меню через GetMenuItemID,

switch (GetMenuItemID(GetMenu(hwnd), LOWORD(lParam)))
{
case IDM_MIN_BATTERY_LEVEL: ...
}

Вам нужно использовать MENUEX чтобы дать подменю идентификатор.

Я знаю, что это старый вопрос, однако проблема заключается в небольшом недопонимании того, как работает сообщение WM_INITMENUPOPUP.

Значение LOWORD(lParam) является индексным значением 0 для пунктов главного меню, поэтому в обычном приложении файловое меню имеет значение 0, следующее справа, это может быть меню редактирования, имеющее значение 1, и скоро.

Значения HIWORD(lParam) для системного меню, такие как восстановление, свертывание и закрытие меню.

Так вот мое решение проблемы

case WM_INITMENUPOPUP:        
    switch (lParam)
    {
    case 0: // The Menu item
        OnMainMenuInit(reinterpret_cast<HMENU>(wParam));
        break;
    }
    break;

Определить номер индекса во всплывающих меню верхнего уровня, таких как меню "Файл" или "Редактировать", достаточно просто, а всплывающие меню второго уровня, такие как в этом вопросе (POPUP "Минимальный уровень заряда батареи"), несколько сложнее.

Другие вопросы по тегам