MFC Feature Pack: An Introduction

by Marius Bancila

Learn about MFC Feature Pack, a Microsoft extension to MFC that allows developers to enable Office 2007, Visual Studio, or IE look and feel to their VC++ applications.

MFC Feature Pack, currently in a beta version, is an extension to the MFC version shipped with Visual Studio 2008. It allows you to build an MFC application with the look and feel specific to Office 2007, Visual Studio, or Internet Explorer. In this article I'll show you how to transform a classic MDI application, enabling the Office 2007 look and feel. The reader is assumed to have basic MFC knowledge.

After completing this tutorial, you should:

  • Have a basic understanding of some extended classes (CWinAppEx, CMDIFrameWndEx, and CMDIChildEndEx)
  • Have a basic understanding of new concepts, such as ribbon bar, application button, ribbon status bar, and Quick Access Toolbar
  • Be able to customize an application bar with command and a ribbon bar with categories, panels, and elements.

During this tutorial, I will use some bitmaps that are added to the probject by Visual Studio when you create an MDI project with the Office 2007 look and feel. The main reason is that you can see that at the end of this tutorial you created an application very similar to the default one generated by Visual Studio.


The MFC Feature Pack beta is available at the Microsoft Download Center.

When you install it, make sure you read and follow the instructions; otherwise, the installation can fail.

  • If you installed Visual Studio from a network share, the network share must be accessible.
  • If you installed Visual Studio from a DVD, the DVD media must be present in the drive it was installed from.

Visual Studio Changes

Once the feature pack is installed, when you create a new MFC application, the Application Type property page of the wizard is changed.

The changes can be seen on the right side of the page and include:

  • Project style: You can select one of MFC standard (the classic style), Windows Explorer, Visual Studio, and Office.
  • Visual Style and colors: Allows you to select different themes, such as Office 2007 Blue, Black, Silver, or Aqua.
  • Enable visual style switching: If this checkbox is checked, the wizard will create support in the generated application for switching between different styles.

Transforming a Classic MFC Application

I believe the best approach to present classes from the feature pack is to take a classic MFC application and make changes manually.

Create a new MFC application, called Multipad. Set the application type Multiple documents, and make sure the Project style is "MFC Standard". Build and run the application; it should look like this:

After the changes that you will do, it should look like this:

Step 1: Add a New Header to stdafx.h

To enable the support for ribbons and control bars, the <afxcontrolbars.h> header must be used. If you are using precompiled headers, add it to stdafx.h (or the header used for this feature).

Step 2: Change CWinApp to CWinAppEx

Each application built with MFC contains one and only one CWinApp-derived object. CWinApp provides functionality for initializing and running the application.

In MFC Feature Pack, there is a new class derived from CWinApp, called CWinAppEx, that should be the new base class for your Windows application object. This new class offers the functionality of a workspace manager, handling the application state, saving and loading state to/from the registry, initializing, and providing links to the application managers.

To do:

  1. Change all references to CWinApp with CWinAppEx.

  2. class CMultipadApp : public CWinAppEx
    // Overrides
       virtual BOOL InitInstance();
    // Implementation
       afx_msg void OnAppAbout();
  3. Insert the following code in InitInstance() (for example, before registering a document template):
  4. InitContextMenuManager();
    CMFCToolTipInfo ttParams;
    ttParams.m_bVislManagerTheme = TRUE;
       RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);

Step 3: Change CMDIFrameWnd to CMDIFrameWndEx

An MDI application has a class called CMainFrame (the default name created by the Visual Studio wizard) derived from CMDIFrameWnd. This base class provides the functionality for an MDI frame window. In turn, this class inherits most of its functionality from CFrameWnd.

In MFC Feature Pack, there is a new class derived from CMDIFrameWnd, called CMDIFrameWndEx. This class is required when an MDI application needs some classes from the Feature Pack, such as ribbon classes.

To do:

  1. Replace all references to CMDIFrameWnd with CMDIFrameWndEx.

The application should look like this:


Step 4: Add Support for Changing the Application Look

To do:

  1. Add a public member m_nAppLook of type UINT to CMultipadApp.
  2. Declare a new function in CMainFrame:
  3. afx_msg void OnApplicationLook(UINT id);
  4. Define in resource.h the following IDs (the actual numerical values are not important):
  5. #define ID_VIEW_APPLOOK_OFF_2007_BLUE   215
    #define ID_VIEW_APPLOOK_OFF_2007_BLACK  216
    #define ID_VIEW_APPLOOK_OFF_2007_SILVER 217
    #define ID_VIEW_APPLOOK_OFF_2007_AQUA   218
  6. Add the following code to the constructor:
  7. CMainFrame::CMainFrame()
       theApp.m_nAppLook = theApp.GetInt(
  8. Define the body for OnApplicationLook():
  9. void CMainFrame::OnApplicationLook(UINT id)
       CWaitCursor wait;
       theApp.m_nAppLook = id;
       switch (theApp.m_nAppLook)
       case ID_VIEW_APPLOOK_OFF_2007_BLUE:
       case ID_VIEW_APPLOOK_OFF_2007_BLACK:
       case ID_VIEW_APPLOOK_OFF_2007_SILVER:
       case ID_VIEW_APPLOOK_OFF_2007_AQUA:
                    RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
       theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
  10. Call OnApplicationLook() from OnCreate():
  11. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
       if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
          return -1;
       // rest of the function body
       return 0;

The application should look like this:


Step 5: Change CMDIChildWnd to CMDIChildWndEx

An MDI child window is shown inside the MDI frame window. A child does not have a menu of its own, but shares the menu of the frame window, which is changed automatically by the framework. The functionality for such an MDI child window is provided by CMDIChildWnd.

In MFC Feature Pack, this class is extended by CMDIChildWndEx. To enable the advanced docking features from the new pack or use certain new classes, this class should be used as the base class for the child windows.

To do:

  1. Replace all references to CMDIChildWnd with CMDIChildWndEx.
  2. class CChildFrame : public CMDIChildWndEx
       // the rest of the class declaration

The application should look like this:


Notice the modified child frame.

Step 6: Change CStatusBar to CMFCRibbonStatusBar

The status bar is a control bar with panes that can display text, icons, or include controls. The MFC class for the status bar is CStatusBar.

In an application with the Office 2007 look and feel, a ribbon status bar should be used. It has two areas:

  • A main area, usually displaying status notifications
  • An extended area, usually displaying view controls; this area is located on the right side of the bar, and is shown with a different color than the main area.

The class representing the ribbon status bar is CMFCRibbonStatusBar.

To do:

  1. In CMainFrame replace CStatusBar with CMFCRibbonStatusBar.
  2. Define in resource.h two IDs, ID_STATUSBAR_PANE1 and ID_STATUSBAR_PANE2.
  3. After creating the status bar (in OnCreate), add the following code:
  4. m_wndStatusBar.AddElement(new
          _T("Pane1"), TRUE), _T("Pane1"));
          _T("Pane2"), TRUE), _T("Pane2"));

The application should look like this:


Notice the modified status bar.

Step 7: Add a Ribbon and a Ribbon Main Button

Office 2007 styled applications have a special button located on the top-left corner of the main window. This menu usually contains File commands, such as New, Open, Save, Print, or Close, but can be customized to contain any desired commands. The class representing this button is called CMFCRibbonApplicationButton.

The ribbon bar specific to Office 2007 is a pane containing tabs that are called categories. Each category is split into panels; each panel can contain controls and command buttons. The ribbon bar behaves a as static control bar and can be docked at the top of a frame. The class representing the ribbon bar is CMFCRibbonBar.

To do:

  1. Add the following fields to CMainFrame:
  2. CMFCRibbonApplicationButton m_MainButton;
    CMFCRibbonBar m_wndRibbonBar;
  3. Add the following method to CMainFrame:
  4. bool InitializeMainButton();
  5. Add the following bitmaps to the project and name them IDB_FILESMALL, IDB_FILELARGE, and IDB_MAIN_BUTTON (first, convert from PNG to BMP).
  6. IDB_FILESMALL: [filesmall.png]

    IDB_FILELARGE: [filelarge.png]

    IDB_MAIN_BUTTON: [main.png]

  7. Define the body for the method:
  8. bool CMainFrame::InitializeMainButton()
       m_MainButton.SetToolTipText(_T("File menu"));
          CSize (45, 45));
       CMFCRibbonMainPanel* pMainPanel =
          _T("Main"), IDB_FILESMALL, IDB_FILELARGE);
  9. Create the ribbon bar in OnCreate, and call InitializeMainButton().
  10. int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
       if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1)
          return -1;
       if (!m_wndStatusBar.Create(this))
          TRACE0("Failed to create status bar\n");
          return -1;    // fail to create
       m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(
          ID_STATUSBAR_PANE1, _T("Pane1"), TRUE), _T("Pane1"));
          ID_STATUSBAR_PANE2, _T("Pane2"), TRUE), _T("Pane2"));
       return 0;

The application should look like this:


Notice the application button on the top-left corner and the ribbon bar area.

Step 8: Add Commands to the Application Button

Ribbon buttons, such as application button, Quick Access Toolbars, mini toolbars, and popup menus, can be added to the ribbon bar elements. The class representing such a button is CMFCRibbonButton. Other controls that can be added to a ribbon are button groups, combo boxes, edit controls, link control, slider, label, and so forth. A non-clickable text label that can be added to a ribbon is implemented by CMFCRibbonLabel. Such a label cannot be added to the Quick Access Toolbar.

To do:

  1. Add the following code to the end of method InitializeMainButton():
  2. pMainPanel->Add(new
       CMFCRibbonButton(ID_FILE_NEW, _T("New"), 0, 0));
       CMFCRibbonButton(ID_FILE_OPEN, _T("Open"), 1, 1));
       CMFCRibbonButton(ID_FILE_SAVE, _T("Save"), 2, 2));
       CMFCRibbonButton(ID_FILE_SAVE_AS, _T("Save As"), 3, 3));

The application should look like this (when you click on the application button):


Step 9: Add More Commands to the Application Button

To do:

  1. Add the following code to the end of method InitializeMainButton():
  2. CMFCRibbonButton* pBtnPrint =
       new CMFCRibbonButton(ID_FILE_PRINT, _T("Print"), 6, 6);
    pBtnPrint->SetKeys(_T("p"), _T("w"));
       CMFCRibbonLabel(_T("Print Commands")));
       CMFCRibbonButton(ID_FILE_PRINT_DIRECT, _T("Quick Print"),
          7, 7, TRUE));
          _T("Print Preview"), 8, 8, TRUE));
          _T("Print Setup"), 11, 11, TRUE));
    pMainPanel->Add(new CMFCRibbonSeparator(TRUE));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_CLOSE,
       _T("Close"), 9, 9));
    pMainPanel->AddRecentFilesList(_T("Recent documents"));
       CMFCRibbonMainPanelButton(ID_APP_EXIT, _T("Exit"), 15));

The application should look like this (when you click on the application button):


Step 10: Add Quick Access Commands

The Quick Access Toolbar is a toolbar that can be customized with quick access to the most used commands, such as New, Open, Save, or Print.

To do:

  1. Add the following field to CMainFrame:
  2. CMFCToolBarImages m_PanelImages;
  3. Add the following method to CMainFrame:
  4. void AddQuickAccessButton();
  5. Add the following bitmap to the project and call it IDB_BUTTONS (first, convert it from PNG to BMP).
  6. [buttons.png]

  7. Create the tool bar images in OnCreate (after creating the ribbon bar):
  8. m_PanelImages.SetImageSize(CSize(16, 16));
  9. Define the body for AddQuickAccessButton():
  10. void CMainFrame::AddQuickAccessButton()
       CList<UINT, UINT> lstQATCmds;
  11. Call this function from OnCreate.

The application should look like this:


Notice the Quick Access Toolbar right to the application button.

Step 11: Add a Category to the Ribbon Bar

To add a category to a ribbon bar, you should call AddCategory, a method from CMFCRibbonBar that returns a pointer to a CMFCRibbonCategory object.

To do:

  1. Add a method to CMainFrame called InitializeRibbonBar():
  2. bool InitializeRibbon();
  3. Add the following bitmaps to the project and call them IDB_WRITESMALL and IDB_WRITELARGE (convert them from PNG to BMP first).
  4. IDB_WRITESMALL: [writesmall.png]

    IDB_WRITELARGE: [writelarge.png]

  5. Define the body for the method:

    bool CMainFrame::InitializeRibbon()
       CMFCRibbonCategory* pCategoryHome =
          m_wndRibbonBar.AddCategory(_T("Home"), IDB_WRITESMALL,
       return true;
  6. Call the method from OnCreate() (after the ribbon was created).

The application should look like this:


Step 12: Add Panels to the Ribbon Category

To add a panel to a ribbon category, call AddPanel from CMFCRibbonCategory that returns a pointer to a CMFCRibbonPanel object. To add content to a panel, call:

  • Add, to add elements (such as buttons, combo boxes, labels, and so on)
  • AddSeparator, to add a separator
  • AddToolBar, to add a toolbar

To do:

  1. Add a new menu called IDM_WINDOWS_MENU, with a single item called "New Window" with the ID ID_WINDOW_NEW, and popup property set to false.
  2. Add the following code to InitializeRibbon():
  3. // Create "Clipboard" panel:
    CMFCRibbonPanel* pPanelClipboard = 
    pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_PASTE,
       _T("Paste"), 0, 0));
    pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_CUT,
       _T("Cut"), 1));
    pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_COPY,
       _T("Copy"), 2));
    pPanelClipboard->Add(new CMFCRibbonButton(ID_EDIT_SELECT_ALL,
       _T("Select All"), -1));
    // Create and add a "View" panel:
    CMFCRibbonPanel* pPanelView =
          m_PanelImages.ExtractIcon (7));
    pPanelView->Add(new CMFCRibbonCheckBox(ID_VIEW_STATUS_BAR,
       _T("Status bar")));
    pPanelView->Add(new CMFCRibbonCheckBox(ID_VIEW_CAPTION_BAR,
       _T("Caption bar")));
    // Create and add a "Windows" panel:
    CMFCRibbonPanel* pPanelWindow =
          m_PanelImages.ExtractIcon (7));
    CMFCRibbonButton* pBtnWindows =
       new CMFCRibbonButton(ID_WINDOW_MANAGER, _T("Windows"),
          -1, 1);
          pBtnWindows->SetMenu(IDR_WINDOWS_MENU, TRUE);

The application should look like this:



Step 13: Add Windows Management Support

To do:

  1. Add a new method to CMainFrame, called OnWindowManager().
  2. afx_msg void OnWindowManager();
  3. Add a command to the message map:
  4. ON_COMMAND(ID_WINDOW_MANAGER, &CMainFrame::OnWindowManager)
  5. Define the body of the new method:
  6. void CMainFrame::OnWindowManager()
  7. Add the following call at the end of OnCreate():
  8. EnableWindowsDialog(ID_WINDOW_MANAGER,
       _T("Windows..."), TRUE);

The application should look like this:


Step 14: Add Support for Tabbed Groups

To do:

  1. Add a method to CMainFrame, called EnableTabbedGroups():
  2. void EnableTabbedGroups();
  3. Define the body for the method:
  4. void CMainFrame::EnableTabbedGroups()
       CMDITabInfo mdiTabParams;
       // set the desire tab style
       mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE;
       // set to FALSE to place close button at right of tab area
       mdiTabParams.m_bActiveTabCloseButton = TRUE;
       // set to TRUE to enable document icons on MDI tabs
       mdiTabParams.m_bTabIcons = FALSE;
       // set to FALSE to disable auto-coloring of MDI tabs
       mdiTabParams.m_bAutoColor = TRUE;
       // enable the document menu at the right edge of the tab
       // area
       mdiTabParams.m_bDocumentMenu = FALSE;
       EnableMDITabbedGroups(TRUE, mdiTabParams);
  5. Call the method from OnCreate().

The application should look like this:


Notice how the multiple child windows are tabbed in the One Note style.

Step 15: Add Style Switching Support

Until now, the application you developed used the Office 2007 Black style. You can add support for switching among several Office 2007 styles.

To do:

  1. Add the IDM_THEME_MENU with four non-popup menu items called Office 2007 (Blue Style), Office 2007 (Black Style), Office 2007 (Silver Style), and Office 2007 (Aqua Style) and with the IDs defined in Step 4.
  2. Add the following methods to CMainFrame:
  3. void AddStylesButton();
    afx_msg void OnUpdateApplicationLook(CCmdUI* pCmdUI);
  4. Define the body for the AddStylesButton:
  5. void CMainFrame::AddStylesButton()
       CMFCRibbonButton* pVisualStyleButton = 
          new CMFCRibbonButton(-1, _T("Style"), -1, -1);
       pVisualStyleButton->SetMenu(IDR_THEME_MENU, FALSE, TRUE);
          Visual Studio"));
       pVisualStyleButton->SetDescription(_T("Choose an
          Office 2007 Style"));
  6. Define the body for OnUpdayeApplicationLook:
  7. void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
       pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
  8. Add the following commands to the message map:
       ID_VIEW_APPLOOK_OFF_2007_AQUA, OnApplicationLook)
       ID_VIEW_APPLOOK_OFF_2007_AQUA, OnUpdateApplicationLook)

Now, a button called Style should appear on the right side of the ribbon, and allow changing the visual style.


Step 16: Add a Caption Bar

A caption bar is a control bar that can display information to the user using three elements: a label, a button, and a bitmap, but using only one element of each type at a time. Top and button borders can be customized to have a flat or 3D style. The class representing a caption bar is CMFCCaptionBar.

To do:

  1. Add a new field to CMainFrame:
  2. CMFCCaptionBar m_wndCaptionBar;
  3. Add the following methods to CMainFrame:
  4. bool InitializeCaptionBar();
    afx_msg void OnViewCaptionBar();
    afx_msg void OnUpdateViewCaptionBar(CCmdUI* pCmdUI);
  5. Add the following bitmap to resources and name it IDB_INFO (first, convert from PNG to BMP).
  6. [info.png]

  7. Define the body for the three methods:
  8. bool CMainFrame::InitializeCaptionBar()
       if (!m_wndCaptionBar.Create(WS_CHILD | WS_VISIBLE |
          -1, TRUE))
          TRACE0("Failed to create caption bar\n");
          return false;
          _T("This is a caption bar where a message can be
             presented to the user."),
       m_wndCaptionBar.SetBitmap(IDB_INFO, RGB(255, 255, 255),
          FALSE, CMFCCaptionBar::ALIGN_LEFT);
          _T("Here is an informational message for the user."));
       return true;
    void CMainFrame::OnViewCaptionBar()
          ? SW_HIDE : SW_SHOW);
    void CMainFrame::OnUpdateViewCaptionBar(CCmdUI* pCmdUI)
  9. Call InitializeCaptionBar() from OnCreate().
  10. Add the following commands to the message map:

The application should look like this:



The steps I've walked you through show how to transform an MDI application to enable the Office 2007 look and feel. Basically, the same can be achieved if you select Office for the Project Style when you create a new MFC application from Visual Studio. I consider that the hard-way approach should give better clarification on how to enable or customize different elements. Hopefully, this article can help you to start enabling the Office look and feel for your applications.

This article was originally published on Tuesday Mar 11th 2008
Mobile Site | Full Site