void CMainWindow::OnColor ()
{
UINT nID = (UINT) LOWORD (GetCurrentMessage ()->wParam);
m_nCurrentColor = nID _ ID_COLOR_RED;
}
This approach works just fine as long as the command IDs constitute a contiguous range beginning with ID_COLOR_RED, but it''''s an imperfect solution because it relies on the value of wParam. If the meaning of the wParam parameter accompanying WM_COMMAND messages changes in a future release of Windows (as it did between Windows 3.1 and Windows 95), you might have to modify this code to get it to work properly. And even though you''''ve reduced the number of command handlers from three to one, you''''re still adding three separate entries to the class''''s message map at a cost of 24 bytes each.
A better solution is the MFC ON_COMMAND_RANGE macro, which maps a range of contiguous command IDs to a common handling function. Assuming ID_COLOR_RED is the lowest value in the range and ID_COLOR_BLUE is the highest, ON_COMMAND_RANGE allows you to rewrite the code for the Color menu like this:
// In CMainWindow''''s message map
ON_COMMAND_RANGE (ID_COLOR_RED, ID_COLOR_BLUE, OnColor)
void CMainWindow::OnColor (UINT nID)
{
m_nCurrentColor = nID _ ID_COLOR_RED;
}
When OnColor is called because the user chose an item from the Color menu, nID contains ID_COLOR_RED, ID_COLOR_GREEN, or ID_COLOR_BLUE. One simple statement sets m_nCurrentColor to the proper value, no matter which menu item was selected.
Updating the Items in a Menu
In many applications, menu items must be constantly updated to reflect internal states of the application or its data. When a color is selected from a Color menu, for example, the corresponding menu item should be checked or bulleted to indicate which color is currently selected. An application that features an Edit menu with Cut, Copy, and Paste commands should disable the Cut and Copy menu items when nothing is selected and disable the Paste menu item when the clipboard is empty. Menus are more than just lists of commands. Deployed properly, they provide visual feedback to the user about the current state of the application and make clear what commands are (and are not) available at any given moment.
Windows programmers have traditionally taken one of two approaches to keeping menu items up to date. The first approach is illustrated by the following code sample, which is a modified version of the OnColor function presented in the previous section:
void CMainWindow::OnColor (UINT nID)
{
CMenu* pMenu = GetMenu ();
pMenu->CheckMenuItem (m_nCurrentColor + ID_COLOR_RED, MF_UNCHECKED);
pMenu->CheckMenuItem (nID, MF_CHECKED);
m_nCurrentColor = nID _ ID_COLOR_RED;
}
In this example, the Color menu is updated the moment an item is selected. First CMenu::CheckMenuItem is called with an MF_UNCHECKED flag to uncheck the item that''''s currently checked. Then CheckMenuItem is called with an MF_CHECKED flag to place a check mark by the item that was just selected. The next time the Color menu is pulled down, the check mark will identify the current color.
The second approach is to move the code that updates the menu to an OnInitMenuPopup handler that''''s activated in response to WM_INITMENUPOPUP messages. This strategy positions the check mark each time the Color menu is pulled down, just before the menu is actually displayed. OnInitMenuPopup receives three parameters: a CMenu pointer referencing the submenu that''''s about to be displayed, a UINT value holding the submenu''''s 0-based index in the top-level menu, and a BOOL value that''''s nonzero if the message pertains to the system menu instead of a submenu. Here''''s what an OnInitMenuPopup handler for the Color menu might look like. COLOR_MENU_INDEX is an index specifying the Color menu''''s position in the top-level menu:
// In CMainWindow''''s message map
ON_WM_INITMENUPOPUP ()
void CMainWindow::OnInitMenuPopup (CMenu* pPopupMenu, UINT nIndex,
BOOL bSysMenu)
{
if (!bSysMenu && (nIndex == COLOR_MENU_INDEX)) {
pPopupMenu->CheckMenuItem (ID_COLOR_RED, MF_UNCHECKED);
pPopupMenu->CheckMenuItem (ID_COLOR_GREEN, MF_UNCHECKED);
pPopupMenu->CheckMenuItem (ID_COLOR_BLUE, MF_UNCHECKED);
pPopupMenu->CheckMenuItem (m_nCurrentColor + ID_COLOR_RED,
MF_CHECKED);
}
}
This method is more robust than the first because it decouples the code that processes commands from the code that updates the menu. Now any function anywhere in the application can change the drawing color, and the menu will be updated automatically the next time it''''s displayed.
MFC provides a similar but more convenient mechanism for keeping menu items updated. Through ON_UPDATE_COMMAND_UI macros in the message map, you can designate selected member functions to serve as update handlers for individual menu items. When the user pulls down a menu, MFC traps the ensuing WM_INITMENUPOPUP message and calls the update handlers for all the items in the menu. Each update handler is passed a pointer to a CCmdUI object whose member functions can be used to modify the menu item. And because the CCmdUI class isn''''t specific to any particular type of user interface (UI) element, the same update handler that serves a menu item can serve toolbar buttons and other UI objects, too. Abstracting UI updates in this way simplifies the program logic and helps make an application independent of the operating system it''''s written for.
Here''''s how to rewrite the code for the Color menu to take advantage of update handlers:
// In CMainWindow''''s message map
ON_COMMAND_RANGE (ID_COLOR_RED, ID_COLOR_BLUE, OnColor)
ON_UPDATE_COMMAND_UI (ID_COLOR_RED, OnUpdateColorRed)
ON_UPDATE_COMMAND_UI (ID_COLOR_GREEN, OnUpdateColorGreen)
ON_UPDATE_COMMAND_UI (ID_COLOR_BLUE, OnUpdateColorBlue)
void CMainWindow::OnColor (UINT nID)
{
m_nCurrentColor = nID _ ID_COLOR_RED;
}
void CMainWindow::OnUpdateColorRed (CCmdUI* pCmdUI)
{
pCmdUI->SetCheck (m_nCurrentColor == 0);
}
void CMainWindow::OnUpdateColorGreen (CCmdUI* pCmdUI)
{
pCmdUI->SetCheck (m_nCurrentColor == 1);
}
void CMainWindow::OnUpdateColorBlue (CCmdUI* pCmdUI)
{
pCmdUI->SetCheck (m_nCurrentColor == 2);
}
ON_UPDATE_COMMAND_UI connects menu items to update handlers just as ON_COMMAND connects menu items to command handlers. Now selecting a color from the Color menu will activate CMainWindow::OnColor, and before the Color menu is displayed, each item''''s update handler will be called. The handlers shown here do their updating by calling CCmdUI::SetCheck to check or uncheck the corresponding menu item. Called with a nonzero value, SetCheck adds a check mark to the corresponding menu item; called with a 0, it displays no check mark.
SetCheck is just one of the CCmdUI methods that you can use to update a menu item. The following table shows a complete list, along with a description of each function''''s effect on a menu item.
| Function |
Description |
CCmdUI::Enable
Enables or disables a menu item
CCmdUI::SetCheck
Checks or unchecks a menu item
CCmdUI::SetRadio
Bullets or unbullets a menu item
CCmdUI::SetText
Changes the text of a menu item
SetRadio works like SetCheck but adds or removes a bullet instead of a check mark. SetRadio is one of those MFC functions that doesn''''t have a direct counterpart in the Windows API; the framework does some work behind the scenes to allow menu items to be bulleted rather than checked. Ideally, you''''d use a bullet to indicate which item in a group of mutually exclusive menu items is currently selected and a check mark to indicate whether a feature is on or off. (In practice, check marks are frequently used for both.) Enable enables or disables a menu item, and SetText allows you to change the text of the menu item on the fly.
Update Ranges
For updating groups of menu items with a single update handler, MFC provides the ON_UPDATE_COMMAND_UI_RANGE macro, which is to ON_COMMAND_RANGE as ON_UPDATE_COMMAND_UI is to ON_COMMAND. To understand how ON_UPDATE_COMMAND_UI_RANGE is used, let''''s revisit the Color menu and assume that it contains eight color choices: black, blue, green, cyan, red, magenta, yellow, and white, in that order. The corresponding menu item IDs are ID_COLOR_BLACK through ID_COLOR_WHITE. Let''''s also assume that we want to put a bullet by the current color. Here''''s the most concise way to do it.
// In CMainWindow''''s message map
ON_COMMAND_RANGE (ID_COLOR_BLACK, ID_COLOR_WHITE, OnColor)
ON_UPDATE_COMMAND_UI_RANGE (ID_COLOR_BLACK, ID_COLOR_WHITE,
OnUpdateColorUI)
void CMainWindow::OnColor (UINT nID)
{
m_nCurrentColor = nID _ ID_COLOR_BLACK;
}
void CMainWindow::OnUpdateColorUI (CCmdUI* pCmdUI)
{
pCmdUI->SetRadio (pCmdUI->m_nID - ID_COLOR_BLACK ==
m_nCurrentColor);
}
m_nID is a public data member of CCmdUI that holds the ID of the menu item for which the update handler was called. By comparing m_nID minus ID_COLOR_BLACK to m_nCurrentColor and passing the result to SetRadio, you can ensure that only the current color is bu
上一页 [1] [2] [3] [4] 下一页
[常用软件][设计]Flashation Menu Builder 菜单软件教学 [Delphi程序]Create a menu item into the Delphi menu
[VB.NET程序]WAP Basics [VB.NET程序]Event-Handling Basics
[VB.NET程序]Internet Basics [Web开发]利用JavaScript和CSS制作浮动menu
[MySql]linux下的c 编程------控制台下的menu