Here are some more functions useful for working with menus:
When you change a top-level menu item, the change is not shown until Windows redraws the menu bar. You can force this redrawing by calling:
DrawMenuBar (hwnd) ;
Note that the parameter to DrawMenuBar is a handle to the window rather than a handle to the menu.
You can obtain the handle of a popup menu using:
hMenuPopup = GetSubMenu (hMenu, nPos) ;
where nPos is the index (starting at 0) of the popup within the top-level menu indicated by hMenu. You can then use the popup menu handle with other functions (such as AppendMenu).
You can obtain the current number of items in a top-level or popup menu using:
nCount = GetMenuItemCount (hMenu) ;
You can obtain the menu ID for an item in a popup menu from:
wID = GetMenuItemID (hMenuPopup, nPosition) ;
where nPosition is the position (starting at 0) of the item within the popup.
In MENUDEMO you saw how to check or uncheck an item in a popup menu using:
CheckMenuItem (hMenu, wID, wCheck) ;
In MENUDEMO, hMenu was the handle to the top-level menu, wID was the menu ID, and the value of wCheck was either MF_CHECKED or MF_UNCHECKED. If hMenu is a handle to a popup menu, then the wID parameter can be a positional index rather than a menu ID. If an index is more convenient, you include MF_BYPOSITION in the third parameter. For instance:
CheckMenuItem (hMenu, nPosition, MF_CHECKED | MF_BYPOSITION) ;
The EnableMenuItem function works similarly to CheckMenuItem except the third parameter is MF_ENABLED, MF_DISABLED, or MF_GRAYED. If you use EnableMenuItem on a top-level menu item that has a popup, you must also use the MF_BYPOSITION identifier in the third parameter because the menu item has no menu ID. We'll see an example of EnableMenuItem in the POPPAD program shown later in this chapter. HiliteMenuItem is similar to CheckMenuItem and EnableMenuItem but uses MF_HILITE and MF_UNHILITE. This highlighting is the reverse video that Windows uses when you move among menu items. You do not normally need to use HiliteMenuItem.
What else do you need to do with your menu? Have you forgotten what character string you used in a menu? You can refresh your memory by calling:
nByteCount = GetMenuString (hMenu, wID, lpString, nMaxCount, wFlag) ;
The wFlag is either MF_BYCOMMAND (where wID is a menu ID) or MF_BYPOSITION (wID is a positional index). The function copies up to nMaxCount bytes of the text string into lpString and returns the number of bytes copied.
Or perhaps you'd like to know what the current flags of a menu item are:
wFlags = GetMenuState (hMenu, wID, wFlag) ;
Again, wFlag is either MF_BYCOMMAND or MF_BYPOSITION. The wFlags parameter is a combination of all the current flags. You can determine them by testing against the MF_DISABLED, MF_GRAYED, MF_CHECKED, MF_MENUBREAK, MF_MENUBARBREAK, and MF_SEPARATOR identifiers.
Or maybe by this time you're a little fed up with menus. In that case you'll be pleased to know that if you no longer need a menu in your program, you can destroy it:
DestroyMenu (hMenu) ;
This invalidates the menu handle.