In the SDI app I am working on, I needed to be able to insert a new submenu
in the apps main menu based on the currently selected object. (My app uses
the nested splitter code found elsewhere on CodeGuru to provide multiple
views into a selected sound on an advanced MIDI soundcard). I found no
information on how to do it, so after a bit of trial and error I came up
with the technique shown in the following code. Please note that this code
is NOT directly reusable; but it should give you an idea of what needs to
be done. The submenus are all contained in a separate menubar,
IDR_OBJECT_MENUS; everything else should be clear to the experienced MFC
user :’)
// Add a an additional popup menu to the main menu which is
// specific to the currently selected object type. If pViewClass is NULL,
// no menu is added.
void CMainFrame::AddViewMenu(CRuntimeClass* pViewClass)
{
const int INSERT_POSITION = 3;
const int DEFAULT_MENU_COUNT = 6; // INCOMPLETE - change when test menu is
removed!
enum { PROGRAM_MENU, LAYER_MENU, KEYMAP_MENU, SAMPLE_MENU };
CMenu* pMenu = GetMenu();
ASSERT(pMenu->GetMenuItemCount() == DEFAULT_MENU_COUNT
|| pMenu->GetMenuItemCount() == DEFAULT_MENU_COUNT + 1);
// If there is already an extra menu present, remove it
if (pMenu->GetMenuItemCount() == DEFAULT_MENU_COUNT + 1)
pMenu->RemoveMenu(INSERT_POSITION, MF_BYPOSITION);
// Now based on the specific view type, add the appropriate menu
int iMenuToAdd = -1;
if (pViewClass == RUNTIME_CLASS(CProgramView))
iMenuToAdd = PROGRAM_MENU;
else if (pViewClass == RUNTIME_CLASS(CLayerView))
iMenuToAdd = LAYER_MENU;
else if (pViewClass != NULL)
ASSERT(FALSE); // INCOMPLETE - other types!
if (iMenuToAdd != -1)
{
// get the menu to add
CMenu objectMenu;
objectMenu.LoadMenu(IDR_OBJECT_MENUS);
CMenu* pPopupMenu = objectMenu.GetSubMenu(iMenuToAdd);
ASSERT(pPopupMenu != NULL);
// get its string - *^&) Windows can't figure it out for itself
CString strMenuItem;
objectMenu.GetMenuString(iMenuToAdd, strMenuItem, MF_BYPOSITION);
// Add it
VERIFY(pMenu->InsertMenu(INSERT_POSITION, MF_BYPOSITION | MF_POPUP,
(UINT)pPopupMenu->GetSafeHmenu(), strMenuItem));
// remove from the other menu!
objectMenu.RemoveMenu(iMenuToAdd, MF_BYPOSITION);
}
DrawMenuBar();
}