Inserting submenus in an existing SDI menu

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();
}



Comments

  • Don't get messages when adding a submenu from a DLL to the main menu!

    Posted by Legacy on 01/04/2002 12:00am

    Originally posted by: Juergen Suetterlin

    Hy folks,
    I'm trying to modify my main menu out of a dynamically loaded (runtime) DLL.

    My application uses loadlibrary() to load my DLL and can open it. The I call an exported function inside the DLL which adds a submenu to the main menu (procedure found also at codeguru). But when I select the added submenu all sub entries are grayed and the debuggers says this: "Warning: no message line prompt for ID 0x8015." but in the resource the item was alligned to an ID and the ID was alligned to a funciton.

    Can anyone help me?

    J�rgen

    Reply
  • Works fine now thnaks to Julien Roger's fix !!!

    Posted by Legacy on 07/11/2001 12:00am

    Originally posted by: Alf

    In fact it works without it on Win 95 / 98 / NT systems,
    but crashes on Win 2000 / XP systems. With the "fix" it
    works now fine !

    Reply
  • Disable a sub menu at runtime

    Posted by Legacy on 01/10/2001 12:00am

    Originally posted by: Usha

    I want to disable a sub menu at Runtime. Can u help me with that

    Thanks
    usha

    Reply
  • problem with Win95

    Posted by Legacy on 08/12/1999 12:00am

    Originally posted by: latha

    This code works fine with NT but gives an assertion failure when i try to access the sub menu in Win95. Please let me know a solution for the same.

    Reply
  • ON_UPDATE_COMMAND_UI does not work on the inserted menu

    Posted by Legacy on 03/24/1999 12:00am

    Originally posted by: David Geldreich

    If you try to associate an ON_UPDATE_COMMAND_UI on one of the command included in the inserted menu command routing will work but in ON_UPDATE_COMMAND_UI, pCmdUI->Enable(FALSE) will not work.

    It is because things like pCmdUI->m_pMenu->EnableMenuItem(pCmdUI->m_nID, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND); will return -1.

    One solution is to keep a pointer to the inserted menu and do ourself, change pCmdUI->m_pMenu before calling CCmdUI functions.

    Reply
  • This doesn't work

    Posted by Legacy on 12/25/1998 12:00am

    Originally posted by: Vasu Y

    This piece of code doesn't work for me.
    It is adding the new Pop-up menu to the Main menu, but if you click on the newly added pop-up menu, it is giving a Debug-Assertion Failure.

    Can somebody help me out.
    The following is the piece of code.

    CMenu* pMainMenu = pMainFrame->GetMenu();
    short iMenuToAdd;
    iMenuToAdd = 0;
    CMenu objectMenu;
    objectMenu.LoadMenu(IDR_MENU2);
    CMenu* pPopupMenu = objectMenu.GetSubMenu(iMenuToAdd);
    ASSERT(pPopupMenu != NULL);
    short count = 0;
    count = pPopupMenu->GetMenuItemCount();
    // get its string - *^&) Windows can't figure it out for itself
    CString strMenuItem;
    objectMenu.GetMenuString(iMenuToAdd, strMenuItem, MF_BYPOSITION);

    VERIFY(pMainMenu->AppendMenu( MF_POPUP,
    (UINT)pPopupMenu->Detach(), strMenuItem));

    Reply
  • modifying SDI/MDI menus

    Posted by Legacy on 10/13/1998 12:00am

    Originally posted by: Brian Smith

    Instead of
    
    

    VERIFY(pMenu->InsertMenu(INSERT_POSITION, MF_BYPOSITION | MF_POPUP,
    (UINT)pPopupMenu->GetSafeHmenu(), strMenuItem)); // remove from the other menu!
    objectMenu.RemoveMenu(iMenuToAdd, MF_BYPOSITION);

    you could call:

    VERIFY(pMenu->InsertMenu(INSERT_POSITION, MF_BYPOSITION | MF_POPUP,
    (UINT)pPopupMenu->Detach(), strMenuItem));

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • For many organizations, moving enterprise applications to the public cloud can be a very attractive proposition, but planning the best way to move your applications is mission–critical. As an alternative to the costly option of re–architecting the application for a cloud environment, you can follow a "lift and shift" model that's significantly cheaper and almost always a lot quicker. In order to have a successful "lift and shift" migration, read this white paper to learn a few rules you should …

  • Microsoft® Office 365 is a top choice for enterprises that want a cloud–based suite of productivity collaboration applications. With Office 365, you get access to Microsoft™ Office solutions practically anytime, anywhere, on virtually any device. It's a great option for current Microsoft users who can now build on their experience with Microsoft™ solutions while enjoying the flexibility of a cloud-based delivery. But even organizations with no previous investment in Microsoft will find that …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date