1

I'm writing an application for Windows Mobile 6 in C/C++. As usually, it has 2 soft keys, one of which is a menu. This menu has a popup menu in it. Here's (stripped) source of soft keys from resources.rc and few defines from 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
    }
}

When user opens a menu, I want to modify it - check, uncheck, enable, disable items etc. So I process WM_INITMENUPOPUP message in WndProc():

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

Now, when user opens main menu, OnMainMenuInit() is called. This works fine.

Now about the problem. I'd like to process opening "Min battery level" submenu separately. I get WM_INITMENUPOPUP message when opening submenu, I also get menu's handle (e.g., 0x0A5B0B74 for main menu, 0x0A5BA924 for submenu), but "Min battery level" submenu does not have a "command id" which could be used for identifying it. I get 2 as LOWORD(lParam), which is position of "Min battery level" item in main menu, but I don't like the idea of hard-coding this 2 for identifying "Min battery level" submenu, because adding menu items would mean that I have to change this hard-coded 2 as well.

Any advices on how to identify "Min battery level" submenu in WM_INITMENUPOPUP? With "identify" I mean "how do I know that this menu is for min battery level" (rather than "what is handle of min battery level submenu").

ctacke
  • 66,480
  • 18
  • 94
  • 155
binaryLV
  • 9,002
  • 2
  • 40
  • 42

2 Answers2

1

You can use the 2 to recover the menu item ID via GetMenuItemID.

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

You need to use MENUEX in order to give the submenu an ID.

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
  • I tried `MENUEX`, but I couldn't get it working as soft keys - it compiles, "Lock" and "Menu" soft keys are displayed, but click on "Menu" does not open the menu. – binaryLV Nov 29 '11 at 21:47
  • This may be one of the place where Windows CE differs from desktop Windows. Sorry I can't help further. – Raymond Chen Nov 30 '11 at 00:04
  • 1
    For what it's worth, using `MENUITEM SEPARATOR` (as shown in the question) with using `MENUEX` seems to cause compiler errors. Using `MENUITEM "", -1, MFT_SEPARATOR` appears to work though. – Frerich Raabe Jun 05 '12 at 12:43
0

I know this is an old question however what gives the problem is a slight misunderstanding of how the WM_INITMENUPOPUP message works.

The LOWORD(lParam) value is the 0 based index value of the main menu items, therefore in a normal application the file menu has value 0, the next on to the right, it could be the edit menu has a value of 1, and so on.

The HIWORD(lParam) values are for the system menu'e like the restore, minimize, and the close menu.

So here's is my solution to the problem

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

Guessing the index number on top level popup menus like the File or Edit menu is easy enough, second level popup menus like the one in this question (POPUP "Min battery level") is somewhat more difficult.

idsantos
  • 1
  • 1