演练:更新 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 应用程序中的基类
在 scribble.cpp 中,验证
CScribbleApp::InitInstance
是否包含对 AfxOleInit 的调用。将以下代码添加到 pch.h 文件中(Visual Studio 2017 及更低版本中的 stdafx.h):
#include <afxcontrolbars.h>
在 scribble.h 中,修改
CScribbleApp
类的定义,使其派生自 CWinAppEx 类。class CScribbleApp: public CWinAppEx
Scribble 1.0 是在 Windows 应用程序使用初始化 (.ini) 文件来保存用户首选项数据时编写的。 与其初始化文件,不如修改 Scribble,以将用户首选项存储在注册表中。 要设置注册表项和基础映像,请在
LoadStdProfileSettings()
语句之后的CScribbleApp::InitInstance
中键入以下代码。SetRegistryKey(_T("MFCNext\\Samples\\Scribble2")); SetRegistryBase(_T("Settings"));
多文档界面 (MDI) 应用程序的主框架不再派生自
CMDIFrameWnd
类, 而是改为派生自 CMDIFrameWndEx 类。在 mainfrm.h 和 mainfrm.cpp 文件中,将所有对
CMDIFrameWnd
的引用替换为CMDIFrameWndEx
。在 childfrm.h 和 childfrm.cpp 文件中,将
CMDIChildWnd
替换为CMDIChildWndEx
。在 childfrm. h 文件中,将
CSplitterWnd
替换为CSplitterWndEx
。修改工具栏和状态栏以使用新的 MFC 类。
在 mainfrm.h 文件中:
将
CToolBar
替换为CMFCToolBar
。将
CStatusBar
替换为CMFCStatusBar
。
在 mainfrm.cpp 文件中:
将
m_wndToolBar.SetBarStyle
替换为m_wndToolBar.SetPaneStyle
将
m_wndToolBar.GetBarStyle
替换为m_wndToolBar.GetPaneStyle
将
DockControlBar(&m_wndToolBar)
替换为DockPane(&m_wndToolBar)
在 ipframe.cpp 文件中,注释掉以下三行代码。
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); pWndFrame->EnableDocking(CBRS_ALIGN_ANY); pWndFrame->DockPane(&m_wndToolBar);
保存更改,然后生成并运行应用程序。
将位图添加到项目中
本演练接下来的四个步骤需要位图资源。 可以通过各种方式获取适当的位图:
使用资源编辑器创建自己的位图。 也可使用资源编辑器从 Visual Studio 中包含的可移植网络图形 (.png) 图像组合位图,这些位图可以从 Visual Studio 图像库下载。
但是,功能区用户界面要求某些位图支持透明图像。 透明位图使用 32 位像素,其中 24 位指定红色、绿色和蓝色的色差分量,8 位定义用于指定颜色透明度的 alpha 通道。 当前的资源编辑器可以查看但不能修改使用 32 位像素的位图。 因此,使用外部图像编辑器(而不是资源编辑器)来操作透明位图。
将相应的资源文件从其他应用程序复制到项目中,然后从该文件导入位图。
本演练从演练:使用 MFC 创建功能区应用程序中创建的示例复制资源文件。
将位图添加到项目中
使用文件资源管理器将以下 .bmp 文件从功能区示例的资源目录 (
res
) 复制到 Scribble 项目的资源目录 (res
):将 main.bmp 复制到 Scribble 项目中。
将 filesmall.bmp 和 filelarge.bmp 复制到 Scribble 项目中。
创建 filelarge.bmp 和 filesmall.bmp 文件的新副本,但将副本保存在功能区示例中。 将副本重命名为 homesmall.bmp 和 homelarge.bmp,然后将副本移至 Scribble 项目中。
创建 toolbar.bmp 文件的副本,但将副本保存在功能区示例中。 将副本重命名为 panelicons.bmp,然后将副本移至 Scribble 项目。
为 MFC 应用程序导入位图。 在“资源视图”中,依次双击“scribble.rc”节点和“位图”节点,然后单击“添加资源”。 在出现的对话框中,单击“导入”。 浏览到
res
目录,选择 main.bmp 文件,然后单击“打开”。main.bmp 位图包含一个 26x26 的图像。 将位图的 ID 更改为
IDB_RIBBON_MAIN
。为附加到“应用程序”按钮的文件菜单导入位图。
- 导入 filesmall.bmp 文件,其中包含 11 个 16x16 (16x176) 的图像。 将位图的 ID 更改为
IDB_RIBBON_FILESMALL
。
注意
由于我们只需要前八个 16x16 (16x128) 的图像,因此可以选择性地将此位图的右侧宽度从 176 裁剪为 128。
- 导入包含九个 32x32 (32x288) 的图像的 filelarge.bmp。 将位图的 ID 更改为
IDB_RIBBON_FILELARGE
。
- 导入 filesmall.bmp 文件,其中包含 11 个 16x16 (16x176) 的图像。 将位图的 ID 更改为
导入功能区类别和面板的位图。 功能区栏上的每个选项卡都是一个类别,并由一个文本标签和一个可选图像组成。
导入 homesmall.bmp 位图,其中包含用于小按钮位图的 11 个 16x16 的图像。 将位图的 ID 更改为
IDB_RIBBON_HOMESMALL
。导入 homelarge.bmp 位图,其中包含用于大按钮位图的 9 个 32x32 的图像。 将位图的 ID 更改为
IDB_RIBBON_HOMELARGE
。
为重设大小的功能区面板导入位图。 如果功能区太小而无法显示整个面板,请在执行重设大小操作后使用这些位图或面板图标。
- 导入 panelicons.bmp 位图,其中包含八个 16x16 的图像。 在“位图编辑器”的“属性”窗口中,将位图的宽度调整为 64 (16x64)。 将位图的 ID 更改为
IDB_PANEL_ICONS
。
注意
由于我们只需要前四个 16x16 (16x64) 的图像,因此可以选择性地将此位图的右侧宽度从 128 裁剪为 64。
- 导入 panelicons.bmp 位图,其中包含八个 16x16 的图像。 在“位图编辑器”的“属性”窗口中,将位图的宽度调整为 64 (16x64)。 将位图的 ID 更改为
将功能区资源添加到项目中
如果将使用菜单的应用程序转换为使用功能区的应用程序,则不必删除或禁用现有菜单。 只需创建功能区资源,添加功能区按钮,然后将新按钮与现有菜单项相关联即可。 虽然菜单不再可见,但来自功能区栏的消息通过菜单路由,并且菜单快捷方式将继续工作。
功能区由“应用程序”按钮(位于功能区左上角的大按钮)和一个或多个类别选项卡组成。 每个类别选项卡都包含一个或多个面板,这些面板充当功能区按钮和控件的容器。 以下过程说明如何创建功能区资源,然后自定义“应用程序”按钮。
将功能区资源添加到项目中
在“解决方案资源管理器”中选择 Scribble 项目后,在“项目”菜单中,单击“添加资源”。
在“添加资源”对话框中,选择“功能区”,然后单击“新建”。
Visual Studio 会创建一个功能区资源并在设计视图中打开它。 功能区资源 ID 为
IDR_RIBBON1
,它显示在“资源视图”中。 功能区包含一个类别和一个面板。可以通过修改其属性来自定义“应用程序”按钮。 此代码中使用的消息 ID 已在 Scribble 1.0 的菜单中定义。
在设计视图中,单击“应用程序”按钮以显示其属性。 按如下所示更改属性值:将“图像”更改为
IDB_RIBBON_MAIN
,将“提示”更改为File
,将“键”更改为f
,将“大图像”更改为IDB_RIBBON_FILELARGE
,将“小图像”更改为IDB_RIBBON_FILESMALL
。以下修改将创建用户单击“应用程序”按钮时出现的菜单。 单击“主项”旁边的省略号 (...) 以打开“项编辑器”。
选择“项”类型按钮后,单击“添加”以添加按钮。 将“标题”更改为
&New
,将“ID”更改为ID_FILE_NEW
,将“图像”更改为0
,将“大图像”更改为0
。单击“添加”以添加按钮。 将“标题”更改为
&Save
,将“ID”更改为ID_FILE_SAVE
,将“图像”更改为2
,并将“大图像”更改为2
。单击“添加”以添加按钮。 将“标题”更改为
Save &As
,将“ID”更改为ID_FILE_SAVE_AS
,将“图像”更改为3
,并将“大图像”更改为3
。单击“添加”以添加按钮。 将“标题”更改为
&Print
,将“ID”更改为ID_FILE_PRINT
,将“图像”更改为4
,并将“大图像”更改为4
。将“项”类型更改为“分隔符”,然后单击“添加”。
将“项”类型更改为“按钮”。 单击“添加”以添加第五个按钮。 将“标题”更改为
&Close
,将“ID”更改为ID_FILE_CLOSE
,将“图像”更改为5
,并将“大图像”更改为5
。
以下修改将在上一步中创建的“打印”按钮下创建子菜单。
单击“打印”按钮,将“项”类型更改为“标签”,然后单击“插入”。 将“标题栏”更改为
Preview and print the document
。单击“打印”按钮,将“项”类型更改为“按钮”,然后单击“插入”。 将“标题”更改为
&Print
,将“ID”更改为ID_FILE_PRINT
,将“图像”更改为4
,并将“大图像”更改为4
。单击“打印”按钮,然后单击“插入”以添加按钮。 将“标题”更改为
&Quick Print
,将“ID”更改为ID_FILE_PRINT_DIRECT
,将“图像”更改为7
,并将“大图像”更改为7
。单击“打印”按钮,然后单击“插入”以添加另一个按钮。 将“标题”更改为
Print Pre&view
,将“ID”更改为ID_FILE_PRINT_PREVIEW
,将“图像”更改为6
,并将“大图像”更改为6
。现已修改“主项”。 单击“关闭”以退出“项编辑器”。
以下修改将创建“退出”按钮,该按钮显示在“应用程序”按钮菜单的底部。
在“解决方案资源管理器”中选择“资源视图”选项卡。
在“属性”窗口中,单击“按钮”旁边的省略号 (...) 以打开“项编辑器”。
选择“项”类型按钮后,单击“添加”以添加按钮。 将“标题”更改为
E&xit
,将“ID”更改为ID_APP_EXIT
,将“图像”更改为8
。你已修改“按钮”。 单击“关闭”以退出“项编辑器”。
创建功能区栏的实例
以下步骤显示如何在应用程序启动时创建功能区栏的实例。 要将功能区栏添加到应用程序,请在 mainfrm.h 文件中声明功能区栏。 然后,在 mainfrm.cpp 文件中,编写用于加载功能区资源的代码。
创建功能区栏的实例
在 mainfrm.h 文件中,将数据成员添加到
CMainFrame
的受保护部分,即主框架的类定义。 此成员仅用于功能区栏。// Ribbon bar for the application CMFCRibbonBar m_wndRibbonBar;
在 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);
自定义功能区资源
现在你已创建“应用程序”按钮,可以将元素添加到功能区中了。
注意
本演练对所有面板使用相同的面板图标。 不过,你也可以使用其他图像列表索引来显示其他图标。
添加“主页”类别和“编辑”面板
Scribble 程序只需要一个类别。 在设计视图的“工具箱”中,双击“类别”以添加一个类别并显示其属性。 按如下所示更改属性值:将“标题”更改为
&Home
,将“大图像”更改为IDB_RIBBON_HOMELARGE
,将“小图像”更改为IDB_RIBBON_HOMESMALL
。每个功能区类别都组织到命名面板中。 每个面板都包含一组用于完成相关操作的控件。 此类别有一个面板。 单击“面板”,然后将“标题”更改为
Edit
。在“编辑”面板中,添加一个负责清除文档内容的按钮。 此按钮的消息 ID 已在
IDR_SCRIBBTYPE
菜单资源中定义。 将Clear All
指定为用于装饰按钮的按钮文本和位图索引。 打开“工具箱”,然后将“按钮”拖到“编辑”面板。 单击该按钮,然后将“标题”更改为Clear All
,将“ID”更改为ID_EDIT_CLEAR_ALL
,将“图像索引”更改为0
,将“大图像索引”更改为0
。保存更改,然后生成并运行应用程序。 此时应会显示 Scribble 应用程序,并且该应用程序的窗口顶部应有一个功能区栏(而不是菜单栏)。 功能区栏应该有一个“主页”类别,而“主页”应该有一个“编辑”面板。 添加的功能区按钮应与现有事件处理程序相关联,“打开”、“关闭”、“保存”、“打印”和“清除所有”按钮应按预期方式工作。
设置应用程序的外观
虚拟管理器是用于控制应用程序所有绘图的全局对象。 由于原始的 Scribble 应用程序使用 Office 2000 用户界面 (UI) 样式,因此该应用程序的外观可能已过时。 可以重置应用程序以使用 Office 2007 虚拟管理器,使其类似于 Office 2007 应用程序。
设置应用程序的外观
在
CMainFrame::OnCreate
函数中,在return 0;
语句之前键入以下代码,以更改默认虚拟管理器和样式。// Set the default manager to Office 2007 CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007)); CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
保存更改,然后生成并运行应用程序。 应用程序 UI 应类似于 Office 2007 UI。
后续步骤
你已将经典的 Scribble 1.0 MFC 示例修改为使用“功能区设计器”。 现在转到第 2 部分。