c++menumfcdialogcmfcmenubutton

how to correctly send CMFCMenuButton selected ID to the message map?


firstly let me describe what I have:
scenario: CMFCMenuButton, loaded with a CMenu, in a dialog
test: click on an item of the menu
result: the message map will get the ID of the CMFCMenuButton and not the ID of the menu
how to get the actual menu ID clicked: use CMFCMenuButton::m_nMenuResult

The idea is that I want to have menu items and buttons in this dialog, and there would be buttons that share IDs with the menu items.

So in the handler that I've created for the menu button I can get that m_nMenuResult and send it to the dialog or do whatever I want, but that doesn't seem to be how the CMFCMenuButton should work. What is the correct way of doing it?

Code

Here follows an example on how you can reproduce this.
I've used ON_COMMAND_RANGE also with IDC_MFCMENUBUTTON1 just to reuse the code for the OnMenu function

void CRepositionDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_MFCMENUBUTTON1, m_cmfcMenuButton);
}


BEGIN_MESSAGE_MAP(CRepositionDlg, CDialog)
    ON_COMMAND_RANGE(IDC_MFCMENUBUTTON1,IDC_MFCMENUBUTTON1,OnMenu)

    ON_COMMAND_RANGE(IDC_MENU1, IDC_MENU11, OnMenu)
END_MESSAGE_MAP()


// CRepositionDlg message handlers

afx_msg void CRepositionDlg::OnMenu(UINT nID)
{
    CString csMessage;
    csMessage.Format(L"OnMenu(%d)",nID);
    AfxMessageBox(csMessage);
    if(nID == IDC_MFCMENUBUTTON1)
    {
        OnMenu(m_cmfcMenuButton.m_nMenuResult);
    }
}


BOOL CRepositionDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // TODO:  Add extra initialization here

    CMenu* pMenu = new CMenu;
    pMenu->CreatePopupMenu();
    for(int i = IDC_MENU1; i <= IDC_MENU11; i++)
    {
        CString csMenu;
        csMenu.Format(L"menu %d",i);
        pMenu->AppendMenuW(MF_STRING,i,csMenu);
    }
    m_cmfcMenuButton.m_hMenu = pMenu->GetSafeHmenu();
    return TRUE;  // return TRUE unless you set the focus to a control
    // EXCEPTION: OCX Property Pages should return FALSE
}

Solution

  • If you code a handler for BN_CLICKED for the menu button, it will respond with 0 for m_nMenuResult if the click is on the button, or, m_nMenuResult will contain the ID of the menu item selected. If that's not what you wanted, I think you're fighting against the way the button works. Your only other option would be to create your own class to represent a menu button and add the behavior you want.