如何为功能区按钮创建动态菜单?

时间:2014-09-08 16:22:57

标签: mfc ribbon

我知道如何使用以下代码为按钮生成静态菜单项:

CBCGPRibbonCategory *pCategory = ...;
CBCGPRibbonPanel *pPanel = pCategory->AddPanel(_T("Panel Name"), hPanelIcon);

HMENU hMenu = CreateMenu();
AppendMenu(hMenu, MF_STRING, ID_ITEM_1, _T("Item 1"));
AppendMenu(hMenu, MF_STRING, ID_ITEM_2, _T("Item 2"));

CBCGPRibbonButton * pButton = new CBCGPRibbonButton(ID_BUTTON_WITH_MENU, _T(""))
pButton->SetMenu(hMenu, TRUE); // for dynamic
pPanel->Add(pButton);

但如果我想要菜单是动态的,我该怎么办?我尝试通过覆盖HMENU并更改我附加到该按钮的OnShowPopupMenu()来修改原始HMENU,但这不起作用。

我可以通过创建菜单并使用TrackPopupMenu()功能强制按钮下的菜单,但样式错误。 (看起来是灰色而不是白色和其他一些差异)。

修改

为了解决这个问题,我做了以下几点:

class CDynamicMenuButton : public CBCGPRibbonButton
{
public:
    CDynamicMenuButton(
        UINT    nID,
        LPCTSTR lpszText,
        int     nSmallImageIndex = -1,
        int     nLargeImageIndex = -1,
        BOOL    bAlwaysShowDescription = FALSE)
        : CBCGPRibbonButton(nID, lpszText, nSmallImageIndex, nLargeImageIndex, bAlwaysShowDescription)
    {
        SetMenu(CreatePopupMenu());
    }

    void OnShowPopupMenu() override
    {
        // legacy code to generate menu
        CMenu newMenu;
        populateMenu(&newMenu);

        // sets the new menu
        SetMenu(newMenu);

        // Pops up the new menu
        CBCGPRibbonButton::OnShowPopupMenu();
    }
};

将此按钮添加到面板将生成我想要的动态菜单。

1 个答案:

答案 0 :(得分:1)

功能区似乎只使用hMenu作为模板来构建它自己的结构,因此修改hMenu是徒劳的。使用现有功能区菜单按钮更好地工作:

    pBtn->RemoveAllSubItems(); // add a dummy hMenu when creating the menu button in CMainFrame!

    std::auto_ptr<CMFCRibbonButtonEx> apBtn3(new CMFCRibbonButtonEx(ID_DYNAMIC_MENU_ITEM_3, "Item 3", -1, -1, true));
    pBtn->AddSubItem(apBtn.release());

    std::auto_ptr<CMFCRibbonButtonEx> apBtn4(new CMFCRibbonButtonEx(ID_DYNAMIC_MENU_ITEM_4, "Item 4", -1, -1, true));
    pBtn->AddSubItem(apBtn.release());

但请务必在代码中的正确位置更新菜单。改变CMyView::OnUpdate()中的菜单被证明不是一个好主意(see here)。如果您在打开mdi文档时需要修改菜单,请考虑OnInitialUpdate()。我还没有尝试OnCmdMsg()

也许它足以通过CMFCRibbonBar::FindByID()获取pBtn,但也许通过CMFCRibbonBar::GetElementsByID迭代并更改您找到的每个菜单按钮(即还要修改快速访问工具栏?)是正确的。我发现文档对此并不十分具体,但在我的代码中通过'.FindByID'进行修改似乎就足够了。

如果您对动态功能区菜单有任何进一步的启示,请给我留言。