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 intended to illustrate a concept, and it shows only the code that is relevant to that concept. It may not meet the security requirements for a specific environment, and it should not be used exactly as shown. We recommend that you add security and error-handling code to make your projects more secure and robust. Microsoft provides this sample code "AS IS" with no warranties.
To get samples and instructions for installing them:
To access samples from Visual Studio
On the Help menu, click Samples.
By default, these samples are installed in drive:\Program Files\Microsoft Visual Studio 10.0\Samples\.
For the most recent version of this sample and a list of other samples, see Visual Studio Samples on the MSDN Web site.
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 Change Options 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.