Click here to Skip to main content
15,887,585 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have an application written in VS 2013, with some toolbars and a main menu. The menu is derived from a CMFCMenuBar and the toolbars are derived from CMFCToolBar. The menu is partly defined from the resource file and partly by dynamically added entries due to loaded drivers etc.

I want the toolbars but not the menu to be customizable, so I have disabled customization of the menu by setting m_bDisableCustomize = TRUE in the menu constructor.

The problem is that I can still choose to reset the menu from the Customize-dialog (when opened from a toolbar), and then the menu will lose all dynamically added entries. (an MFC bug?)

I have tried overriding the RestoreOriginalState()-function in the menu class, but for some reason it is never called - why?

Any ideas out there how to either disable the reset of the CMFCMenuBar altogether or catch it in the menu class before it destroys the dynamically added menu entries?

Regards,
RobertM
Posted
Updated 3-Sep-15 22:40pm
v3
Comments
Richard MacCutchan 4-Sep-15 3:58am    
the menu will lose all dynamically added entries. (a bug?)
More than likely, but no one here can guess what your code does.
RobertM 4-Sep-15 4:36am    
Well, I meant if it was a bug in the MFC toolbar customize dialog, that it was possible to do a reset on a control that is not customizable.

But that is off the point really. My real question is how to avoid this reset. I haven't been able to neither disable it, nor catch it.
Richard MacCutchan 4-Sep-15 4:45am    
Sorry I have not used this feature. But in either case, without seeing some of your code I do not think anyone can offer much in the way of suggestions.
RobertM 4-Sep-15 8:24am    
Yeah, you are probably right. I had hoped somebody would say "Ah, but to catch the reset menu from the Customize dialog you ..." or something like that.

I don't really know what code to show though. The entire code base is sort of humongous, while the menu class itself is rather trivial. I'll give it a try though. Thank you for your interest.

1 solution

I can't show my entire code base as it is sort of big (and people might get kind of annoyed if I published it), but here is the menu class and the references to the menu object in the main frame. The menu is implicitly created in the main frame.

I could solve the problem if the RestoreOriginalState or OnReset was called on the reset command in the Customize dialog, but for some reason they are not.

IaMenuBar.h
// This is the main menu class. We have derived our own class to be able to
// for example block customization.
class IaMenuBar : public CMFCMenuBar
{
  DECLARE_SERIAL(IaMenuBar)
public:
  IaMenuBar();
  virtual ~IaMenuBar();

  virtual BOOL CreateEx( CWnd* pParentWnd,
                         DWORD dwCtrlStyle,
                         DWORD dwStyle,
                         CRect rcBorders,
                         UINT  nID );
  virtual BOOL RestoreOriginalState();   // TBD: Is not called???
  virtual BOOL CanBeRestored() const;
  virtual BOOL LoadState(LPCTSTR lpszProfileName = NULL, int nIndex = -1, UINT uiID = (UINT)-1);
  virtual BOOL SaveState(LPCTSTR lpszProfileName = NULL, int nIndex = -1, UINT uiID = (UINT)-1);

  afx_msg void OnContextMenu(CWnd* pWnd, CPoint pos);
  virtual void OnReset();   // TBD: Is not called???

private:
  DECLARE_MESSAGE_MAP()
};


IaMenuBar.cpp
C++
#include "IaPch.h"
#include "IaMenuBar.h"

IMPLEMENT_SERIAL(IaMenuBar, CMFCMenuBar, VERSIONABLE_SCHEMA | 1)

//{{AFX_MSG_MAP(IaMenuBar)
BEGIN_MESSAGE_MAP(IaMenuBar, CMFCMenuBar)
  ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()
//}}AFX_MSG_MAP

IaMenuBar::
IaMenuBar()
: CMFCMenuBar()
{
  m_bDisableCustomize = TRUE;
}

IaMenuBar::
~IaMenuBar()
{
}

BOOL 
IaMenuBar::
CreateEx( CWnd* pParentWnd,
          DWORD dwCtrlStyle,
          DWORD dwStyle,
          CRect rcBorders,
          UINT  nID )
{
  if (!__super::CreateEx(pParentWnd, dwCtrlStyle, dwStyle, rcBorders, nID))
  {
    return FALSE;
  }
  return TRUE;
}

BOOL 
IaMenuBar::
RestoreOriginalState()
{
  // Skip restoring of the state, since we don't allow customization and
  // we don't want our inserted menus to be replaced by the insertion
  // points.
  return TRUE;
  // TBD: This function is not called!
}

BOOL
IaMenuBar::
CanBeRestored() const
{
  return FALSE;
}

BOOL 
IaMenuBar::
LoadState(LPCTSTR lpszProfileName /*= NULL*/, int nIndex /*= -1*/, UINT uiID /*= (UINT)-1*/)
{
  // Skip loading of the state, since we don't allow customization and
  // we want to control what the menu looks like ourselves.
  return TRUE;
}

BOOL 
IaMenuBar::
SaveState(LPCTSTR lpszProfileName /*= NULL*/, int nIndex /*= -1*/, UINT uiID /*= (UINT)-1*/)
{
  // Skip saving of the state, since we don't allow customization and
  // we want to control what the menu looks like ourselves.
  return TRUE;
}

void
IaMenuBar::
OnContextMenu(CWnd* pWnd, CPoint pos)
{
  // Prevent the context menu from appearing if the customize dialog is
  // open. That context menu is for customizing the menu, which we have
  // disabled.
  if (IsCustomizeMode())
    return;

  CMFCMenuBar::OnContextMenu(pWnd, pos);
}

void
IaMenuBar::
OnReset()
{
  // Prevent the context menu from appearing if the customize dialog is
  // open. That context menu is for customizing the menu, which we have
  // disabled.
  if (IsCustomizeMode())
    return;

  CMFCMenuBar::OnReset();
}


IaMainFrame.h
C++
class IaMainFrame : 
  public IfMDIFrameWnd,...

private:
...
  // control bar embedded members
  IaMenuBar           m_wndMenuBar;


IaMainFrame.cpp
C++
int
IaMainFrame::
OnCreate(LPCREATESTRUCT lpCreateStruct)
{
  if (IfMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
    return -1;

  if (!m_wndMenuBar.Create(this))
  {
    TRACE0("Failed to create menubar\n");
    return -1;
  }
  m_wndMenuBar.SetPaneStyle(CBRS_BORDER_TOP | CBRS_TOP | CBRS_SIZE_FIXED |
    CBRS_TOOLTIPS | CBRS_FLYBY);

...

  // If I use CBRS_ALIGN_TOP instead of CBRS_ALIGN_ANY here the menu appears 
  // under the toolbar, for some reason.
  m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY);
  EnableDocking(CBRS_ALIGN_TOP);
  DockPane(&m_wndMenuBar);

...
}

void
IaMainFrame::
UpdateMenuBar()
{
  // Found no other way (than being brutal) to make the CMFCMenuBar rebuild what it displays.
  HMENU hMenu = m_wndMenuBar.GetHMenu();
  m_wndMenuBar.CreateFromMenu(hMenu, TRUE, TRUE);
}
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900