0

To reproduce the behavior, start a new MFC Outlook style project with Ribbon (CMyView as the view class name).

Let's say I want to modify a menu of a CMFCRibbonButton, for example the subitems of the Print command, and for this, I want to RemoveAllSubItems() first.

Add this as a public member in MainFrm.h:

CMFCRibbonButton *m_pBtnPrint;

Add this in the InitializeRibbon() member funcion in MainFrm.cpp:

CMFCRibbonButton* pBtnPrint = new CMFCRibbonButton(ID_FILE_PRINT, strTemp, 6, 6);
// store the pointer to the button to be used in CMyView class
m_pBtnPrint = pBtnPrint;   

In CMyView::OnUpdate() add this code:

CMFCRibbonButton *pBtnPrint = ((CMainFrame*)AfxGetMainWnd())->m_pBtnPrint;
if (pBtnPrint) pBtnPrint->RemoveAllSubItems();  

My best guess is that something goes wrong with the frameworks internal replication of the Print command, e.g. for the Quick Access Toolbar. I wonder if I'm missing something here. Is it somehow forbidden to modify menus after the ribbon bar has been created in CMainFrame?

Edit: It obviously has nothing to do with m_pBtnPrint being invalidated e.g. after LoadFrame(). If you retreive pBtnPrint dynamically using CMFCRibbonBar::FindByID(), it will crash as well:

CMFCRibbonBar *pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
CMFCRibbonButton *pBtnPrint = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_FILE_PRINT)); 
if (pBtnPrint) pBtnPrint->RemoveAllSubItems();  

Edit: I have started a support query on the Microsoft Connect website, but no meaningful response since.

thomiel
  • 2,467
  • 22
  • 37
  • Does `AfxGetMainWnd()` return the class you've defined in `MainFrm.cpp`? Because if you get a different window and cast it to `CMainFrame*` you'll probably end up with a non-NULL `pBtnPrint` but not to what you think. – ta.speot.is May 30 '14 at 07:53
  • Sure it does. You can check yourself, if you create a new Visual Studio project. – thomiel May 30 '14 at 12:17
  • did you/they already solve this problem? are you adding m_pBtnPrint to the ribbon? – Robson Oct 30 '14 at 08:11
  • @Robson... Bug report: No, nothing happend there. m_pButtonPrint: See last code box of the question. The print button is being added by the framework. This was just for illustration purposes. But I experienced the same with buttons I added myself. – thomiel Oct 30 '14 at 09:19
  • why do you have to do something on the ribbon on the onUpdate of the view? – Robson Oct 30 '14 at 09:40
  • @Robson: Because I have to modify menus dynamically depending on the document's data. – thomiel Oct 30 '14 at 11:40

1 Answers1

0

CmainFrame::LoadFrame() overrides your pointer. If you have registry values saved from the last time you ran and closed this program, then LoadFrame will serialize the old state of the MFC buttons. The memory locations change during this time, and your saved pointers during Initialize will be invalid. You must find a way to grab the pointer to the button AFTER the LoadFrame has been ran.

I created a setup function on all my MFCToolbars just to grab these custom button pointers after the new buttons have been created from registry. I call this Setup function in my CWinAppEx::InitInstance after the call to CMainFrame::LoadFrame()

You should be able to run fine if you delete the registry values saved by this program, but upon second run it will crash.

diox8tony
  • 348
  • 3
  • 13