1

Is there a way to create dynamic menu items in the menu bar of an MFC applications created with visual studio 2008 style with menus not ribbon, I have plugins that add their menus dynamically how can I add them to that menu??? I see

//this is the menubar that i want to update
CMFCMenuBar       m_wndMenuBar;
ahmedsafan86
  • 1,776
  • 1
  • 26
  • 49

4 Answers4

2

At first you have to create a new submenu. It can be filled by hand or loaded from resources. Then create a new menu button and attach submenu to it. After that update the menu bar. That's it.

CMenu menu;

if(menu.LoadMenu(IDR_MY_MENU))
{
    m_wndMenuBar.InsertButton(CMFCToolBarMenuButton(0, menu, -1, _T("&MyMenu")), -1);

    m_wndMenuBar.AdjustLayout();
    m_wndMenuBar.AdjustSizeImmediate();
}

P.S. menu may be local because CMFCToolBarMenuButton constructor copy content from it.

sliser
  • 1,645
  • 11
  • 15
1

You probably need to override:

CMDIFrameWndEx::OnShowPopupMenu(CMFCPopupMenu* pMenuPopup)

and put a placeholder menu item where you need a dynamic menu, then replace the placeholder menu item with your dynamic menu.

For an example look into the source code shipping with MFC:

afxframeimpl.cpp

BOOL CFrameImpl::OnShowPopupMenu(CMFCPopupMenu* pMenuPopup, CFrameWnd* /*pWndFrame*/)
darune
  • 10,480
  • 2
  • 24
  • 62
0

The ideal way is probably to completely build a CMenu object, and then assign it to the menu bar: This makes the code almost compatible with the previous versions of VisualStudio.

  1. Declare a pointer to an instance of CMenu in CMainFrame definition:

    CMenu *m_pMainMenu
    
  2. Set it to NULL in CMainFrame constructor:

    m_pMainMenu = NULL;
    
  3. In CMainFrame::OnCreate(), create an instance of CMenu assuming it was NULL before:

    SAFE_DELETE(m_pMainMenu);  
    m_pMainMenu = new CMenu;
    
  4. Modify it at will with:

    pMainMenu->LoadMenu(),  
    pMainMenu->RemoveMenu(),  
    pMainMenu->AppendMenu(),  
    pMainMenu->InsertMenu(),  
    ...
    
  5. Finally, associate the menu toolbar with this new menu by using CreateFromMenu:

    m_wndMenuBar.CreateFromMenu(m_pMainMenu->m_hMenu);
    
  6. Don't forget to release m_pMainMenu in CMainFrame destructor to avoid leaks:

    SAFE_DELETE(m_pMainMenu)
    

Note: This is a very handy and safe macro:

#define SAFE_DELETE(a) { if (a) { delete(a); a=NULL; } }
JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Nick22
  • 1
  • 1
-1

You can use UPDATE_COMMAND_UI in property view window. Let's say, you put a 'Text Capture' menu with 'ID_TEXTCAPTURE', and then you want to change the menu with 'Stop Capture'.

-in message map

BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWndEx)
    ON_WM_CREATE()
    ON_UPDATE_COMMAND_UI(ID_TEXTCAPTURE, &CChildFrame::OnUpdateTextcapture)
END_MESSAGE_MAP()

-event handler

void CChildFrame::OnUpdateTextcapture(CCmdUI *pCmdUI)
{
    if(pCmdUI->m_pMenu)
    {
        int pos;
        CMenu* mmenu = pCmdUI->m_pMenu;
        pos = FindMenuItem(mmenu, _T("Text Capture(&C)"));

        if (pos > -1 && IsCapture == TRUE)
        {
            UINT id = mmenu->GetMenuItemID(pos);

            //change menu text as 'Stop Capture'
            mmenu->ModifyMenu(id, MF_BYCOMMAND, id, _T("Stop Capture(&S)"));
            IsCapture = TRUE;
        }       
     }
 }


CChildFrame::FindMenuItem(CMenu* Menu, LPCTSTR MenuString)
{

    ASSERT(Menu);
    ASSERT(::IsMenu(Menu->GetSafeHmenu()));

    int count = Menu->GetMenuItemCount();
    for (int i = 0; i < count; i++)
    {

        CString str;
        if (Menu->GetMenuString(i, str, MF_BYPOSITION) && str.Compare(MenuString) == 0)
      return i;
    }
    return -1;
}
hyun
  • 2,135
  • 2
  • 18
  • 20
  • I need full customization adding new items, deleting existing ones, not just text, I can change text, but not adding or removing. – ahmedsafan86 Dec 29 '13 at 12:34
  • @ahmedsafan86 I apologize about my careless. I do not have any method about that also. I hope you already solve this. Thanks. – hyun Dec 30 '13 at 00:29