Vista Aero’s Menus Hiding with MFC 9.0

You probably noticed that IE7 or Windows Media Player 11 don’t have the menu shown by default; it only shows up when you press the ALT key. This is one particularity of the look and feel of Windows Vista Aero. You can find guidelines about designing menus here:

As revealed by the VC++ team some time ago, MFC 9.0 offers support for hiding the menus automatically and manually, in accordance with the Aero look and feel. A recent article in the MSDN Magazine by Tarek Madkour, explains how: by calling the SetMenuBarVisibility method from CFrameWnd with the AFX_MBV_DISPLAYONFOCUS. What is not told is that works only for SDI applications.

Menus in SDI applications 

In a SDI application you have a class derived from CFrameWnd, usually called CMainFrame. In the OnCreate() method, after calling the CFrameWnd’s OnCreate, you can call SetMenuBarVisibility:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
      return -1; 

   SetMenuBarVisibility(AFX_MBV_DISPLAYONFOCUS); 

   // other stuff here 

   return 0;
}



AFX_MBV_DISPLAYONFOCUS is defined in afxwin.h:

// Frame window menu bar visibility styles
#define AFX_MBV_KEEPVISIBLE    0x01L // always visible
#define AFX_MBV_DISPLAYONFOCUS 0x02L // toggle state on ALT
#define AFX_MBV_DISPLAYONF10   0x04L // display on F10



The result is that the menu is automatically hidden (as can be seen in the image)

SDI menu is hidden 

and shown only when pressing the ALT key.

SDI menu is shown

Menus in MDI applications

The same technique does not work for MDI menus. In such an application you have

  • a main frame, represented by a (usually called) CMainFrame class derived from CMDIFrameWnd, which in turn is derived from CFrameWnd, and
  • one or more child frames, derived from CMDIChildFrame, which in turn is derived from CFrameWnd

Both the main window and the child windows can have menus, but the menu of a child window is shown on the same bar with the menu of the main window. As long as a child window exists the menu of that document is shown. When no child window exists the menu of the main window is shown. Both on the same bar.

Trying to make the menu of the child window(s) hidden by default does not work. Calling SetMenuBarVisibility has no effect:

int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
   if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
      return -1;

   SetMenuBarVisibility(AFX_MBV_DISPLAYONFOCUS);

   return 0;
}



Calling SetMenuBarVisibility for the main frame results in an assertion failure because the implementation in the CMDIFrameWnd expects the parameter to be always AFX_MBV_KEEPALIVE; it doesn’t do anything else, such as calling the function from the base class.

void CMDIFrameWnd::SetMenuBarVisibility(DWORD dwStyle)
{
   ENSURE_ARG(dwStyle == AFX_MBV_KEEPVISIBLE);
   ASSERT(m_dwMenuBarVisibility == AFX_MBV_KEEPVISIBLE);
}



Overriding the method in CMainFrame accept any parameter and call the method in CFrameWnd to bypass CMDIFrameWnd does not have any effect either.

void CMainFrame::SetMenuBarVisibility(DWORD dwStyle)
{
   CFrameWnd::SetMenuBarVisibility(dwStyle);
}



In conclusion MFC 9.0 supports the Aero look-and-feel for the automatically hiding of menus, but only in SDI applications.

Hits for this post: 13337 .
Trackback

2 comments untill now

  1. Gravatar
    DoYouKnow @ 2009-06-04 11:01

    Thanks, :D

Add your comment now