Reputation: 10911
I know how to generate a static menu item for a button with the following code:
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);
But if I want the menu to be dynamic, what do I do? I tried to modify the original HMENU
by overriding the OnShowPopupMenu()
and changing the HMENU
that I attached to that button, but that didn't work.
I was able to force a menu under the button by creating a menu and using the TrackPopupMenu()
function but the style is wrong. (Looks grey instead of white and some other differences).
EDIT
To solve this, I did the following:
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();
}
};
Adding this button to a panel will then generate the dynamic menu that I want.
Upvotes: 0
Views: 1574
Reputation: 2937
The ribbon seems to only use the hMenu
as a template to build it's own structure from it, so modifying the hMenu
is vain. Better work with the existing Ribbon Menu Button:
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());
But make sure to update the menu at the right place in your code. Changing the menu in CMyView::OnUpdate()
proved to be not such a good idea (see here). If you need to modify the menu when opening a mdi document, consider OnInitialUpdate()
. I haven't tried OnCmdMsg()
yet.
Maybe its sufficient to get pBtn via CMFCRibbonBar::FindByID()
but maybe its the right thing to iterate through CMFCRibbonBar::GetElementsByID
and change each menu button you find (i.e. to also modify the quick access toolbar?)... I found the documentation is not very specific about that but modifying via ´FindByID´ seems to be sufficient in my code.
If you have any further revelations about dynamic ribbon menus, please leave me a comment.
Upvotes: 1