Question

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;
Était-ce utile?

La solution

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.

Autres conseils

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*/)

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

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top