27.1 Adding menu selections

To add menu selections, open the Resource View as described in Appendix C. Click on the boxed little + signs as necessary to navigate down into the display until you see the Menu | IDR_POPTYPE selection. Double-click on this to open the menu in the Resource Editor.

(By the way, you might wonder about the Menu | IDR_MAINFRAME selection. This menu is what appears when no game documents are open; you can see it by closing all active games in the Pop program. Normally we don't bother changing this menu.)

Once you open the IDR_POPTYPE menu in the Resource Editor, you see a picture of a menu bar resource in the Resource Editor window on the right; you can edit this menu bar in a graphical manner. You can also change the arrangement of the menu by dragging selections around inside the Resource Editor, which is fully WYSIWYG. There will be gray boxes with dotted outlines in various positions on the menu; these are the spots where you can add things.

Each of the menu items has properties associated with it. To change the properties you can open the menu item Properties dialog for an item by double-clicking it or by highlighting it and pressing Alt+Enter. If you are using Visual Studio.NET, you may need to resize the dialog so you can see all of it, or you can scroll through it to find the lines you need to change.

It's worth noting that the Alt+Enter key combination will open the Properties dialog for other kinds of resources as well. Visual Studio, Version 6.0, has a helpful question mark at the corner of the dialog box that you can select for specific information about the Properties entries. Visual Studio.NET instead has a more generic and less specific kind of help that you can access with Help | Dynamic Help or Ctrl+F1.

Anyway, once you get your menu item Properties dialog box open, your typing goes into the Caption field of this box and onto the menu bar resource. Usually you don't bother to fill in the ID field in this dialog, Visual Studio will put something reasonable based on the menu item's position and name. You can see what Visual Studio put you have to close the menu item Properties dialog box and then open again. Thus the Game | Restart selection gets the ID_GAME_RESTART as its identifier.

Note that menu selections usually have one of their letters underlined for the short-cut key. You set the shortcut key by putting an '&' in front of the desired letter in the Caption field of the menu item Properties dialog box for that item. Thus the caption for Game | Restart that we type in is &Restart. You shouldn't use the same shortcut letter for different controls on the same popup, as Windows will always just do the first of the two controls when you use this key.

Also note that in the menu item Properties dialog box we have the option of Setting to TRUE [or checking the box for (in Version 6.0)] the Separator or Popup selections. A separator is a horizontal dividing line. A popup selection leads off a menu bar or a popup to another popup. Generally you should avoid having popups go down more than two, or at most three, levels deep. If you have a lot of controls it's better to lay them all out on a dialog box.

A final thing to notice in the menu item Properties dialog box is a field at the bottom labeled Prompt. The string you put into this box supplies a user prompt that appears in the status bar when that particular menu selection is highlighted. It's a good idea to fill in a prompt for each of your menu items. Whenever possible try and include some really useful information that's not already contained in the caption of the menu item. For instance, it's better to have the Game | Small prompt be Show 20 critters than to have the prompt be Small. Don't be stingy with the user. Share what you know.

A second point about the Prompt is that it's common to actually have two strings inside the prompt, with the second string being a one or two word phrase that can be used for a 'tool tip' in the event that this menu selection becomes implemented as a toolbar button. The two strings are separated with a newline symbol \n. Usually a tool tip is little more than the name of the menu selection. Thus the full Prompt used for the Game | Small might be Show 20 critters\nSmall count. We'll talk more about toolbar buttons in the next section.

Handling and updating menu selections

For every menu item that your program has, MFC will let you add two 'message handler' methods to your CView. The first is a so-called UPDATE method, whose name usually starts with On... The second message handler is a so-called UPDATE_COMMAND_UI method, whose name normally starts with OnUpdate... By the way, UI stands for 'user interface.' And we're using '. . .' here to stand for a name which is normally based on the name of your menu selection. the default behavior of Visual Studio is indeed to give these methods names based on your menu item's name. In the case of the Game | Small selection, for instance, the corresponding CView methods are named OnGameSmall and OnUpdateGameSmall.

The UPDATE or On... method is where you specify what happens when the user clicks on the menu selection.

The UPDATE_COMMAND_UI or OnUpdate... method is where you specify the appearance of the menu selection. Is it grayed-out? Does it have a checkmark? etc. The OnUpdate... method for a menu selection gets always gets called automatically before you open a popup. You might think that you need to worry about calling OnUpdate... to fix your menus, but you don't. In fact the OnUpdate... method gets called every time your program has nothing else to do on its message queue. The reason it gets called so often is that it's possible to turn your menu selections into toolbar buttons, and Windows wants to make sure that the appearance of your toolbar buttons is always up to date.

In Visual Studio.NET we use something called the Event Handler Wizard to add the message handlers. You open the Event Handler Wizard by right-clicking on the menu item whose messages you wish to handle, and by then selecting Add Event Handler... from the context popup menu. You will see a wizard dialog with the Command Name filled filled in with the ID of your menu selection, suh as ID_GAME_SMALL.

[In Version 6.0, we use the so-called Class Wizard. To open the Class Wizard, right-click the item and select Class Wizard.... You will see a multi-sheet Wizard dialog with the Message Maps sheet selected, and with the ID of your menu selection highlighted in the Object IDs box.]

You can now use the wizard to add the handler methods to your code. A box near the top middle says Class list [Class Name (Version 6.0)]. This is where we specify which class is going to be responsible for handling the menu selections. If a menu selection changes a parameter, it's most logical to have the class in which that parameter lives do the message handling. Our feeling regarding our new menu selections is that the Game | Play Sound should be handled by the CPopApp, the other Game selections should be handled by CPopDoc, and our new View selections should be handled by CPopView. By letting the classes that own the relevant parameters handle the menu-based changes of these parameters, we have to do a minimum of work in getting at the parameters.

Let's look at how we would add the handlers for the Game | Small selection. First we set the active field in Class list [or Class Name (Version 6.0)] to CPopDoc in the Wizard dialog. In the Message type box [Messages box (Version 6.0)] we see an UPDATE and an UPDATE_COMMAND_UI selection. One at a time, we highlight the selection. When you highlight a message selection, the wizard will suggest a default name for the message handler. You can edit this name in the wizard if you like. To actually put the handler into your code, you should click the wizard's Add and Edit button. Thus you can add, for instance, the prototypes and function bodies for the CPopDoc::OnGameSmall and CPopDoc::OnUpdateGameSmall methods.

Remember that menu selections will always need the UPDATE handler, and usually they will need the UPDATE_COMMAND_UI handler as well. In Visual Studio.NET, the wizard will close after you add one handler, so you will need to reopen it to add and edit the other handler.

[In Version 6.0, there is an Add button you can use to first add one handler before using the Add and Edit button to close the wizard and edit the handlers. Gotcha Alert! If you exit the Version 6.0 Class Wizard by just pressing the Esc key or by using the kill button in the corner of the dialog, the changes aren't saved. You need to exit the Version 6.0 Class Wizard either by pressing OK or by pressing Add and Edit, or Edit Code.]

[Once in a great while, in Version 6.0 you will start having trouble with the so-called Class Wizard *.clw file and Visual Studio will pop up warning messages about it. In this case you need to rebuild the *.clw file. To do this, close the project and delete the *.clw file. Then reopen the project, and select View | ClassWizard. Visual Studio will ask if you want to build a new Class Wizard file, say yes, and accept the defaults offered by the dialog.]

Now let's talk about the code for the handler methods. Remember that the On... method is for reacting to clicks on the menu selection. And the OnUpdate... method is for making the menu item's appearance reflect the current state of the program.

Remember that in handling our menu actions, we have the option of either affecting the underlying data in the document or of affecting the representation of the data in the view.

Let's look at an example involving a document variable.

void CPopDoc::OnGameSmall() 
    _pgame->setSeedcount (cgame::COUNTSMALL); 

void CPopDoc::OnUpdateGameSmall(CCmdUI* pCmdUI) 

And here's an example involving a view variable.

void CPopView::OnViewKeepplayerinview() 
        //Toggle the value. 

void CPopView::OnUpdateViewKeepplayerinview(CCmdUI* pCmdUI) 

The point of the OnUpdate... handlers is to put a checkmark by a menu item when it reflects the state of the program. Each time a popup is displayed, these handlers will automatically get called for all the menu items, so we can expect that only the desired ones of them will be checked.

An UPDATE_COMMAND_UI message handler like OnUpdateGameSmall takes a special MFC class CCmdUI as argument, this class can stand either for a menu selection or a toolbar button, and its most important methods are Enable and SetCheck. Enable takes a BOOL argument, and if this argument is TRUE, the effect is to gray a selection out. SetCheck takes an int argument which is 0 for unchecked and 1 for checked. The value of 2 is also used for toolbar buttons.

Yes, as we'll see in the next subsection, SetCheck can also be called by a toolbar buttons. SetCheck(0) leaves a toolbar button looking normal. SetCheck(1) makes the button's background a light gray, making it look as if it were in a pressed-down position. And SetCheck(2) sets a toolbar button to an 'indeterminate' grayed-out state, which is appropriate when the toolbar button doesn't apply to the current program state (for instance if no document windows are open).

    Part I: Software Engineering and Computer Games
    Part II: Software Engineering and Computer Games Reference