Walkthrough: Updating the MFC Scribble Application (Part 1)

This walkthrough demonstrates how you can modify an exisiting MFC application to use the new Office Fluent Ribbon user interface that was introduced in the 2007 Microsoft Office release. For more information about the Office Fluent Ribbon user interface, see "Office Fluent User Interface Developer Portal" at the MSDN Library.

This walkthrough modifies the classic Scribble 1.0 MFC sample that lets you use the mouse to create line drawings. Part 1 of this walkthrough shows you how to modify the Scribble sample so that it displays a ribbon bar. Part 2 of this walkthrough adds more buttons to the ribbon bar.

Prerequisites

SCRIBBLE Sample: MFC MDI Drawing Application

RibbonGadgets Sample: Ribbon Gadgets Application

Sections

Part 1 of this walkthrough has the following sections:

  • Replacing the Base Classes

  • Adding a Ribbon to the Application

  • Adding Bitmaps to the Ribbon

  • Creating an Instance of the Ribbon Bar

  • Adding a Ribbon Category

  • Setting the Look of the Application

Replacing the Base Classes

To convert an application that supports a menu to an application that supports a ribbon, you must derive the application, frame window, and toolbar classes from base classes provided by the Visual C++ 2008 Feature Pack. (We suggest that you do not modify the original Scribble sample but that you clean the Scribble project, copy it to another directory, and then modify the copy.)

To replace the base classes in the Scribble application

  1. In scribble.cpp, verify that CScribbleApp::InitInstance includes a call to AfxOleInit.

  2. Add the following code to the stdafx.h file.

    #include <afxcontrolbars.h>
    
  3. In scribble.h, modify the definition for the CScribbleApp class so that it is derived from CWinAppEx Class.

    class CScribbleApp: public CWinAppEx
    
  4. Scribble 1.0 was written when Windows applications used an initialization (.ini) file to save user preference data. Instead of an initialization file, modify Scribble to store user preferences in the registry. To set the registry key and base, type the following code in CScribbleApp::InitInstance after the LoadStdProfileSettings() statement.

    SetRegistryKey(_T("MFCNext\\Samples\\Scribble2"));
    SetRegistryBase(_T("Settings"));
    
  5. In the Visual C++ 2008 Feature Pack, the main frame for a multiple document interface (MDI) application is no longer derived from the CMDIFrameWnd class. Instead, it is derived from the CMDIFrameWndEx class.

    In the mainfrm.h and mainfrm.cpp files, replace all references to CMDIFrameWnd with CMDIFrameWndEx.

  6. In the childfrm.h and childfrm.cpp files, replace CMDIChildWnd with CMDIChildWndEx.

    In the childfrm. h file, replace CSplitterWnd with CSplitterWndEx.

  7. Modify toolbars and status bars to use the new MFC classes.

    In the mainfrm.h file:

    1. Replace CToolBar with CMFCToolBar.

    2. Replace CStatusBar with CMFCStatusBar.

  8. In the mainfrm.cpp file:

    1. Replace m_wndToolBar.SetBarStyle with m_wndToolBar.SetPaneStyle

    2. Replace m_wndToolBar.GetBarStyle with m_wndToolBar.GetPaneStyle

    3. Replace DockControlBar(&m_wndToolBar) with DockPane(&m_wndToolBar)

  9. In the ipframe.cpp file, comment out the following three lines of code.

    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    pWndFrame->EnableDocking(CBRS_ALIGN_ANY);
    pWndFrame->DockPane(&m_wndToolBar);
    
  10. Add the following code to the start of your project's resource (.rc) file if you intend to link your application statically.

    #include "afxribbon.rc"
    

    The afxribbon.rc file contains resources that are required at run time if your migrated application uses the dialog boxes or strings in the Visual C++ 2008 Feature Pack. The MFC Application Wizard includes this file automatically when you create a new application.

  11. Save the changes and then build and run the application.

[go to top]

Adding a Ribbon to the Application

When you convert an application that uses menus to an application that uses a ribbon, you do not have to remove or disable the existing menus. Instead, you create the ribbon bar, add ribbon buttons, and then associate the new buttons with the existing menu items. Although the menus are no longer visible, messages from the ribbon bar are routed through the menus. In addition, menu shortcuts continue to work.

A ribbon bar consists of the Application button, which is the large button on the upper-left side of the ribbon, and one or more tabs. Each tab contains one or more panels that act as containers for ribbon buttons and controls.

To add a ribbon bar to an application, declare the ribbon bar in the mainfrm.h file. In the mainfrm.cpp file, write code to add controls to the ribbon bar.

To add a ribbon to the application

  1. In the mainfrm.h file, add two data members to the protected section of CMainFrame, the class definition for the main frame. These members represent the ribbon bar and the Application button.

    // Ribbon bar for the application
    CMFCRibbonBar  m_wndRibbonBar;
    // The application button for the ribbon
    CMFCRibbonApplicationButton  m_MainButton;
    
  2. After the previous two members, add a data member for the image list that is used by ribbon panels. These images are visible only when the user resizes the application, and therefore, the ribbon.

    // Ribbon panel icons
    CMFCToolBarImages  m_PanelImages;
    

[go to top]

Adding Bitmaps to the Ribbon

The next four steps of this walkthrough require bitmap resources. You can obtain appropriate bitmaps in various ways:

  • Use the Resource Editors to invent your own bitmaps. Or use the resource editors to assemble bitmaps from the portable network graphics (.png) images that are included with Visual Studio. These images are in the VS2008ImageLibrary directory. 

    However, the Ribbon user interface requires that certain bitmaps support transparent images. Transparent bitmaps have a 32-bit color depth, where 24 bits specify the red, green, and blue components of the color, and 8 bits define an alpha channel that specifies the transparency of the color. The current resource editors can view, but not modify bitmaps with a 32-bit color depth. Consequently, use an external image editor instead of the resource editors to manipulate transparent bitmaps.

  • Copy an appropriate resource file from another application to your project and then import bitmaps from that file.

This walkthrough copies resource files from an application in the Samples directory.

To add bitmaps to the ribbon

  1. Use the Windows Explorer to copy the following .bmp files from the resources directory (res) of the the RibbonGadgets sample:

    1. Copy main.bmp to your Scribble project.

    2. Copy filesmall.bmp and filelarge.bmp to your Scribble project.

    3. Make new copies of the filelarge.bmp and filesmall.bmp files, but save the copies in the RibbonGadgets sample. Rename the copies homesmall.bmp and homelarge.bmp and then move the copies to your Scribble project.

    4. Make a copy of the toolbar.bmp file, but save the copy in the RibbonGadgets sample. Rename the copy panelicons.bmp and then move the copy to your Scribble project.

  2. Import the bitmap for an MFC application. In Resource View, double-click the scribble.rc node, double-click the Bitmap node, and then click Add resource. On the dialog box that appears, click the Import button. Browse to the res directory, select the main.bmp file, and then click the Open button.

    The main.bmp bitmap contains a 26x26 image. Change the ID of the bitmap to IDB_RIBBON_MAIN.

  3. Import the bitmaps for the file menu that is attached to the Application button.

    1. Import the filesmall.bmp file, which contains ten 16x16 (16x160) images. Because we need only eight 16x16 images (16x128), use the Resource View to change the width of that bitmap from 160 to 128. Change the ID of the bitmap to IDB_RIBBON_FILESMALL.

    2. Import the filelarge.bmp, which contains eight 32x32 (32x256) images. Change the ID of the bitmap to IDB_RIBBON_FILELARGE.

  4. Import the bitmaps for the ribbon categories and panels. Each tab on the ribbon bar is a category, and consists of a text label and an optional image.

    1. Import the homesmall.bmp bitmap, which contains eight 16x16 images for small button bitmaps. Change the ID of the bitmap to IDB_RIBBON_HOMESMALL.

    2. Import the homelarge.bmp bitmap, which contains eight 32x32 images for large button bitmaps. Change the ID of the bitmap to IDB_RIBBON_HOMELARGE.

  5. Import bitmaps for the resized ribbon panels. These bitmaps, or panel icons, are used after a resize operation if the ribbon is too small to display the entire panel.

    1. Import the panelicons.bmp bitmap, which contains eight 16x16 images. In the Properties window of the Bitmap Editor, adjust the width of the bitmap to 64 (16x64). Change the ID of the bitmap to IDB_PANEL_ICONS.

[go to top]

Creating an Instance of the Ribbon Bar

The following procedure shows you how to create an instance of the ribbon bar when your application starts. Then the procedure shows you how to initialize the menu items and images that are associated with the Application button.

To create an instance of the ribbon bar

  1. In the mainfrm.cpp file, add the following code before the final return statement at the end of the CMainFrame::OnCreate function. This creates an instance of the ribbon bar.

    // Create the ribbon bar
    if (!m_wndRibbonBar.Create(this))
    {
    return -1;   //Failed to create ribbon bar
    }
    
  2. Add the following code after the statements in the previous step. This code loads images for the ribbon panels and Application button; then attach the Application button to the ribbon.

    // Load images for ribbon panels
    m_PanelImages.SetImageSize(CSize(16,16));
    m_PanelImages.Load(IDB_PANEL_ICONS);
    // Initialize the application button
    m_MainButton.SetImage(IDB_RIBBON_MAIN);
    m_MainButton.SetToolTipText(_T("File"));
    m_MainButton.SetText(_T("\nf"));
    // Attach the application button to the ribbon
    m_wndRibbonBar.SetApplicationButton(&m_MainButton, CSize(45,45));
    
  3. Add the following code after the statements in the previous step. This code creates the menu that appears when the user presses the Application button. The message IDs used in this code are already defined in the menu for Scribble 1.0.

    CMFCRibbonMainPanel* pMainPanel = m_wndRibbonBar.AddMainCategory(
    _T("File"), IDB_RIBBON_FILESMALL, IDB_RIBBON_FILELARGE);
    pMainPanel->Add(new CMFCRibbonButton(
    ID_FILE_NEW, _T("&New"), 0, 0));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_OPEN, _T("&Open..."), 1, 1));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_CLOSE, _T("&Close"), 5, 5));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE, _T("&Save"), 2, 2));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_SAVE_AS, _T("Save &As..."), 3, 3));
    CMFCRibbonButton* pBtnPrint = new CMFCRibbonButton(ID_FILE_PRINT, _T("&Print"), 4, 4);
    pBtnPrint->AddSubItem(new CMFCRibbonLabel(_T("Preview and print the document")));
    pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT, _T("&Print"), 4, 4, TRUE));
    pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT_DIRECT, _T("&Quick Print"), 7, 7, TRUE));
    pBtnPrint->AddSubItem(new CMFCRibbonButton(ID_FILE_PRINT_PREVIEW, _T("Print Pre&view"), 6, 6, TRUE));
    pBtnPrint->SetKeys(_T("p"), _T("w"));
    pMainPanel->Add(pBtnPrint);
    pMainPanel->Add(new CMFCRibbonSeparator(TRUE));
    pMainPanel->Add(new CMFCRibbonButton(ID_FILE_CLOSE, _T("&Close"), 5, 5));
    pMainPanel->AddRecentFilesList(_T("Recent Documents"));
    pMainPanel->AddToBottom(new CMFCRibbonMainPanelButton(ID_APP_EXIT, _T("E&xit"), 8));
    

[go to top]

Adding a Ribbon Category

Now that you have created the Application button, you are ready to add the first ribbon category and ribbon panel. Each category defines a tab that appears on the ribbon. (This walkthrough uses the same panel icon for all panels. However, you can experiment and use other image list indexes to display other icons.)

To add a Home category and Edit panel

  1. The Scribble program requires only a single category. Name this category Home. Add the following code after the statements in the previous procedure.

    // Add a Home category to the ribbon bar.
    CMFCRibbonCategory* pCategory = m_wndRibbonBar.AddCategory(
    _T("&Home"),           // Category name
       IDB_RIBBON_HOMESMALL,    // Category small images (16 x 16)
       IDB_RIBBON_HOMELARGE);   // Category large images (32 x 32)
    
  2. Each ribbon category is organized into named panels. Each panel contains a set of controls that perform related operations. Add the following code to create a panel that handles editing functions. Name this panel Edit.

    // Add an Edit panel to the Home category.
    CMFCRibbonPanel* pPanelEdit = pCategory->AddPanel(
        _T("Edit"),                // Panel name
        m_PanelImages.ExtractIcon(0));  // Panel icon
    
  3. Add a button to the Edit panel that is responsible for clearing the contents of the document. The message ID for this button has already been defined in the IDR_SCRIBBTYPE menu resource. Specify Clear All as the button text and the index of the bitmap that decorates the button.

    // Add a Clear All button to the Edit panel.
    pPanelEdit->Add(new CMFCRibbonButton(ID_EDIT_CLEAR_ALL, _T("Clear All"), 0));
    
  4. Save the changes and then build and run the application. You should see the familiar Scribble application, but with a ribbon bar at the top of the window instead of a menu bar. The ribbon bar has one category, Home, with one panel, Edit.

    The ribbon buttons that you added are associated with the existing event handlers, and the Open, Close, Save, Print, and Clear All buttons work as they did previously.

[go to top]

Setting the Look of the Application

A visual manager is a global object that controls all drawing for an application. Because this application uses the default GUI style (Office 2000), the application looks a bit old-fashioned. This walkthrough uses the Office 2007 visual manager to make the Scribble application resemble a modern Office 2007 application.

To set the look of the application

  1. In the CMainFrame::OnCreate function, type the following code to change the default manager and style.

    // Set the default manager to Office 2007 
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
    
  2. Save the changes and then build and run the application. The application user interface should resemble the Office 2007 user interface.

[go to top]

Congratulations!

You have completed Part 1 of the walkthrough. Now go to Part 2.

See Also

Tasks

Walkthrough: Updating the MFC Scribble Application (Part 2)

SCRIBBLE Sample: MFC MDI Drawing Application

Other Resources

Walkthroughs (MFC Feature Pack)