Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / MFC
Article

A set of classes to create the IE-style GUI

Rate me:
Please Sign up or sign in to vote.
4.85/5 (52 votes)
19 Jul 2003CPOL6 min read 568.7K   6.4K   168   130
The article gives a sample of how to implement Internet Explorer-style sizable re-bar and menu bar controls.

Introduction

I was recently looking for a sample of how to mimic the IE menu bar.  First, I read an article in MSDN Library named "Creating an Internet Explorer-style Menu Bar" which gives a brief idea of how to get started.  Then, I ran across an article by Paul DiLascia (with a working sample!).  Unfortunately, Paul's article addresses SDI applications rather than MDI, although it gives many useful ideas and tricks which I used later on.  Finally, I visited Internet sites devoted to MFC programming and found there some good articles concerning the problem in question.  But most of those articles seem to pretend to be too universal and as a result are too heavy.  This is possibly because the authors were trying to mimic MS Office/DevStudio (which is more complicated indeed) rather than the IE menu bar.  Thus I came to the decision to create my own MenuBar which will meet all my unpretentious needs.

As my MenuBar was getting along I realized that it also would be nice to incorporate the standard ReBar control into another sizable "re-bar" just like IE does, so that the user could resize the ReBar by dragging a divider between the frame's client area and the ReBar itself.  So this gave rise to another control, which I call SizableReBar here.  It was not hard to implement corresponding C++ class, since there are a lot of samples of custom ControlBars on the Net.  My favourite is CSizingControlBar by Cristi Posea (thanks Cristi for your excellent work!).  I used some of his basic ideas in my CSizableReBar class.

After all, one thing left to be implemented to fully mimic the IE-style GUI was a toolbar control that could display itself on a chevron menu when some of its buttons get clipped.  Frankly speaking, I was not excited about this idea in the beginning and the initial version of the class library did not contain any toolbar classes.  Fortunately, I had some spare time a while ago and did write that anticipated CToolBarEx class.

Although bitmapped menus are not a distinction of the IE-style GUI, it is considered to be a good form for modern apps to have them nowadays.  There are plenty of good articles on the Net that show how to implement owner-draw bitmapped menus.  But I have failed to find one that utilizes new functions and structures introduced in Windows 98, namely the hbmpItem member of the MENUITEMINFO structure and the GetMenuInfo() / SetMenuInfo() functions along with the MENUINFO structure.  In my opinion it is quite reasonable to use these functions/structures, bearing in mind the growing number of the users that have already moved from W95/NT4 to W98/W2K/XP platforms.  Also it is much more easy and a more standard way than to use fully owner-draw menus.  That is why I have built in support of bitmapped menus using these new functions/structures.

Highlights of the classes

Moving on to what has been implemented so far (all these classes are located in \GuiLib directory of the demo project and compiled into MFC extension DLL called GuiLib.dll):

  1. CMenuBar class encapsulates the core functionality of the menu bar.  It also knows how to display itself on chevron menu when some of menu bar items (and/or caption buttons, in case of MDI app) get clipped:

    Image 1

    The latest version of CMenuBar  seems to work correctly when an embedded item is activated in-place.

  2. CToolBarEx class is meant to be used instead of standard CToolBar class.  Unlike CToolBarCToolBarEx knows how to display itself on chevron menu when some of its buttons get clipped:

    Image 2

    CToolBarEx  provides 3 different options for text labels ("Show text lables", "Selective text on right" and "No text labels") and 2 options for icons ("Small icons" that is 16x16 and "Large icons" that is 24x24").

    Besides, CToolBarEx is persistent, i.e. its state (including Text and Icon options) can be saved in the registry and restored later on.  Corresponding methods are: SaveState(LPCTSTR lpszProfileName) and LoadState(LPCTSTR lpszProfileName).

  3. CCustomizeDialog class allows the user to change toolbar options, as well as do other toolbar customizations.  In fact, it is standard "Customize Toolbar" dialog which has been slightly extended (see new combo-boxes at the bottom of the dialog):

    Image 3

  4. CSizableReBar class encapsulates the functionality of the sizable re-bar control.

    The control is persistent, i.e. its state can be saved in the registry and restored later on now.  Corresponding methods are: SaveState(LPCTSTR lpszProfileName) and LoadState(LPCTSTR lpszProfileName).

    CSizableReBar has context menu which usually has two parts:  the first part is a list of bands that can be hidden/shown, and the second part (which is optional) is specific to the band that was clicked.  For example, when the user right-clicks band with a toolbar the context menu may look as follows:

    Image 4

  5. CFrameWndEx (to be used in SDI applications), CMDIFrameWndEx and CMDIChildWndEx (to be used in MDI applications) classes were introduced to make the programmer's life as easy as possible. C(MDI)FrameWndEx will automatically create a SizableReBar and MenuBar, as well as handle some key windows messages in order to get the MenuBar working correctly.

  6. CPreviewToolBar, CPreviewViewEx and template<class TBase> class CPreviewableView classes were introduced to provide Print Preview mode with nice-looking CToolBarEx-derived toolbar instead of that ugly standard preview bar provided by MFC by default:

    Image 5

    To have such a preview toolbar your view should be derived from CPreviewableView .  For example:

    class CMyView : public CPreviewableView< CEditView >
    Also ID_FILE_PRINT_PREVIEW command handler implemented in CPreviewableView should be added to the message map of the derived class:

    BEGIN_MESSAGE_MAP( CMyView, CEditView )
      ...
      ON_COMMAND( ID_FILE_PRINT_PREVIEW, OnFilePrintPreview )
    END_MESSAGE_MAP()
  7. Every window that is assumed to be used as bitmapped popup menu owner should be derived from template<class TBase> class CBmpMenuOwnerWnd .  For example:
    class CMyFrame : public CBmpMenuOwnerWnd< CMiniFrameWnd  >

    Also message handlers implemented in CBmpMenuOwnerWnd should be added to the message map of the derived class:

    BEGIN_MESSAGE_MAP( CMyFrame, CMiniFrameWnd )
      ...
      ON_WM_INITMENUPOPUP()
      ON_WM_DRAWITEM()
      ON_WM_MEASUREITEM()
    END_MESSAGE_MAP()
    Note: CFrameWndExCMDIFrameWndEx and CMDIChildWndEx  are already derived from CBmpMenuOwnerWnd.

  8. CWindowListDialog  class allows the user to manage MDI child windows:

    Image 6

    Obviously, this dialog makes sense for MDI apps only.  Menu item that invokes this dialog is automatically added to the end of the Window popup menu, if any.

  9. CWinAppEx  class is used to cache various system-wide settings.  It also holds image list with menu icons.

General note for the latest release of CMenuBar and CToolBarEx classes:  all that new W98/W2K/XP visual effects (like XP themes, flat menu appearance, menu animation, menu underlines, menu fade, etc.) are supported by menu bar/toolbar chevron menu now and brought into accord with corresponding system-wide settings.

Using the classes

Here are basic steps:

  1. Add GuiLib directory to the list of additional include directories for your project.
  2. Add the following line of code to your stdafx.h:
    #include "GuiLib.h"
  3. Add inclusion of GuiLib\Resource.h in your RC file:
    #include "afxres.h"
    #include "GuiLib\Resource.h"
    
    ...
    
    2 TEXTINCLUDE MOVEABLE PURE
    BEGIN
      "#include ""afxres.h""\r\n"
      "#include ""GuiLib\\Resource.h""\r\n"
      ...
      "\0"
    END
    Note: Resource IDs from 101 to 999 and from 33001 to 33999 are reserved by GuiLib.dll and should not be used by your application.
  4. Derive your Windows application object from CWinAppEx rather than CWinApp and modify InitInstance() as follows:
    BOOL YourApp::InitInstance()
    {
      InitGuiLibDLL();	// insert GuiLib.dll into the resource chain
    	
      ...
    }
  5. Derive your main frame object from C(MDI)FrameWndEx rather than C(MDI)FrameWnd.  In case of MDI application all child frames should be derived from CMDIChildWndEx.
  6. Derive all your toolbars from CToolBarEx (don't forget to override CToolBarEx::Init() function!).  As soon as toolbar created it should be added to the sizable re-bar control.  This can be done in CMainFrame::OnCreate().  For example:
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
      if ( CMDIFrameWndEx::OnCreate( lpCreateStruct ) == -1 )
        return -1;
    		
      VERIFY( m_wndToolBar.Create( this,
          WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_FLYBY ) );
      VERIFY( m_wndReBar.AddBar( &m_wndToolBar,
          0, 0, RBBS_FIXEDBMP | RBBS_BREAK, _T("&Toolbar"), false ) );
    
      m_wndToolBar.Init();
    	
      ...
    }

Having no time to illustrate bit by bit usage of each of the classes, I can say that it should not be a problem for an intermediate MFC developer to get all omitted here details and aspects from the source code of the demo project.

Minimal system requirements

As you probably know, there is always a fly in the ointment:  all this stuff requires Comctl32.dll version 5.81 or higher now.  I personally don't see any difference between v5.80 and v5.81 though.  From my experience all these v5.81 specific flags (like BTNS_SHOWTEXT) work with v5.80 just fine.  What a mystery!  Should someone know the actual difference, please let me know.

Final words

Unfortunately, I had no time to test the classes thoroughly.  Therefore, any bug reports, bug fixes and comments are more than welcome!  Anyway, I hope you will enjoy using this set of classes.

License

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


Written By
Software Developer (Senior)
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: how to add a new button to the toolbar Pin
Christian Cheney27-Jan-05 10:01
Christian Cheney27-Jan-05 10:01 
Generalstrange menu behaviour Pin
Michel Wassink18-Nov-04 21:14
Michel Wassink18-Nov-04 21:14 
QuestionNicolay, thanks 4 yr great work. How to use yr Re-Bar in a dialog based application? Pin
FromTheWest15-Oct-04 13:58
FromTheWest15-Oct-04 13:58 
AnswerRe: Nicolay, thanks 4 yr great work. How to use yr Re-Bar in a dialog based application? Pin
yhtonline14-Dec-05 21:46
yhtonline14-Dec-05 21:46 
GeneralRe: Nicolay, thanks 4 yr great work. How to use yr Re-Bar in a dialog based application? Pin
triplebit17-Oct-06 6:44
triplebit17-Oct-06 6:44 
QuestionHow to hide buttons in the CCustomizeDialog Pin
Oeg20-Sep-04 22:51
Oeg20-Sep-04 22:51 
GeneralFix for group selection in CWindowListDialog Pin
Thomas Haase8-Aug-04 23:28
Thomas Haase8-Aug-04 23:28 
GeneralMissing command handler for save button in CWindowListDialog Pin
Thomas Haase8-Aug-04 23:17
Thomas Haase8-Aug-04 23:17 
QuestionHow to insert a combo box in tool bar Pin
Anonymous2-Aug-04 15:27
Anonymous2-Aug-04 15:27 
AnswerRe: How to insert a combo box in tool bar Pin
Christian Cheney27-Jan-05 11:09
Christian Cheney27-Jan-05 11:09 
GeneralMissing tool tip help windows in customize dialog Pin
Thomas Haase14-Jul-04 2:09
Thomas Haase14-Jul-04 2:09 
Generala problem ablut preview toolbar Pin
benben21-Dec-03 21:57
benben21-Dec-03 21:57 
GeneralDropdown button AND Office XP Menu styles Pin
darthmaul10-Dec-03 2:40
darthmaul10-Dec-03 2:40 
Questionhow to use toobarex only? Pin
Tiger.Z12-Nov-03 19:01
Tiger.Z12-Nov-03 19:01 
GeneralPaint probleem Pin
dddv19-Oct-03 1:03
dddv19-Oct-03 1:03 
GeneralVisual Studio .NET Pin
dam1el27-Aug-03 22:03
dam1el27-Aug-03 22:03 
GeneralRe: Visual Studio .NET Pin
Roger Bond4-Dec-03 5:03
Roger Bond4-Dec-03 5:03 
GeneralRe: Visual Studio .NET Pin
Nikolay Denisov4-Dec-03 22:47
Nikolay Denisov4-Dec-03 22:47 
GeneralRe: Visual Studio .NET Pin
dam1el8-Dec-03 21:47
dam1el8-Dec-03 21:47 
GeneralAdding an item to menubar at run time Pin
Hal Director27-Aug-03 10:07
Hal Director27-Aug-03 10:07 
GeneralA Bug Pin
RoseKing26-Aug-03 3:09
RoseKing26-Aug-03 3:09 
GeneralRemoving item from context menu Pin
Hal Director30-Jul-03 16:04
Hal Director30-Jul-03 16:04 
GeneralUxtheme.dll needed. Pin
TomPeakz21-Jul-03 19:21
TomPeakz21-Jul-03 19:21 
GeneralRe: Uxtheme.dll needed. Pin
Nikolay Denisov21-Jul-03 22:18
Nikolay Denisov21-Jul-03 22:18 
GeneralYes, you are right. Pin
TomPeakz23-Jul-03 19:26
TomPeakz23-Jul-03 19:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.