DYNAMENU Sample: Dynamically Updates Menus
The DYNAMENU sample illustrates dynamic modification of menus and status bars regardless of whether handling commands are known at compile time. DYNAMENU illustrates the following capabilities:
Dynamically updating the list of items in a menu.
Implementing the equivalent of ON_COMMAND and ON_UPDATE_COMMAND_UI handlers for menu commands whose IDs are not known at compile time. This illustration can be applied to more complex cases, such as user-configurable menus.
Updating the status bar command prompt for commands whose IDs are not known at compile time.
This sample code is provided to illustrate a concept and should not be used in applications or Web sites, as it may not illustrate the safest coding practices. Microsoft assumes no liability for incidental or consequential damages should the sample code be used for purposes other than as intended.
To get samples and instructions for installing them:
On the Visual Studio Help menu, click Samples.
For more information, see Visual Studio Samples.
The most recent version and complete list of samples is available online from the Visual Studio 2008 Samples page.
You can also locate samples on your computer's hard disk. By default, samples and a Readme file are copied into a folder under \Program Files\Visual Studio 9.0\Samples\. For Express editions of Visual Studio, all samples are located online.
To build and run the DYNAMENU sample
Open the solution dynamenu.sln.
On the Build menu, click Build.
On the Debug menu, click Start Without Debugging.
DYNAMENU initially displays a window with the text: "This text is displayed in the current color." You can change the color of the displayed text by selecting one of four items initially offered in the Color menu: Black, Red, Purple, or Blue.
To exercise the dynamic menu updating feature of DYNAMENU, click ChangeOptions on the Color menu, which opens a Change Color Options dialog box. Check boxes for Black, Red, Purple, and Blue allow you to choose which colors are dynamically offered in the Color menu. For example, if you clear Red and Purple and return to the Color menu, only Black and Blue items will be offered in the menu.
Note how the status bar displays, for example, "Set current color text to Black," when the focus is on the Black item in the Color menu.
Class CDynaMDIChildWnd in Mdichild.cpp implements dynamic updating of items in the Color menu. When the list of available colors is updated, or when then MDI child window is activated, the CDynaMDIChildWnd::RefreshColorMenu function calls CMenu::DeleteMenu to delete each color item from the menu, and then adds the currently available colors to the menu using CMenu::AppendMenu.
DYNAMENU could have been implemented by reserving a fixed list of command IDs for the colors: ID_COLOR_BLACK, ID_COLOR_RED, and so on. In such a case, ON_COMMAND and ON_UPDATE_COMMAND_UI handlers could have been implemented for the color commands as usual. This would be the most straightforward way to implement DYNAMENU.
However, for sake of illustration, DYNAMENU does not use fixed command IDs. Instead, DYNAMENU dynamically assigns command IDs not known or associated with the menu items at compile time. This illustration can be applied to more complex cases, such as user-configurable menus.
The equivalent of ON_COMMAND and ON_UPDATE_COMMAND message map handling is implemented in the document's override of CCmdTarget::OnCmdMsg. If the OnCmdMsg function is called with a NULL pointer for the AFX_CMDHANDLERINFO* parameter, this means that no message map entry has been found for the command. In this case, the override of OnCmdMsg checks whether the command ID, passed as the first parameter, is one of the dynamically assigned command IDs for the color menu items. If so, the override calls either a command handler (DoSelectColor) or command user interface handler (DoUpdateSelectColor), depending on whether the second parameter passed to OnCmdMsg is the MFC-defined CN_COMMAND or CN_UPDATE_COMMAND_UI.
In DYNAMENU, the MDI child window (CDynaMDIChildWnd) owns the status bar. The default implementation of CFrameWnd::GetMessageString uses the currently shown command ID (for the item that currently has the focus in the menu) to get the corresponding string resource for the command and display it in the first pane of the status bar. DYNAMENU overrides GetMessageString to display a command prompt for the dynamically defined commands.
This sample demonstrates the following keywords:
AfxFormatString1; AfxGetMainWnd; CCmdTarget::OnCmdMsg; CDialog::DoModal; CDialog::OnInitDialog; CDocument::GetFirstViewPosition; CDocument::GetNextView; CDocument::OnNewDocument; CDocument::UpdateAllViews; CFrameWnd::Create; CFrameWnd::GetActiveDocument; CFrameWnd::GetMessageString; CFrameWnd::LoadFrame; CMenu::AppendMenu; CMenu::DeleteMenu; CMenu::GetMenuItemCount; CMenu::GetMenuItemID; CMenu::GetSubMenu; CObject::AssertValid; CObject::Dump; CObject::Serialize; CString::LoadString; CView::DoPreparePrinting; CView::GetDocument; CView::OnBeginPrinting; CView::OnDraw; CView::OnEndPrinting; CView::OnPreparePrinting; CWinApp::AddDocTemplate; CWinApp::EnableShellOpen; CWinApp::InitInstance; CWinApp::LoadStdProfileSettings; CWinApp::RegisterShellFileTypes; CWnd::CenterWindow; CWnd::DoDataExchange; CWnd::GetClientRect; CWnd::GetDlgItem; CWnd::GetMenu; CWnd::GetParentFrame; CWnd::OnCreate; CWnd::SetWindowText; CWnd::ShowWindow; CWnd::UpdateWindow; DragAcceptFiles; DrawText; LoadBitmap; RGB; SetBkMode; SetTextColor
Some samples, such as this one, have not been modified to reflect the changes in the Visual C++ wizards, libraries, and compiler, but still demonstrate how to complete your desired task.