【问题标题】:Example code for CMFCMenuButton?CMFCMenuButton 的示例代码?
【发布时间】:2015-08-13 20:08:43
【问题描述】:

很抱歉这个新手问题,但任何人都可以指出示例代码来说明 CMFCMenuButton 的使用吗? Microsoft 帮助引用了“新控件示例”,但这些示例似乎位于 Visual Studio 2008“功能包”中,并且由于我正在运行 VS 2013 并且没有 VS 2008,因此它拒绝安装在我的系统上。我无法找到作为独立代码的示例。 具体来说,我有一个对话框栏,其中我想要一个标记为 Save 的按钮,其中包含 Save All 和 Save Visible 的下拉选项(默认为 Save All)。但任何工作代码至少可以让我开始。

【问题讨论】:

    标签: c++ mfc cmfcmenubutton


    【解决方案1】:

    声明数据成员:

    CMFCMenuButton m_button_menu;
    CMenu m_menu;
    

    还将按钮的 id 添加到消息映射和数据交换中:

    BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
        ON_BN_CLICKED(IDC_MFCMENUBUTTON1, OnButtonMenu)
        ...
    END_MESSAGE_MAP
    
    void CMyDialog::DoDataExchange(CDataExchange* pDX)
    {
        CDialogEx::DoDataExchange(pDX);
        DDX_Control(pDX, IDC_MFCMENUBUTTON1, m_button_menu);
    } 
    

    定义:

    BOOL CMyDialog::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
        //...
        m_menu.LoadMenu(IDR_MENU1);
        m_button_menu.m_hMenu = m_menu.GetSubMenu(0)->GetSafeHmenu();
    
        return TRUE;  
    }
    

    IDR_MENU1 是一个常规菜单栏,我们得到它的第一个子菜单。例如:

    IDR_MENU1 MENU
    BEGIN
        POPUP "Dummy"
        BEGIN
            MENUITEM "&Item1", ID_FILE_ITEM1
            MENUITEM "&Item2", ID_FILE_ITEM2
        END
    END
    

    如果单击按钮的下拉箭头,则会出现一个弹出菜单,菜单结果将传递给OnButtonMenu。如果点击左侧按钮,则直接调用OnButtonMenu,不显示弹出菜单。

    void CMyDialog::OnButtonMenu()
    {
        CString str;
        switch (m_button_menu.m_nMenuResult)
        {
        case ID_FILE_ITEM1:
            str = L"first menu item clicked";
            break;
        case ID_FILE_ITEM2:
            str = L"second menu item clicked";
            break;
        default:
            str = L"Button click (popup menu did not appear, or menu ID is not handled)";
            break;
        }
        MessageBox(str);
    }
    

    ** 当使用停靠控件、对话框栏等时。MFC 可能会运行自己的子类,我认为不会调用 DoDataExchangem_button_menu 可能无效。 GetDlgItem 可用于查找正确的指针:

    CMFCMenuButton* CMyDlgBar::GetButtonMenu()
    {
        CMFCMenuButton* pButton = &m_button_menu;
        if (!IsWindow(pButton->m_hWnd))
            pButton = (CMFCMenuButton*)GetDlgItem(IDC_MFCMENUBUTTON1);
        return pButton;
    }
    

    我们在其他任何地方都使用GetButtonMenu() 而不是m_button_menu。例如:

    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
        //...
        m_dlgbar.Create(...);
        m_dlgbar.m_menu.LoadMenu(IDR_MENU1);
        m_dlgbar.GetButtonMenu()->m_hMenu = m_dlgbar.m_menu.GetSubMenu(0)->GetSafeHmenu();
    
        return 0;
    }
    
    void CMainFrame::OnButtonMenu()
    {
        CString str;
        switch (GetButtonMenu()->m_nMenuResult)
        ...
    }
    

    如果下拉箭头不显示怎么办?

    然后阅读答案here,其中解释了您的 RC 文件所需的更改。

    【讨论】:

    • 为了完成这个示例,您可以添加 IDR_MENU1 资源脚本。
    • 更新:按照建议添加了示例菜单资源
    • 非常感谢您提供快速而清晰的解释。但是,我似乎无法让它在我的 CDialogBar 派生类中工作。我已经尝试了上面的 DDX_ 路由,并且我还尝试在 OnInitDialog 中对我的 CMFCMenuButton 成员变量进行子类化(已经完成了该函数在对话框栏中工作所需的模块),但在这两种情况下我都得到了一个灾难性的 ASSERT级联达到高潮
    • 抱歉 - 在我完成之前用完了编辑时间: BOOL CWnd::Attach(HWND hWndNew) { ASSERT(m_hWnd == NULL); // 只附加一次,在销毁时分离 ASSERT(FromHandlePermanent(hWndNew) == NULL); // 不能已经在永久地图中
    • 看起来DoDataExchange 没有在CDialogBar 中调用,SubclassDlgItem 失败,因为 MFC 正在做自己的事情。调用IsWindow(m_button_menu.m_hWnd) 以确保控件已初始化,或使用GetDlgItem。查看CDialogBar的更新答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 2011-12-17
    • 2016-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多