|
In this section, we'll describe programming with wxMenu, a simple way to present commands without taking up a lot of display space. In the next section, we'll look at how menus are used in menu bars. wxMenuA menu is a list of commands that pops up either from a menu bar or on an arbitrary window, often as a "context menu" invoked by clicking the right mouse button (or equivalent). A menu item can be a normal command, or it can have a check or radio button next to the label. A menu item in a disabled state won't respond to commands. A special kind of menu item can display a visual indication of a further pull-right menu, and this can be nested to an arbitrary level. Another kind of menu item is the separator, which simply displays a line or space to indicate separation between two groups of items. Figure 4-33 shows a typical menu with normal, check, and radio items and a submenu. Figure 4-33. A typical menuThe example shows the use of both mnemonics and shortcuts. A mnemonic is a highlighted key in a label (such as the "N" in "New") that can be pressed when the menu is shown to execute that command. Specify a mnemonic by preceding the letter with an ampersand ("&"). A shortcut (or accelerator) is a key combination that can be used when the menu is not shown, and it is indicated in a menu item by a key combination following a tab character. For example, the New menu item in the example was created with this code: menu->Append(wxID_NEW, wxT("&New...\tCtrl+N")); For more on creating accelerators via menu items or by programming with wxAcceleratorTable, please see Chapter 6. Check and radio items automatically update their state; that is, when the user toggles a check item, it will be shown in the reverse state when the menu is next popped up. Similarly, consecutive radio items form a group and when one item is checked, the other items in the group are unchecked. You can also set these states yourself, for example from a user interface update event handler (see Chapter 9). You can create a menu and show it at a particular point in a window using wxWindow::PopupMenu, for example: void wxWindow::OnRightClick(wxMouseEvent& event) { if (!m_menu) { m_menu = new wxMenu; m_menu->Append(wxID_OPEN, wxT("&Open")); m_menu->AppendSeparator(); m_menu->Append(wxID_EXIT, wxT("E&xit")); } PopupMenu(m_menu, event.GetPosition()); } Events are sent to the menu itself before travelling up the hierarchy of windows starting from the window the popup menu was shown on. PopupMenu will cause program flow to "block" at this point, resuming when the user has dismissed the menu. If you want, you can delete and re-create the menu every time it needs to be shown, or you can reuse the same menu. Where possible, use standard wxWidgets identifiers in menus, such as wxID_OPEN, wxID_ABOUT, wxID_PRINT, and so on. You can find a full list of these in Chapter 3. In particular, wxID_ABOUT, wxID_PREFERENCES and wxID_EXIT are interpreted specially on Mac OS X. When used in a menu bar, these menu items are not shown in the menus to which they are appended, but are shown instead in the standard application menu. Thus wxWidgets adapts your menus automatically to Mac OS X conventions, but beware of side effects such as a Help menu with no menu items, or two separators together. See samples/menu in the wxWidgets distribution for a test of most menu functionality, and also see samples/ownerdrw for a demonstration of the use of custom fonts and bitmaps in menu items. wxMenu EventsThere are four different kinds of event associated with wxMenu: wxCommandEvent, wxUpdateUIEvent, wxMenuEvent, and wxContextMenuEvent. Table 4-45 lists the command events, whose handlers take a wxCommandEvent argument. Use these for processing menu commands, either from a pop-up menu or a menu bar on a frame. These are interchangeable with the equivalent toolbar event macros so that events generated from both menus and toolbar buttons can be processed by the same handler.
Table 4-46 lists the event macros for update eventsevents generated by the framework in idle time to give the application a chance to update elements of the UIfor example, enabling or disabling menu items. Although wxUpdateUIEvent applies to all windows, menu event handlers can use them slightly differently than other event handlers: they can call Check and SetText as well as Enable. Check checks or unchecks the menu item, while SetText sets the menu item label, which is useful if the label changes dynamically according to some condition. For example: BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_UPDATE_UI(ID_TOGGLE_TOOLBAR, MyFrame::OnUpdateToggleToolbar) END_EVENT_TABLE() void MyFrame::OnUpdateToggleToolbar(wxUpdateUIEvent& event) { event.Enable(true); event.Check(m_showToolBar); event.SetText(m_showToolBar ? wxT("Show &Toolbar (shown)") : wxT("Show &Toolbar (hidden)")); }
For more on UI update events, please see Chapter 9. Table 4-47 lists the other menu-related events. EVT_CONTEXT_MENU handlers take a wxContextMenuEvent, which is derived from wxCommandEvent and therefore propagates up the parent-child window hierarchy. Use this in preference to intercepting a right mouse button click when you want to show a context menu, and call the event object's GetPosition function to find out where to show the menu.
The remaining macros process wxMenuEvent objects, and these are only sent from a menu bar to its frame. They tell the application when a menu has been opened and closed, and when the user has highlighted a menu item. The default EVT_MENU_HIGHLIGHT handler shows a menu item's help string in the status bar, but you can provide your own handler to do something different. wxMenu Member FunctionsThese are the major wxMenu functions. Append adds a menu item: specify an identifier, a label, a help string, and the kind of item (wxITEM_NORMAL, wxITEM_SEPARATOR, wxITEM_CHECK or wxITEM_ RADIO). You can also use AppendCheckItem and AppendRadioItem to avoid specifying wxITEM_CHECK or wxITEM_RADIO. For example: // Append a normal item menu->Append(wxID_NEW, wxT("&New...\tCtrl+N")); // Append a check item menu->AppendCheckItem(ID_SHOW_STATUS, wxT("&Show Status")); // Append a radio item menu->AppendRadioItem(ID_PAGE_MODE, wxT("&Page Mode")); Another overload of Append enables you to append a submenu, for example: // Append a submenu menu->Append(ID_SUBMENU, wxT("&More options..."), subMenu); Yet another overload of Append enables you to use a wxMenuItem object directly to append an item, and this is the only way to show bitmaps on menus or to set special fonts. For example: // Initialization of bitmaps and font not shown wxBitmap bmpEnabled, bmpDisabled; wxFont fontLarge; // Create a menu item wxMenuItem* pItem = new wxMenuItem(menu, wxID_OPEN, wxT("&Open...")); // Set bitmaps and font pItem->SetBitmaps(bmpEnabled, bmpDisabled); pItem->SetFont(fontLarge); // Finally append it to the menu menu->Append(pItem); Use Insert to insert a menu at a particular position. There are also the functions Prepend, PrependCheckItem, PrependRadioItem, and PrependSeparator for inserting items at the start of the menu. AppendSeparator adds a separator, and InsertSeparator inserts a separator in a given position. For example: // Append a separator menu->AppendSeparator(); Break inserts a break in a menu, causing the next appended item to appear in a new column. Use Check to toggle a check or radio item on or off, passing the menu item identifier and a boolean value. Use IsChecked to get the checked status. Delete deletes a menu item specified by identifier or by wxMenuItem pointer. If the item is a menu, the submenu will not be deleted. Use Destroy if you want to remove and delete a submenu. Remove removes the menu item from a menu without deleting the returned wxMenuItem object. Use Enable to enable or disable a menu item, but rather than doing this explicitly, you may want to use UI update events (see Chapter 9). IsEnabled returns the enabled status. Use FindItem to find an item by label or identifier. Use FindItemByPosition to find an item by position in the menu. GetHelpString and SetHelpString are accessors for the help string associated with a menu item. When the menu is part of a menu bar, wxFrame shows this string in the status bar (if available), as the user highlights each menu item. GetLabel and SetLabel get or set the menu item label, given its identifier. GetMenuCount returns the number of items in the menu. GetMenuItems returns a reference to the list of menu items, a wxMenuItemList object. GetTitle and SetTitle are accessors for the optional title of a menu and are only used for pop-up menus. UpdateUI sends UI update events to the event handler argument or to the owning window if NULL is passed. This is called just before the menu is popped up, but the application may call it at other times if required. |
|