Menus
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.
wxMenu
A 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 menu

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:
menu->Append(wxID_NEW, wxT("&New...\tCtrl+N"));
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.
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());
}
wxMenu Events
There 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.
EVT_MENU(id, func) | Processes a wxEVT_COMMAND_MENU_SELECTED event, generated by a menu item. |
EVT_MENU_RANGE(id1, id2, func) | Processes a wxEVT_COMMAND_MENU_RANGE event, generated by a range of menu items. |
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.
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)"));
}
EVT_CONTEXT_MENU(func) | Processes the event generated when the user has requested a popup menu to appear by pressing a special key (under Windows) or by right-clicking the mouse. The handler takes a wxContextMenuEvent. |
EVT_COMMAND_CONTEXT_MENU(id, func) | The same as EVT_CONTEXT_MENU, but it takes a window identifier. |
EVT_MENU_OPEN(func) | Handles a wxEVT_MENU_OPEN event, sent when a menu is about to be opened. On Windows, this is only sent once for each navigation of the menu bar. |
EVT_MENU_CLOSE(func) | Handles a wxEVT_MENU_CLOSE event, sent when a menu has just been closed. |
EVT_MENU_HIGHLIGHT(id, func) | Handles a wxEVT_MENU_HIGHLIGHT event, sent when the menu item with the specified id has been highlighted. This is used to show help prompts in a frame's status bar. |
EVT_MENU_HIGHLIGHT_ALL(func) | Handles a wxEVT_MENU_HIGHLIGHT event for any menu identifier. |
wxMenu Member Functions
These 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:
Another overload of Append enables you to append a submenu, 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"));
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:
// Append a submenu
menu->Append(ID_SUBMENU, wxT("&More options..."), subMenu);
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:
// 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);
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.
// Append a separator
menu->AppendSeparator();