Defining a Menu the Hard Way

Defining a menu in a program's resource script is usually the easiest way to add a menu in your window, but it's not the only way. You can dispense with the resource script and create a menu entirely within your program using two functions called CreateMenu and AppendMenu. After you finish defining the menu, you can pass the menu handle to CreateWindow or use SetMenu to set the window's menu.

Here's how it's done. CreateMenu simply returns a handle to a new menu:

hMenu = CreateMenu () ;

The menu is initially empty. AppendMenu inserts items into the menu. You must obtain a different menu handle for the top-level menu item and for each popup. The popups are constructed separately; the popup menu handles are then inserted into the top-level menu. The code shown in Figure 9-4 creates a menu in this fashion; in fact, it is the same menu as in the MENUDEMO program.

hMenu = CreateMenu () ;

hMenuPopup = CreateMenu () ;

AppendMenu (hMenuPopup, MF_STRING, IDM_NEW, "&New") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_OPEN, "&Open...") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_SAVE, "&Save") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_SAVEAS, "Save &As...") ;

AppendMenu (hMenuPopup, MF_SEPARATOR, 0, NULL) ;

AppendMenu (hMenuPopup, MF_STRING, IDM_EXIT, "E&xit") ;

AppendMenu (hMenu, MF_POPUP, hMenuPopup, "&File") ;

hMenuPopup = CreateMenu () ;

AppendMenu (hMenuPopup, MF_STRING, IDM_UNDO, "&Undo") ;

AppendMenu (hMenuPopup, MF_SEPARATOR, 0, NULL) ;

AppendMenu (hMenuPopup, MF_STRING, IDM_CUT, "Cu&t") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_COPY, "&Copy") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_PASTE, "&Paste") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_CLEAR, "C&lear") ;

AppendMenu (hMenu, MF_POPUP, hMenuPopup, "&Edit") ;

hMenuPopup = CreateMenu () ;

AppendMenu (hMenuPopup, MF_STRING | MF_CHECKED, IDM_WHITE, "&White") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_LTGRAY, "&Lt Gray") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_GRAY, "&Gray") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_DKGRAY, "&Dk Gray") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_BLACK, "&Black") ;

AppendMenu (hMenu, MF_POPUP, hMenuPopup, "&Background") ;

hMenuPopup = CreateMenu () ;

AppendMenu (hMenuPopup, MF_STRING, IDM_START, "&Start") ;

AppendMenu (hMenuPopup, MF_STRING | MF_GRAYED, IDM_STOP, "S&top") ;

AppendMenu (hMenu, MF_POPUP, hMenuPopup, "&Timer") ;

hMenuPopup = CreateMenu () ;

AppendMenu (hMenuPopup, MF_STRING, IDM_HELP, "&Help") ;

AppendMenu (hMenuPopup, MF_STRING, IDM_ABOUT, "&About MenuDemo...") ;

AppendMenu (hMenu, MF_POPUP, hMenuPopup, "&Help") ;

I think you'll agree that the resource script menu template is easier and clearer. I'm not recommending that you define a menu in this way, only showing that it can be done. Certainly you can cut down on the code size substantially by using some arrays of structures containing all the menu item character strings, IDs, and flags. But if you do that, you might as well take advantage of the third method Windows provides for defining a menu.