演练:更新 MFC Scribble 应用程序(第 1 部分)

本演练演示如何修改现有 MFC 应用程序来使用功能区用户界面。 Visual Studio 支持 Office 2007 功能区和 Windows 7 场景功能区。 有关功能区用户界面的详细信息,请参阅功能区

本演练修改了经典的 Scribble 1.0 MFC 示例,使你可以使用鼠标创建线条图。 该演练部分介绍如何修改 Scribble 示例以使其显示功能区栏。 第 2 部分会将更多按钮添加到功能区栏。

先决条件

Scribble 1.0 MFC 示例。 有关转换为 Visual Studio 2017 或更高版本的帮助,请参阅移植指南:MFC Scribble

章节

该演练部分包含下列内容:

替换基类

要将支持菜单的应用程序转换为支持功能区的应用程序,必须从更新后的基类派生应用程序、框架窗口和工具栏类。 (建议不要修改原始的 Scribble 示例,而是改为清理 Scribble 项目,将其复制到另一个目录,然后修改副本。)

替换 Scribble 应用程序中的基类

  1. 在 scribble.cpp 中,验证 CScribbleApp::InitInstance 是否包含对 AfxOleInit 的调用。

  2. 将以下代码添加到 pch.h 文件中(Visual Studio 2017 及更低版本中的 stdafx.h)

    #include <afxcontrolbars.h>
    
  3. 在 scribble.h 中,修改 CScribbleApp 类的定义,使其派生自 CWinAppEx 类

    class CScribbleApp: public CWinAppEx
    
  4. Scribble 1.0 是在 Windows 应用程序使用初始化 (.ini) 文件来保存用户首选项数据时编写的。 与其初始化文件,不如修改 Scribble,以将用户首选项存储在注册表中。 要设置注册表项和基础映像,请在 LoadStdProfileSettings() 语句之后的 CScribbleApp::InitInstance 中键入以下代码。

    SetRegistryKey(_T("MFCNext\\Samples\\Scribble2"));
    SetRegistryBase(_T("Settings"));
    
  5. 多文档界面 (MDI) 应用程序的主框架不再派生自 CMDIFrameWnd 类, 而是改为派生自 CMDIFrameWndEx 类。

    在 mainfrm.h 和 mainfrm.cpp 文件中,将所有对 CMDIFrameWnd 的引用替换为 CMDIFrameWndEx

  6. 在 childfrm.h 和 childfrm.cpp 文件中,将 CMDIChildWnd 替换为 CMDIChildWndEx

    在 childfrm. h 文件中,将 CSplitterWnd 替换为 CSplitterWndEx

  7. 修改工具栏和状态栏以使用新的 MFC 类。

    在 mainfrm.h 文件中:

    1. CToolBar 替换为 CMFCToolBar

    2. CStatusBar 替换为 CMFCStatusBar

  8. 在 mainfrm.cpp 文件中:

    1. m_wndToolBar.SetBarStyle 替换为 m_wndToolBar.SetPaneStyle

    2. m_wndToolBar.GetBarStyle 替换为 m_wndToolBar.GetPaneStyle

    3. DockControlBar(&m_wndToolBar) 替换为 DockPane(&m_wndToolBar)

  9. 在 ipframe.cpp 文件中,注释掉以下三行代码。

    m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    pWndFrame->EnableDocking(CBRS_ALIGN_ANY);
    pWndFrame->DockPane(&m_wndToolBar);
    
  10. 保存更改,然后生成并运行应用程序。

将位图添加到项目中

本演练接下来的四个步骤需要位图资源。 可以通过各种方式获取适当的位图:

  • 使用资源编辑器创建自己的位图。 也可使用资源编辑器从 Visual Studio 中包含的可移植网络图形 (.png) 图像组合位图,这些位图可以从 Visual Studio 图像库下载。

    但是,功能区用户界面要求某些位图支持透明图像。 透明位图使用 32 位像素,其中 24 位指定红色、绿色和蓝色的色差分量,8 位定义用于指定颜色透明度的 alpha 通道。 当前的资源编辑器可以查看但不能修改使用 32 位像素的位图。 因此,使用外部图像编辑器(而不是资源编辑器)来操作透明位图。

  • 将相应的资源文件从其他应用程序复制到项目中,然后从该文件导入位图。

本演练从演练:使用 MFC 创建功能区应用程序中创建的示例复制资源文件。

将位图添加到项目中

  1. 使用文件资源管理器将以下 .bmp 文件从功能区示例的资源目录 (res) 复制到 Scribble 项目的资源目录 (res):

    1. 将 main.bmp 复制到 Scribble 项目中。

    2. 将 filesmall.bmp 和 filelarge.bmp 复制到 Scribble 项目中。

    3. 创建 filelarge.bmp 和 filesmall.bmp 文件的新副本,但将副本保存在功能区示例中。 将副本重命名为 homesmall.bmp 和 homelarge.bmp,然后将副本移至 Scribble 项目中。

    4. 创建 toolbar.bmp 文件的副本,但将副本保存在功能区示例中。 将副本重命名为 panelicons.bmp,然后将副本移至 Scribble 项目。

  2. 为 MFC 应用程序导入位图。 在“资源视图”中,依次双击“scribble.rc”节点和“位图”节点,然后单击“添加资源”。 在出现的对话框中,单击“导入”。 浏览到 res 目录,选择 main.bmp 文件,然后单击“打开”

    main.bmp 位图包含一个 26x26 的图像。 将位图的 ID 更改为 IDB_RIBBON_MAIN

  3. 为附加到“应用程序”按钮的文件菜单导入位图

    1. 导入 filesmall.bmp 文件,其中包含 11 个 16x16 (16x176) 的图像。 将位图的 ID 更改为 IDB_RIBBON_FILESMALL

    注意

    由于我们只需要前八个 16x16 (16x128) 的图像,因此可以选择性地将此位图的右侧宽度从 176 裁剪为 128。

    1. 导入包含九个 32x32 (32x288) 的图像的 filelarge.bmp。 将位图的 ID 更改为 IDB_RIBBON_FILELARGE
  4. 导入功能区类别和面板的位图。 功能区栏上的每个选项卡都是一个类别,并由一个文本标签和一个可选图像组成。

    1. 导入 homesmall.bmp 位图,其中包含用于小按钮位图的 11 个 16x16 的图像。 将位图的 ID 更改为 IDB_RIBBON_HOMESMALL

    2. 导入 homelarge.bmp 位图,其中包含用于大按钮位图的 9 个 32x32 的图像。 将位图的 ID 更改为 IDB_RIBBON_HOMELARGE

  5. 为重设大小的功能区面板导入位图。 如果功能区太小而无法显示整个面板,请在执行重设大小操作后使用这些位图或面板图标。

    1. 导入 panelicons.bmp 位图,其中包含八个 16x16 的图像。 在“位图编辑器”的“属性”窗口中,将位图的宽度调整为 64 (16x64)。 将位图的 ID 更改为 IDB_PANEL_ICONS

    注意

    由于我们只需要前四个 16x16 (16x64) 的图像,因此可以选择性地将此位图的右侧宽度从 128 裁剪为 64。

将功能区资源添加到项目中

如果将使用菜单的应用程序转换为使用功能区的应用程序,则不必删除或禁用现有菜单。 只需创建功能区资源,添加功能区按钮,然后将新按钮与现有菜单项相关联即可。 虽然菜单不再可见,但来自功能区栏的消息通过菜单路由,并且菜单快捷方式将继续工作。

功能区由“应用程序”按钮(位于功能区左上角的大按钮)和一个或多个类别选项卡组成。 每个类别选项卡都包含一个或多个面板,这些面板充当功能区按钮和控件的容器。 以下过程说明如何创建功能区资源,然后自定义“应用程序”按钮

将功能区资源添加到项目中

  1. 在“解决方案资源管理器”中选择 Scribble 项目后,在“项目”菜单中,单击“添加资源”

  2. 在“添加资源”对话框中,选择“功能区”,然后单击“新建”

    Visual Studio 会创建一个功能区资源并在设计视图中打开它。 功能区资源 ID 为 IDR_RIBBON1,它显示在“资源视图”中。 功能区包含一个类别和一个面板。

  3. 可以通过修改其属性来自定义“应用程序”按钮。 此代码中使用的消息 ID 已在 Scribble 1.0 的菜单中定义。

  4. 在设计视图中,单击“应用程序”按钮以显示其属性。 按如下所示更改属性值:将“图像”更改为 IDB_RIBBON_MAIN,将“提示”更改为 File,将“键”更改为 f,将“大图像”更改为 IDB_RIBBON_FILELARGE,将“小图像”更改为 IDB_RIBBON_FILESMALL

  5. 以下修改将创建用户单击“应用程序”按钮时出现的菜单。 单击“主项”旁边的省略号 (...) 以打开“项编辑器”

    1. 选择“项”类型按钮后,单击“添加”以添加按钮。 将“标题”更改为 &New,将“ID”更改为 ID_FILE_NEW,将“图像”更改为 0,将“大图像”更改为 0

    2. 单击“添加”以添加按钮。 将“标题”更改为 &Save,将“ID”更改为 ID_FILE_SAVE,将“图像”更改为 2,并将“大图像”更改为 2

    3. 单击“添加”以添加按钮。 将“标题”更改为 Save &As,将“ID”更改为 ID_FILE_SAVE_AS,将“图像”更改为 3,并将“大图像”更改为 3

    4. 单击“添加”以添加按钮。 将“标题”更改为 &Print,将“ID”更改为 ID_FILE_PRINT,将“图像”更改为 4,并将“大图像”更改为 4

    5. 将“项”类型更改为“分隔符”,然后单击“添加”

    6. 将“项”类型更改为“按钮”。 单击“添加”以添加第五个按钮。 将“标题”更改为 &Close,将“ID”更改为 ID_FILE_CLOSE,将“图像”更改为 5,并将“大图像”更改为 5

  6. 以下修改将在上一步中创建的“打印”按钮下创建子菜单

    1. 单击“打印”按钮,将“项”类型更改为“标签”,然后单击“插入”。 将“标题栏”更改为 Preview and print the document

    2. 单击“打印”按钮,将“项”类型更改为“按钮”,然后单击“插入”。 将“标题”更改为 &Print,将“ID”更改为 ID_FILE_PRINT,将“图像”更改为 4,并将“大图像”更改为 4

    3. 单击“打印”按钮,然后单击“插入”以添加按钮。 将“标题”更改为 &Quick Print,将“ID”更改为 ID_FILE_PRINT_DIRECT,将“图像”更改为 7,并将“大图像”更改为 7

    4. 单击“打印”按钮,然后单击“插入”以添加另一个按钮。 将“标题”更改为 Print Pre&view,将“ID”更改为 ID_FILE_PRINT_PREVIEW,将“图像”更改为 6,并将“大图像”更改为 6

    5. 现已修改“主项”。 单击“关闭”以退出“项编辑器”

  7. 以下修改将创建“退出”按钮,该按钮显示在“应用程序”按钮菜单的底部

    1. 在“解决方案资源管理器”中选择“资源视图”选项卡

    2. 在“属性”窗口中,单击“按钮”旁边的省略号 (...) 以打开“项编辑器”

    3. 选择“项”类型按钮后,单击“添加”以添加按钮。 将“标题”更改为 E&xit,将“ID”更改为 ID_APP_EXIT,将“图像”更改为 8

    4. 你已修改“按钮”。 单击“关闭”以退出“项编辑器”

创建功能区栏的实例

以下步骤显示如何在应用程序启动时创建功能区栏的实例。 要将功能区栏添加到应用程序,请在 mainfrm.h 文件中声明功能区栏。 然后,在 mainfrm.cpp 文件中,编写用于加载功能区资源的代码。

创建功能区栏的实例

  1. 在 mainfrm.h 文件中,将数据成员添加到 CMainFrame 的受保护部分,即主框架的类定义。 此成员仅用于功能区栏。

    // Ribbon bar for the application
    CMFCRibbonBar m_wndRibbonBar;
    
  2. 在 mainfrm.cpp 文件中,在 CMainFrame::OnCreate 函数末尾的最后一个 return 语句之前添加以下代码。 该代码将创建功能区栏的实例。

    // Create the ribbon bar
    if (!m_wndRibbonBar.Create(this))
    {
        return -1;   //Failed to create ribbon bar
    }
    m_wndRibbonBar.LoadFromResource(IDR_RIBBON1);
    

自定义功能区资源

现在你已创建“应用程序”按钮,可以将元素添加到功能区中了

注意

本演练对所有面板使用相同的面板图标。 不过,你也可以使用其他图像列表索引来显示其他图标。

添加“主页”类别和“编辑”面板

  1. Scribble 程序只需要一个类别。 在设计视图的“工具箱”中,双击“类别”以添加一个类别并显示其属性。 按如下所示更改属性值:将“标题”更改为 &Home,将“大图像”更改为 IDB_RIBBON_HOMELARGE,将“小图像”更改为 IDB_RIBBON_HOMESMALL

  2. 每个功能区类别都组织到命名面板中。 每个面板都包含一组用于完成相关操作的控件。 此类别有一个面板。 单击“面板”,然后将“标题”更改为 Edit

  3. 在“编辑”面板中,添加一个负责清除文档内容的按钮。 此按钮的消息 ID 已在 IDR_SCRIBBTYPE 菜单资源中定义。 将 Clear All 指定为用于装饰按钮的按钮文本和位图索引。 打开“工具箱”,然后将“按钮”拖到“编辑”面板。 单击该按钮,然后将“标题”更改为 Clear All,将“ID”更改为 ID_EDIT_CLEAR_ALL,将“图像索引”更改为 0,将“大图像索引”更改为 0

  4. 保存更改,然后生成并运行应用程序。 此时应会显示 Scribble 应用程序,并且该应用程序的窗口顶部应有一个功能区栏(而不是菜单栏)。 功能区栏应该有一个“主页”类别,而“主页”应该有一个“编辑”面板。 添加的功能区按钮应与现有事件处理程序相关联,“打开”、“关闭”、“保存”、“打印”和“清除所有”按钮应按预期方式工作

设置应用程序的外观

虚拟管理器是用于控制应用程序所有绘图的全局对象。 由于原始的 Scribble 应用程序使用 Office 2000 用户界面 (UI) 样式,因此该应用程序的外观可能已过时。 可以重置应用程序以使用 Office 2007 虚拟管理器,使其类似于 Office 2007 应用程序。

设置应用程序的外观

  1. CMainFrame::OnCreate 函数中,在 return 0; 语句之前键入以下代码,以更改默认虚拟管理器和样式。

    // Set the default manager to Office 2007
    CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
    CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
    
  2. 保存更改,然后生成并运行应用程序。 应用程序 UI 应类似于 Office 2007 UI。

后续步骤

你已将经典的 Scribble 1.0 MFC 示例修改为使用“功能区设计器”。 现在转到第 2 部分

另请参阅

演练
演练:更新 MFC 随意画图应用程序(第 2 部分)