Today you will learn
Back when the first computer terminals were introduced and users began using computer software, even on large mainframe systems software developers found the need to provide the users with some sort of menu of the functions that the computer could perform. These early menus were crude by today's standards and were difficult to use and navigate. Menus have progressed since then; they've become standardized in how they are used and easy to learn.
The software designers that first came up with the idea of a graphical user interface (GUI) planned to make computer systems and applications easier to learn by making everything behave in a consistent manner. Menus used for selecting application functionality were one part of the GUI design that could be more easily learned if they all worked the same. As a result, a number of standard menu styles were developed.
The first menu styles that were standardized are the pull-down and cascading menus. These are the menus with the categories all listed in a row across the top of the application window. If you select one of the categories, a menu drops down below the category, with a number of menu entries that can be selected to trigger various functions in the application.
A variation on this menu style is the cascading menu, which has another submenu that opens to the right of a menu entry. This submenu is similar to the pull-down menu, with a number of entries that trigger application functions. The menu designers placed no limit on how many cascading menus can be strung together, but it quickly became clear to most developers that more than two cascading levels is a little unwieldy.
Eventually, a third style of menu was developed, called a pop-up or context menu--a menu that pops up in the middle of the application area, floating freely above the application work area. This is also called a context menu because the specific menu that pops up is dependent on the selected object or workspace area where the cursor or mouse pointer is.
When users began working with keyboard-intensive applications, such as word processors, it was discovered that taking your hands off the keyboard to use the mouse to make menu selections dramatically reduced productivity. Software designers decided that they needed to add keyboard shortcuts for the various menu entries (especially the most frequently used menu options). For this reason, keyboard shortcuts (accelerators) and hotkeys were added.
Hotkeys are letters that are underlined in each menu entry. If you press the Alt key with the underlined letter, you can select the menu entry that contains the underlined letter. This is a means of navigating application menus without taking your hands off the keyboard.
For more advanced users, application designers added keyboard shortcuts, or accelerators. An accelerator is a single key combination that you can press to trigger an application function instead of having to navigate through the application menus. This allows advanced users to avoid the overhead of using menus for the most common application functions. To enable users to learn what accelerators are available in an application, the key combination is placed on the menu entry that it can be used to replace, positioned at the right edge of the menu window.
Although there are no standards in how menus are designed, there are a number of conventions for how they are designed and organized. All these conventions are available in Windows Interface Guidelines for Software Design, published by Microsoft for use by Windows software developers. The purpose of this publication is to facilitate the development of consistent application behaviors, which will help accomplish one of the primary goals behind the development of GUI systems. The conventions are as follows:
Menus are defined as a resource in Visual C++ applications. Because they are a resource, you can design menus in the Visual C++ editor through the Resource View tab on the workspace pane. When you first create a dialog-style application, there won't be a menu folder in the resource tree, but you can change that.
NOTE: Various aspects of Windows applications are considered to be resources, including window layouts, menus, toolbars, images, text strings, accelerators, and so on. All these features are organized in what is known as a resource file, which is used by the Visual C++ compiler to create these objects from their definitions. The resource file is a text file with an .rc filename extension and contains a textual description of all the various objects, including IDs, captions, dimensions, and so on.
Some resources, such as images and sounds, cannot be described in text, but have to be stored in a binary format. These resources are stored in individual files, with the filenames and locations included in the resource file.
Creating a menu is not difficult. You will follow several steps:
For the example in this chapter, you will create a simple dialog-style application that contains a single button and a menu. To create your application, do the following:
NOTE: If you don't remember how to add the OnOK function, review the section "Closing the Application" on Day 2, "Using Controls in Your Application," for an example.
Now that you have the basic application built, it's time to start creating a menu for the application. To create a menu, you will first add a menu resource to your project. When you add the resource, Visual C++ automatically invokes the Menu Designer, which allows you to customize the menu. The following steps show you how to add and customize a menu:
FIGURE 6.1. The Insert Resource dialog.
FIGURE 6.2. An empty menu.
At this point, you have created the menu resource and you are ready to customize it by adding menu items. To add a menu item, follow these steps:
NOTE: You are in the menu Properties dialog to specify the text that the user will see on the menu bar while the application is running. Because the Pop-up check box is checked (by default on any menu items on the top-level menu bar), this menu element doesn't trigger any application functionality and thus doesn't need to have an object ID assigned to it.
NOTE: This time in the menu Properties dialog, you not only specify the text that the user will see when the menu is opened from the menu bar, but you also specify the object ID that will be used in the event message handler to determine what function receives each of the menu events.
At this point you have created a menu with a single menu item. You can continue to add menu items by repeating steps 3 and 4 of the preceding list for each of the highlighted areas. You can also add separators onto the menu. A separator is a dividing line that runs across the menu to separate two functional areas of menu selections. To add a separator, perform the following steps:
FIGURE 6.3. Specifying a menu separator.
To complete your sample program, follow the same steps I just described to add an Exit item to your File menu and a second menu called Help with one menu item called About. The following steps, which resemble the preceding list of steps, walk you through adding these additional items:
At this point, your menu is created; however, it is not attached to your application.
You now have a menu that you can use in your application. If you compile and run your application at this point, however, the menu doesn't appear. You still need to attach the menu to your dialog window. You can attach a menu by following these steps:
FIGURE 6.4. Attaching the menu to the dialog window.
If you compile and run your application, you find that the menu is attached to the application dialog, as shown in Figure 6.5. You can select menu entries as you do with any other Windows application--with one small difference. At this point, when you select one of the menu entries, nothing happens. You still need to attach functionality to your menu.
FIGURE 6.5. The menu is now part of the application dialog.
Now that you have a menu as part of your application, it sure would be nice if it actually did something. Well, before your menu can do anything, you have to tell it what to do, just like everything else in your Visual C++ applications. To attach some functionality to your menu, follow these steps:
FIGURE 6.6. The menu is now part of the application.
FIGURE 6.7. The Select Class dialog.
For the menu elements that you want to use to trigger new functions in your application, you can add event-handler functions through the Class Wizard, just as you can with controls that you place on the dialog window.
For this example, add a function for the IDM_FILE_HELLO object (the Hello menu) on the COMMAND event message. Name the function OnHello and add the code in Listing 6.1 to the function.
1: void CMenusDlg::OnHello() 2: { 3: // TODO: Add your command handler code here 4: 5: /////////////////////// 6: // MY CODE STARTS HERE 7: /////////////////////// 8: 9: // Display a message for the user 10: MessageBox("Hello there", "Hello"); 11: 12: /////////////////////// 13: // MY CODE ENDS HERE 14: ///////////////////////
15: }
NOTE: The COMMAND event message is the message that is passed to the application window when a menu entry is selected. Placing a function on this event message has the same effect as placing a function on the menu entry selection.
You can call existing event handlers from menu elements by adding the existing function to the menu COMMAND event. You can do this by adding a function to the menu object ID and then specifying the existing function name instead of accepting the suggested function name.
To reuse the OnExit function for the Exit menu element, reopen the Menu Designer and then reopen the Class Wizard. When the Class Wizard is displayed, add a function for the IDM_FILE_EXIT object on the COMMAND event message. Do not accept the default function name presented to you by the Class Wizard. Enter the function name OnExit. This automatically attaches the existing OnExit function that you created with your Exit button earlier.
To round out your example's functionality, add a function to the ID_HELP_ABOUT object on the COMMAND event message. Edit the function as in Listing 6.2.
1: void CMenusDlg::OnHelpAbout() 2: { 3: // TODO: Add your command handler code here 4: 5: /////////////////////// 6: // MY CODE STARTS HERE 7: /////////////////////// 8: 9: // Declare an instance of the About window 10: CAboutDlg dlgAbout; 11: 12: // Show the About window 13: dlgAbout.DoModal(); 14: 15: /////////////////////// 16: // MY CODE ENDS HERE 17: ///////////////////////
18: }
You attached the File | Exit menu entry to an existing function that closes the application. On the File | Hello, you added a new function that called the MessageBox function to display a simple message to the user. With Help | About, you added another function that declared an instance of the About dialog window and called its DoModal method.
If you compile and run your application, you find that all the menu entries are working. If you select Help | About, as shown in Figure 6.8, you see the application About dialog (see Figure 6.9). If you select File | Hello, you see a Hello there message box, as shown in Figure 6.10. And if you select File | Exit, your application closes.
FIGURE 6.8. The Help | About menu entry.
FIGURE 6.9. The About dialog.
FIGURE 6.10. The Hello there message box.
Most Windows applications have what are called either pop-up or context menus, which are triggered by the user right-clicking an object. These are called pop-up menus because they pop up in the middle of the application area, not attached to a menu bar, the window frame, or anything else on the computer screen (not counting the mouse pointer). These menus are often referred to as context menus because the contents of a menu depend on the context in which it is opened; the elements available on the menu depend on what objects are currently selected in the application or what the mouse pointer is positioned over.
To provide a pop-up menu in your application, you have two approaches available. You can either design a menu specifically for use as a pop-up menu, or you can use one of the pull-down menus from the primary menu that you have already designed. If you design a menu specifically for use as a pop-up menu, you will need to skip the top-level, menu bar element by placing a space or some other text in the caption, knowing that it will not be seen. You will see how this works when you build a custom menu specifically for use as a pop-up menu on Day 11, "Creating Multiple Document Interface Applications," in the section "Adding a Context Menu."
Every drop-down portion of a menu can also be used as a pop-up menu. To use it in this way, you must get a handle to the submenu (the drop-down menu) and then call the TrackPopupMenu function on the submenu. The rest of the pop-up menu functionality is already covered in the other menu building and coding that you have already done. To add a pop-up menu to your application, follow these steps:
NOTE: There are two dialog event messages that you can use to trigger your context menu. The event that you'd expect to use is the WM_RBUTTONDOWN event, which is triggered by the user right-clicking. The other event that can (and should) be used is the WM_CONTEXTMENU event, which is intended for use specifically to trigger a context menu. This event is triggered by a couple user actions: One of these is the release of the right mouse button, and another is the pressing of the context menu button on one of the newer Windows-enabled keyboards.
1: void CMenusDlg:: OnContextMenu(CWnd* pWnd, CPoint point) 2: { 3: // TODO: Add your message handler code here 4: 5: /////////////////////// 6: // MY CODE STARTS HERE 7: /////////////////////// 8: 9: // Declare local variables 10: CMenu *m_lMenu; // A pointer to the menu 11: CPoint m_pPoint; // A copy of the mouse position 12: 13: // Copy the mouse position to a local variable 14: m_pPoint = point; 15: // Convert the position to a screen position 16: ClientToScreen(&m_pPoint); 17: // Get a pointer to the window menu 18: m_lMenu - GetMenu(); 19: // Get a pointer to the first submenu 20: m_lMenu = m_lMenu->GetSubMenu(0); 21: // Show the Popup Menu 22: m_lMenu->TrackPopupMenu(TPM_CENTERALIGN + TPM_LEFTBUTTON, 23: m_pPoint.x, m_pPoint.y, this, NULL); 24: 25: /////////////////////// 26: // MY CODE ENDS HERE 27: ///////////////////////
28: }
In Listing 6.3, the first thing that you did was make a copy of the mouse position. This mouse position is a relative position within the window area. It must be converted to an absolute position on the entire screen area for displaying the pop-up menu. If you don't convert the position coordinates, you can't predict where your pop-up menu will appear.
After you convert the position to an absolute position, you get a pointer to the window menu. This pointer should always be a local pointer within the function where you are going to use it because the location of the menu might change as the application runs. From the menu pointer, you next get a pointer to the first drop-down menu (submenu numbering begins with 0, like just about everything else in C/C++). After you have a pointer to the submenu, you can treat it as a regular CMenu class instance.
The final piece in this puzzle is the call to the CMenu member function TrackPopupMenu. This function takes five arguments and uses them to determine where and how to show the pop-up menu. The first argument is a combination of two flags. The first flag, TPM_CENTERALIGN, centers the pop-up menu on the mouse point. You can also use TPM_LEFTALIGN or TPM_RIGHTALIGN instead. These flags line up the left or right edge of the pop-up menu with the mouse position. The second part of this flag combination is TPM_LEFTBUTTON, which makes the pop-up menu trigger from the left mouse button. You can also use TPM_RIGHTBUTTON to make the menu trigger from the right mouse button.
The second and third arguments to the TrackPopupMenu function specify the screen position for the pop-up menu. This is the absolute position on the screen, not a relative position within the window area. The fourth argument is a pointer to the window that receives the menu command messages. The final argument is a rectangle that the user can click without closing the pop-up menu. By passing NULL, you specify that if the user clicks outside the pop-up menu, the menu closes. This code enables you to include a pop-up menu in your application, as shown in Figure 6.11.
FIGURE 6.11. The pop-up menu in action.
One of the original keyboard shortcuts for selecting menu entries were accelerator keys. As mentioned earlier in the chapter, accelerator keys are specific key combinations, usually the Ctrl key combined with another key, or function keys, that are unique within the entire application. Each of these key combinations triggers one menu event function.
The way that accelerator keys work is similar to the way menus work. They are also an application resource that is defined in a table in the resource tab of the workspace pane. Each table entry has an object ID and a key code combination. After you define the accelerators, you can attach functionality to the object IDs. You can also assign accelerator entries the same object ID as the corresponding menu entry so that you have to define only a single entry in the application message map.
After you define all your accelerator keys, you can add the key combination to the menu entry so that the user will know about the accelerator key combination. Add \t to the end of the menu entry caption, followed by the key combination. The \t is replaced in the menu display by a tab, which separates the menu caption from the accelerator key combination.
Unfortunately, accelerator keys don't work in dialog-style windows, so you cannot add them to today's application. You will learn how to attach accelerator keys to menus in a few days when you learn about single and multi-document interface style applications.
Today you learned about menus in Visual C++ applications. You learned how to use the tools in Visual C++ to create a menu for use in your application and then how to attach the menu to a window in your application. After you had the menu attached to your window, you learned how to attach functionality to the various menu entries. Later in the day, you learned how you can use a portion of your menu as a pop-up, or context, menu. Finally, you learned how accelerator keys are added to most applications.
The Workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to provide you with experience in using what you've learned. The answers to the quiz questions are provided in Appendix B, "Answers."
© Copyright, Macmillan Computer Publishing. All rights reserved.