Dal's Programming Course - Lesson 07

Menus

There are a lot of built-in features in Windows that you can use to make your program appear much like other programs that run under Windows. Take menus for example. Menus appear at the top of almost all programs that runs in Windows. Look at the top of this browser window. The menu starts with “File”, followed by “Edit, then “View”, and ends with “Help”. What goes inside of these boxes are commands that the browser program executes.

Windows manages menus for you. All you have to do is to define what items go into a menu, and what action Windows is to take when the user activates a menu item. A menu is actually a resource, just like an icon. So, to define the menu, create one using the Resource View just like you did when you created the icon in the last lesson. You can then use the customized editing tools in the development system to define all the particulars of the menu.

More nuts and bolts: Menus are described in the *.rc file with a special language. By editing a menu in the development system, you are changing the *.rc file. All information about the menu is maintained in the *.rc file. This is different than editing an icon. A *.rc file refers to the name of the icon file, but doesn’t maintain the actual data for the icon in the *.rc file. At compile time, all resource information is encoded into a *.res file. And then at link time, all the information in the *.res file is put into the *.exe file.

Materials for this Lesson: Download.
Homework

Item

Time

Description

1 20 Min Create a menu from the Resource View. Make its ID symbol name to be IDR_MAINMENU. Build it so that there are two main drop downs with the names “File” and “About”. In “File”, there should be three commands: “Red Background”, “Blue Background”, and “Exit”. In “About” there should be “Who?”.
2 5 Mins Add a separator in the “File” part of your menu. The separator should separate the commands of “Red Background” and “Blue Background” from “Exit”. Then, Rebuild your program. The menu should now be a resource in your exe file.
3 2 Mins You must now incorporate the menu in your code. Menus are specified when a window is created with CreateWindow(). CreateWindow() is called in your base class, mcBasicWindow. This presents a design challenge… Should you change the base class to incorporate a menu for your windows, or should you override the creation of windows in a derived class, and put this new functionality in your derived class? Since a menu is typically a basic feature of a window, I recommend that you do this in your base class.
4 20 Mins Change your Create() function in mcBasicWindow to accept a third argument. Make the argument an integer, to accept the menu ID. In the revised create function, you will need to call LoadMenu() to retrieve the menu resource out of the exe file. LoadMenu() will return a handle to the menu that you can use with CreateWindow(). Calling LoadMenu() will require converting the ID number to something Windows can use with MAKEINTRESOURCE(). Read about these Windows functions in the documentation. Note that at some point you will have to call DestroyMenu() when you are done with the menu.
5 10 Mins Now that you have an understanding of the requirements to use your menu, add code to Create() in mcBasicWindow, to get a handle to the menu with the ID number that is given to the Create() function. Then, give this menu handle to the CreateWindow() function call.
6 10 Mins Note that because you will need to call DestroyMenu() on the menu handle when the window is destroyed, you will need to store the menu handle as a member of your mcBasicWindow. When your destructor runs for mcBasicWindow, you need to call DestroyMenu(). Include all the code to do so now.
7 10 Mins Recompile your entire program. Everything should compile accept your mcTopLevelWindow.cpp, since it is using the old Create() with two arguments instead of three. One good style of programming is to not break what already works (at least without very good reason.) This can be accomplished even though you added a the third argument to Create() by using a default value for the new argument. Set the ID number to zero in the prototype for mcBasicWindow::Create(). That is, the prototype in mcBasicWindow.h should be something like:

void Create(HWND hParent, RECT rWindow, int iMenuID = 0);

8 10 Mins Now, your entire program should compile without errors. But, you probably didn’t rewrite mcBasicWindow::Create() to accept a zero for the menu ID. Add code to check for zero, and if zero is found, avoid calling LoadMenu(), and instead just set the menu handle to zero. If the menu handle is zero, don’t try to destroy it either, so your destructor might need to change as well.
9 5 Mins At this point, your program should compile and work as it did before. Test that it does.
10 5 Mins Okay, so now lets cause your new menu to appear… Simply change the call to create the window in mcTopLevelWindow by adding a third argument. The value for the argument is IDR_MAINMENU. That symbol is defined in “resource.h”, so include “resource.h” in McTopLevelWindow.cpp.
11 5 Mins Rebuild your program and run it. Do menus appear in your windows? Do they have all the items that you defined? Do the items do anything? Why not? If you got a menu to display – congratulations! In the next lesson we will make the menu items do something.