第四章 MFC资源统管理

更新时间:2024-07-03 15:06:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第4章 资源和资源编辑器

精讲 VC++集成开发环境提供了资源编辑器,支持窗口应用程序的可视化开发,自动生成和管理资源代码。本章将介绍VC++所支持的资源,及使用资源编辑器编辑资源的方法。学习了本章,你将学会资源编辑器的使用,在应用程序中操作菜单、工具栏和状态栏。

4.1资源与资源编辑器 4.1.1资源和资源符号

资源作为一种界面成分,可以从中获取信息并在其中执行某些动作。VC++6.0可以处理的资源有加速键(Accelerator)、位图(Bitmap)、光标(Cursor)、对话框(Dialog Box)、图标(Icon)、菜单(Menu)、串表(String Table)、工具栏(Toolbar)和版本信息(Version Information)等。

VC++在内部使用资源符号来标识资源,资源符号是映射到某个整数值的一串字符,是一种标识符。从而使资源能够以字符串的方式被引用。每当创建一个新的资源或资源对象时,系统就会为其提供一个默认的资源符号名称并赋一个整数值,该定义保存在resource.h文件中。

Develop Studio提供了资源符号的查看和编辑工具,使用菜单命令View->Resource Symbol来打开资源符号浏览器Resource Symbols对话框,如图4-1所示,列表中列出了当前项目正在使用的资源符号的名称和相应的整数值。若选中“Show read-only symbols”复选框,则只读状态和未被使用的资源符号也一并显示出来。

图4-1 Resource Symbols对话框

在资源符号浏览器Resource Symbols对话框中,可以方便地新建、更改和删除资源符号,单击按钮“View Use”自动进入到某个资源对应的编辑器中。

VC++6简明教程

在同一项目中,资源符号不能重复。资源符号的命名通常带有描述性的前缀来表示所代表的资源或对象类型,表4-1是VC++6.0中提供的一些定义资源符号常用的前缀。

表4-1 资源符号定义的常用前缀

类 别 资源 菜单项命令控制 字符串 资源符号前缀 IDR_ IDD_ IDC_ IDI_ IDB_ IDM_ ID_ IDC_ IDS_ IDP_ 代表的资源或对象 加速键或菜单及相关资源 对话框资源 光标资源 图表资源 位图资源 菜单项 命令项 控件 字符串表中的字符串 消息框中使用的字符串

资源符号的取值有一定的限制。资源(加速键、位图、光标、对话框、图标、菜单、串表、工具栏和版本信息)的符号值范围为十进制的0~32767,而资源控件(如对话框控件或串表中的串)的符号值范围为0~65535或0~32767。

4.1.2资源编辑器

Develop Studio提供了功能强大、易于使用的资源编辑器,用于创建和修改应用程序的资源。使用资源编辑器,可以创建新的资源,修改、拷贝已有的资源,删除不再需要的资源。例如可以用加速键编辑器处理加速键表,用图形编辑器处理图形资源(工具栏、位图、光标和图标等),用对话编辑器处理对话框,用菜单编辑器处理菜单等等。创建或打开资源时,系统将自动打开相应的编辑器。

1. 创建资源

如果要创建新的资源,选择Insert->Resourcre菜单命令,弹出Insert Resourse对话框,如图4-2所示。Resourse Type列表选择资源类型,然后单击“New”按钮。新创建的资源将加入到当前资源(.rc)文件中,相应的资源编辑器也会打开。例如插入一个新的Menu,菜单编辑器就会打开。

112

第4章 MFC应用程序资源和资源编辑器

图4-2 Insert Resourse对话框

2. 编辑资源

VC++提供了可视化工具资源编辑器编辑资源,资源编辑器有很多公共操作。例如,你一旦学会了如何创建和打开一个对话框资源,你就能使用同样的步骤去创建和打开其它的资源。使用资源编辑器能够

(1) 查看资源

(2) 使用资源模板 (3) 导入和导出资源

(4) 查看和编辑属性页

Developer Studio使用项目工作区的ResouceView面板统一组织和管理来查看资源,如图4-3所示。首次打开ResourceView面板时,系统自动压缩每个资源分类,可单击“+”标记来扩展每一分类。

图4-3 项目工作区窗口的ResourceView面板

资源编辑器主要包括:

(1) 对话框编辑器(Dialog Editor) (2) 菜单编辑器(Menu Editor)

113

VC++6简明教程

(3) 加速键编辑器(Accelerator Editor)

(4) 工具栏编辑器(Toolbar Editor) (5) 版本信息编辑器(Version Information Editor) (6) 字符串编辑器(String Editor) (7) 图形编辑器(Graphics Editor) 下面对每一类编辑器的使用作简要介绍: (1) 对话框编辑器

使用对话框编辑器可以创建或编辑一个对话框模板或者对话框资源,如图4-4所示。常用操作包括:

? ? ? ?

增加、删除和编辑控件 改变Tab顺序 布置控件位置 测试一个对话框窗口

Layout菜单 对话框模板 Control工具栏

图4-4 对话框编辑器

(2) 菜单编辑器

使用菜单可以在一个工程项目中直观,有组织地安排命令。菜单编辑器提供了创建和编辑窗口菜单的图形界面,使用菜单编辑器,可以创建标准菜单和菜单选项,为菜单或菜单选项定义热键、加速键和状态栏提示。也可以创建快捷菜单,以便用鼠标右按钮来执行要频繁使用的命令。建立菜单或菜单项后,可以用ClassWizard为菜单项映射函数并编写要执行的代码。

114

第4章 MFC应用程序资源和资源编辑器

增加新的菜单项 菜单项属性对话框

图4-5 菜单编辑器

如图4-5所示。双击任意一个菜单项,可以打开一个菜单项属性对话框,常用操作包括: ? ? ? ?

创建标准菜单和命令 创建弹出菜单命令

设置快捷键、加速键和菜单命令项的状态栏消息 移动菜单命令

(3) 加速键编辑器

加速键表列出了窗口资源中加速键和相应的命令ID。通常,加速键所对应的命令,都对应着一个菜单命令。使用加速键编辑器可以维护加速键列表,如图4-6所示,常用操作包括:

? 增加、删除、改变和浏览加速键列表

? ?

浏览并改变加速键表资源ID

将一个加速键与一个菜单命令相联系

115

VC++6简明教程

增加新的加速键 加速键属性对话框

图4-6 加速键编辑器

(4) 工具栏编辑器

工具栏编辑器可以帮助你创建工具栏资源,也可将位图转化为工具栏资源。工具栏编辑器的使用上很类似于画图工具,如图4-7所示,常用操作包括:

? 创建工具栏和按钮

? ?

将位图转化为工具栏资源

创建、移动、和编辑工具栏按钮

116

第4章 MFC应用程序资源和资源编辑器

工具栏 新的工具按钮 编辑状态的按钮 真实大小的按钮 工具按钮属性对话框 图

4-7 工具栏编辑器

对工具按钮的设置由两部分构成:一是使用图形工具栏编辑位图;二是在工具按钮属性对话框中输入工具按钮的ID。一般工具按钮的ID是一个已定义的菜单项的ID,也可以定义一个新的ID,但要对这个新定义的ID定义消息处理函数。

添加一个工具按钮,只需对最后一个空白按钮做以上两部分操作,再将按钮拖到合适的位置。删除一个工具按钮,只需使用鼠标将按钮拖出工具栏,抛弃即可。通过鼠标的拖动操作,可以方便调整按钮在工具栏上的位置。 (5) 版本编辑器

版本信息包括公司和产品的信息、语言、序列号、版权和商标的声明,版本信息编辑器帮助创建并方便地维护这些信息,如图4-8所示。

例如:需要修改公司名称,可按照下列步骤:

(a) 在ResourceView中,双击版本信息资源(VS_VERSION_INFO) (b) 在对象列表中找到项目:CompanyName

(c) 左键单击“CompanyName”,出现文本框,填入合适的内容。 同样的步骤可以修改其他版本信息。

117

VC++6简明教程

4-8 版本信息编辑器

(6) 字符串编辑器

字符串列表包括了一个应用程序中所有标识符的ID、数值和名称。例如,状态栏的提示。使用字符串编辑器可以创建或编辑一个字符串,如图4-9所示,常用操作包括:

? 查找一个字符串记录

? ? ? ? ?

增加一个字符串记录 删除一个字符串记录

移动一个字符串记录到另一个段

移动一个字符串记录到另一个资源文件(*.rc) 改变一个字符串的值或它的ID

? 增加格式或特殊字符到一个字符串

注意:不能创建一个空字符串表,如果创建了一个空的字符串表,Develop Studio在退出的时候会自动删除。

118

第4章 MFC应用程序资源和资源编辑器

图4-9 字符串编辑器

(7) 图形编辑器

图形编辑器是用于画位图、图标和鼠标的工具,同时支持工具栏位图的创建,如图4-10所示。

图4-10 图形编辑器

119

VC++6简明教程

3. 保存或删除资源

从前面的讲述中可以知道,开发者使用可视化界面编辑资源的信息,由Develop studio自动保存在.rc和.h两个文件中。当使用资源编辑器修改了资源,在ResourceView中树形结构的根结点文件夹的最右边会出现‘*’,表示修改后还未存盘。保存操作是执行菜单命令File->Save All,保存后‘*’号将消失。

要删除一个资源,只需在ResourceView的树目录中选中该资源的ID图标,直接单击“Delete”按键,该资源将从资源管理器中删除。

4.1.3 编辑器使用实例

【例4-1】文本编辑器的实现。要求文本编辑器可以在视图窗口内接收键盘输入并编辑文本,能将文本存盘并从磁盘装入文本文件;具有撤消、选择、复制、剪切、粘贴、查找、替换等功能,基本上实现类似记事本的功能。同时需要修改该编辑器的程序图标。

设计思路:

MFC类库的CEditView类不仅提供了在视图中使用CEdit控件的功能,还提供了实现简单文本编辑器的功能,因此,只要在用AppWizard生成Exam4_1的基本框架时,选择从CEditView类派生应用程序的视图类CExam4_1View,就能生成文本编辑器的基本框架。

根据对文本编辑器的要求,还须在“编辑”菜单下增加“全选”、“查找”、“查找下一个”、和“替换”4个菜单项。实现后的应用程序运行窗口如图4-11所示。

图4-11 实现的文本编辑器

实现步骤:

1. 用AppWizard生成应用程序的基本框架

(1) 在VC集成开发平台,单击File菜单中的New菜单项,打开New对话框。 (2) 在New对话框中,选择Project标签,单击MFC Application(EXE)。

(3) 在右边填写工程名称:Exam4_1,并确定工程文件保存位置。

120

第4章 MFC应用程序资源和资源编辑器

(4) 单击“OK”按钮,在MFC AppWizard-Step 1 of 6对话框中,选择应用程序的类型为Single Document。

(5) 连续单击5个“Next”按钮,接受向导默认设置,进入到MFC AppWizard-step 6 of 6对话框

中,在类的列表中选中CExam4_1View,在Baseclass下拉框中选择CEditView。

(6) 单击“Finish”按钮,显示New Project Information对话框,单击“OK”按钮,回到集成开发平台。

(7) 选择Build菜单中的Execute Exam4_1.exe菜单项,运行该应用程序。

2. 增加文本编辑器的菜单项

(1) 展开Resource View标签中的Menu菜单资源,双击IDR_MAINFRAME,打开菜单编辑窗口。

(2) 在“编辑”菜单项底部依次加入“全选”、“查找”、“查找下一个”和“替换”菜单项,各菜

单项的属性如表4-2 所示。

(3) 在“全选”菜单项后,应插入一个分隔线,分隔线是一个特殊的菜单项,只要在属性窗口中

选取Separator复选框即可,不用输入ID和Caption内容。

表4-2 菜单属性设置

菜单ID ID_EDIT_SELECT_ALL ID_EDIT_FIND ID_EDIT_REPEAT ID_EDIT_REPLACE 菜单名(Caption) 全选(&A)\\tCtrl+A 查找(&F)\\tCtrl+F 查找下一个(&N)\\t F3 替换(&R)\\tCtrl+H

(4) 最终在菜单编辑器完成的“编辑”菜单如图4-11 所示,保存后重新运行程序。 说明:

? 一个菜单项与一个菜单ID相对应,经消息映射后与一条菜单消息相对应,选择一个菜单项

? ?

系统将自动调用相应的菜单消息处理函数 一个菜单若具有下级菜单,不对应菜单ID

在此程序中,因加入的菜单命令是标准的MFC菜单命令ID标识符,即CEditView类中定义的消息映射能自动将每个命令消息发送到相应的消息处理函数,所以不用再定义消息处理函数

3. 添加菜单命令的加速键(Accelerator)

(1) 展开ResourceView标签中的Accelerator加速键资源,双击IDR_MAINFRAME,打开加速键

编辑窗口。

(2) 双击加速键清单底部的空框,打开Accel Properties对话框。

(3) 在ID栏输入:IDR_EDIT_SELECT_ALL,在“Key”编辑框中输入A,右边单选钮保留默认

值,关闭对话框。 (4) 同样的方法定义“查找”和“替换”的加速键。

(5) 完成“查找下一个”的加速键F3的定义方法有所不同:先输入ID,再选择右边“ASCII”单

选钮,单击“Next Key Typed”按钮,再按键盘上的“F3”键。 (6) 保存后重新运行程序,使用加速键来执行菜单命令。 4. 修改文本编辑器的默认文件扩展名为(.txt)

在字符串编辑器中修改文本编辑器的默认文件扩展名。

(1) 展开ResourceView标签中的String Tab字符串资源,双击IDR_MAINFRAME,打开字符串编

辑窗口如图4-12所示。

121

VC++6简明教程

图4-12 字符串编辑器窗口

字符串编辑器窗口中列出的第一个字符串表识符为IDR_MAINFRAME,这个字符串是AppWizard生成的,由7个子串组成(\\n为子串的分隔符),包含Exam4_1程序的特定消息。其当前值为:

Exam4_1\\n\\nExam4_\\n\\n\\nExam41.Document\\nExam4_ Document

双击该行中的任意位置,打开String Properties对话框,如图4-13 所示。在Caption文本框中修改字符串,分别修改第四、第五子串,结果如下:

Exam4_1\\n\\nExam4_\\nExam4_1文件(*.txt)\\n.txt\\nExam41.Document\\nExam4_ Document

图4-13 字符串属性对话框

第四子串的内容“Exam4_1文件(*.txt)”是“打开”或“保存为”对话框显示在“文件类型:”或“保存类型:”列表框中的程序默认文件扩展名;第五子串的内容“.txt”是程序默认文件扩展名本身。

(2) 保存后重新运行程序。 5. 修改文本编辑器的程序图标

(1) 展开ResourceView标签中的Icon位图资源,双击IDR_MAINFRAME,打开图形编辑窗口,

显示当前程序图标。

(2) 运用画图工具栏对Icon进行修改。图标数据以二进制的形式存放在Exam4_1.ico文件中。 (3) 保存后重新运行程序。

4.2菜单的使用 4.2.1菜单的类型

菜单是由MFC菜单类(CMenu)来创建的,CMenu是从CObject类派生的,它在MFC类库中的层次位置如图4-14所示。

122

第4章 MFC应用程序资源和资源编辑器

CObject CMenu 图4-14 CMenu类

在一个窗口应用程序中,菜单的组成分成两大类:顶层菜单和弹出菜单。顶层菜单是指出现在应用程序的主窗口或最上层窗口的菜单;弹出菜单通常是指选择顶层菜单或一个菜单时弹出的子菜单。 1. 顶层菜单(top-level menu)

一个顶层菜单由菜单名和菜单项构成。菜单名指出一组菜单项命令的主要功能和目标。常见的顶层菜单有:“File”、“Edit”、“Windows”、“Help”等。一个菜单项是可选择或可执行的,对应一个确定的功能。

2. 弹出菜单(pop-up menu)

本节将介绍三种弹出菜单:下拉菜单、子菜单和快捷菜单,如表4-3所示。

表4-3 弹出菜单的类型

菜单类型 下拉菜单(Drop-down menus) 子菜单(Submenus) 介 绍 当一个顶层菜单列表中的菜单项被选中,会显示下拉菜单 当一个菜单项被选择时,有继续选择菜单的要求,子菜单会显示。菜单项右边的三角符号就表示有子菜单的存在。 快捷菜单(Shortcut menus) 当右击鼠标键的时候,弹出一个包含相关命令的快捷菜单。快捷菜单出现在鼠标箭头的位置。

在通常情况下,使用AppWizard生成一个应用程序框架时,定义了一个默认的菜单资源“IDR_MAINFRAME”,创建窗口时加载该资源。该菜单资源包括标准菜单,例如,在“File”菜单中的“New”和“Open”。要增加更多的菜单需要经过下面两步:

(1) 使用菜单编辑器创建菜单;

(2) 使用ClassWizard创建菜单命令消息处理函数,编写代码支持菜单所要实现的功能。

4.2.2添加并设置菜单项

菜单编辑器的主要操作包括: 1. 插入新菜单项

在当前空白菜单框位置插入,选定窗口中的空白菜单框后按回车(或双击空白菜单框),系统弹出Menu Item Properties对话框。例如在应用程序Exam4_1的“查看”菜单插入一个新的菜单项“版本”,如图4-15 所示编辑对话框。

123

VC++6简明教程

图4-15 菜单编辑器和属性对话框

在某菜单项前插入,选择该菜单按“Ins”键,菜单编辑器将在该菜单前插入一个空白菜单项,然后双击该空白菜单项进行编辑。

(1) 插入一条分割线

要插入一个分割线,分割线实际也是一个菜单项,只要在对话框中选择Seperator属性即可。

(2) 增加子菜单

要为一个菜单增加子菜单,只要在对话框中选择Pop-up属性即可。

(3) 调整菜单项位置

选中某菜单项将其拖至适当位置即可。 (4) 属性对话框的设置

在ID文本框中,输入菜单选项的资源符号,可从键盘输入,也可选取系统已定义的ID号。例如:“ID_VIEW_VERSION”是用户自定义输入的,例4-1中的“ID_EDIT_FIND”是系统已定义的ID号。

在Caption文本框中,输入菜单选项名。如:“版本(&V)\\tCtrl+F12”,其中,“(&V)”是给菜单定义的热键为V字母,在热键字母前需加符号&;“\\tCtrl+F12”说明菜单的加速键为“Ctrl+F12”,转移字符“\\t”为使加速键都按右对齐显示。

在Prompt文本框中,输入描述性的文字,是为菜单定义在状态栏显示的提示。这样,只要选中该项,系统将在状态栏提示相应的描述性的文字。在文本串的最后可以加上工具按钮的提示文本,即“\\n”后的文本,如上图中的“Version”是对应工具按钮下方的提示。 2. 删除菜单项

用鼠标单击该菜单项或用上下左右光标键选择,然后按“Del”键删除。

4.2.3菜单命令处理

当添加了一个用户自定义的菜单项,并设置完菜单项属性后,若立即执行应用程序,可以看到该菜单项呈灰色,不可选择,必须为该菜单项增加菜单命令消息处理函数和相应支持代码。菜单命令消息处理函数就是用户选择一个特定菜单项而产生的菜单消息映射函数。

MFC使用ClassWizard管理一个菜单命令消息处理函数,如图4-16所示,例如创建上节菜单命令“版本”的菜单命令消息处理函数的步骤如下:

124

第4章 MFC应用程序资源和资源编辑器

(1) 打开ClassWizard,在Class name下拉列表中选择增加的菜单命令消息处理函数所属的类,本例选择CMainFrame。

(2) 在Object IDs列表中选择菜单项ID:ID_VIEW_VERSION。 (3) 在Messages列表中选择COMMAND。 (4) 单击“Add Function”,弹出函数名称确认对话框,接受默认函数名,单击“OK”按钮。 (5) 单击“Edit Code”,增加代码如程序清单4-1所示,实现版本信息显示。 (6) 重新编译运行程序,执行菜单命令“版本”。

程序清单4-1:菜单命令消息处理函数显示版本信息 void CMainFrame::OnViewVersion() { }

// TODO: Add your command handler code here MessageBox(\ersion1.0! \

图4-16 增加命令处理函数

菜单命令消息映射函数增加在哪一个类中,主要取决于哪一个类与函数所执行的功能相关。例如,一个菜单命令如果要输出一个图像,菜单命令消息映射函数应增加在视图类,因为视图类能方便地访问CDC对象实现图像输出。

4.2.4更新菜单的显示

设计菜单显示,应该考虑到用户在选择有些菜单命令时,希望看到选择留下的痕迹,例如,在“我的电脑”文件夹窗口中,通过菜单命令“查看”可以选择文件和文件夹显示的方式,用户作选择后,相应的菜单项的左边会出现一个圆点。

125

VC++6简明教程

MFC通过消息映射机制和CCmdUI类实现更新菜单的显示。当用户点击菜单时,窗口操作系统发送WM_INITMENU或WM_INITMENUPOPUP消息到窗口框架,窗口框架调用与该菜单命令相关联的菜单命令更新处理函数,菜单项的更新就产生了。

CCmdUI类提供了支持更新菜单显示的功能函数,例如CCmdUI::Enable()函数可以设置菜单项是否有效,当参数值为false时,菜单项无效,呈灰色显示;当参数值为true时,菜单项有效,可以被执行。CCmdUI提供的更新菜单显示的成员函数如表4-4所示。

表4-4 CCmdUI的成员函数

成员函数 Enable SetCheck SetRadio SetText 描 述 设置菜单项是否有效 增加或清除‘√’标记 增加或清除圆点标记 改变菜单显示文本

应用程序如果需要在运行过程中更新菜单项的显示,就要为该菜单项映射菜单命令更新处理函数,增加代码,实现更新。下面通过一个例子来熟悉菜单更新操作。

【例4-2】在应用程序Exam4_1的“查看”菜单中增加菜单项“大”,该菜单项为切换菜单,要求增加切换标记,并且使菜单项名称随选择次数逢3在“大”“中”“小”三个菜单名称之间循环变换。 具体实现步骤如下:

(1) 打开菜单编辑器,在“查看”菜单中增加菜单项ID为ID_VIEW_BIG,Caption为“大”。 (2) 为CMainFrame类增加Public访问权限的int型成员变量count ,并在该类的构造函数中设置初值为0。

(3) 打开ClassWizard,Class name 列表中选择CMainFrame,Object IDs列表中选择ID_VIEW_BIG,

Messages 列表中分别选中COMMAND和UPDATE_COMMAND_UI消息,单击“Add Function”按钮,增加命令处理函数和菜单更新处理函数。

(4) 单击“Edit Code”按钮,为新增的函数添加代码,代码参考程序清单4-2。 (5) 运行程序,连续选择菜单项ID_VIEW_BIG,观察菜单项的改变。

程序清单4-2:更新菜单显示

void CMainFrame::OnUpdateViewBig(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here if (count%2) pCmdUI->SetCheck(true); else pCmdUI->SetCheck (false);

if (count==9) count=0;

if(count==0) pCmdUI->SetText(\大\ else if(count==3) pCmdUI->SetText(\中\ else if(count==6)

126

第4章 MFC应用程序资源和资源编辑器

pCmdUI->SetText(\小\ }

void CMainFrame::OnViewBig() { // TODO: Add your command handler code here count++; }

4.2.5 使用快捷菜单

快捷菜单用于提供高效的、面向对象的菜单命令访问方式。快捷菜单通常出现在鼠标右键点击的位置,内容由鼠标所指向的对象决定,在窗口应用程序的设计中,快捷菜单是可选项。

添加快捷菜单的步骤分两步: (1) 增加一个快捷菜单。

(2) 增加快捷菜单项命令处理函数。

下面通过一个实例来介绍如何使用Component Gallery增加一个快捷菜单。

【例4-3】为应用程序Exam4_1创建的文本编辑器中增加一个快捷菜单,程序运行后,当在视图窗口单击鼠标右键时,弹出一快捷菜单如图4-17 所示。

图4-17 程序运行结果窗口

1. 增加快捷菜单

(1) 在主菜单中选中project->Add To Project菜单项,单击Components and Controls弹出菜单,在

Components and Controls Gallery对话框中,选择Visual C++ Components文件夹。如图4-18所示。

127

VC++6简明教程

图4-18 找到的构件或控件库窗口

(2) 单击“Insert”按钮,列出Visual C++ Components内容如图4-19所示。

图4-19 Visual C++ Components列表

(3) 选择Pop-up Menu构件,单击“Insert”按钮后,在弹出的对话框中选择“确定”按钮,将弹

出Pop-up Menu对话框,如图4-20 所示。在Add pop-up menu to下拉框中选择CExam4_1View,ID使用默认设置,单击“OK”按钮。单击“Close”按钮关闭对话框,插入快捷菜单。

128

第4章 MFC应用程序资源和资源编辑器

图4-20 Visual C++ Components列表

说明:“Add pop-up menu to”选项会将所生成的快捷菜单和一个类关联在一起,程序运行时,当鼠标右击该类的实例时,弹出快捷菜单。

2. 快捷菜单的编辑

(1) 在ResourceView标签页中展开Menu资源,如图4-21所示。双击新增的菜单资源

CG_IDR_POPUP_EXAM4_1VIEW,打开该菜单资源的编辑器窗口。

图4-21 新增快捷菜单的资源ID

(2) 修改_POPUP_菜单下已存在的菜单项Cut、Copy和Paste为“剪切”,“复制”和“粘贴”。 (3) 增加一条分隔线,再增加系统已定义的“查找”和“替换”菜单项,其ID号分别为ID_EDIT_FIND和ID_EDIT_REPLACE。

(4) 增加一条分隔线,再增加Pop up菜单项“颜色”(Pop-up属性被选择),“颜色”下有两个子

菜单项“前景色”和“背景色”,ID号分别为ID_COLOR_FORECOLOR和

ID_COLOR_BACKCOLOR。

3. 为快捷菜单连接一个类

(1) 将鼠标移到编辑状态的菜单上,单击右键选择ClassWizard菜单项,打开ClassWizard窗口,

弹出Adding a Class对话框 。

(2) 选择Select an existing class单击“OK”按钮,在弹出的Select Class对话框中的列表中选择

CExam4_1View,单击“Select”按钮。 4. 为快捷菜单连接消息函数

(1) 在ClassWizard的Message Maps标签中Class name列表中选择CExam4_1View,Object IDs列

表中选择菜单项ID_COLOR_FORECOLOR,选择消息COMMAND,单击“Add Function”增

加消息映射,同样对菜单项ID_COLOR_BACKCOLOR映射消息处理函数。 (2) 编辑消息映射函数,代码如程序清单4-3所示。

129

VC++6简明教程

程序清单4-3:前景色、背景色快捷菜单映射的消息函数 void CEX4_3View::OnColorForecolor() {

AfxMessageBox(“in OnColorForecolor”); }

void CEX4_3View::OnColorBackcolor() {

AfxMessageBox(“in OnColorBackcolor”); }

5. 编译运行程序,鼠标右键单击客户(视图窗口)区,弹出快捷菜单,执行各个菜单命令。

4.3 自定义工具栏和状态栏 4.3.1 工具栏和状态栏

工具栏和状态栏都是应用程序的界面元素,是一个完整的Windows应用程序的重要组成部分。其外观和组成如图4-22所示。

工具按钮 工具提示 工具栏 状态栏 窗格

图4-22 工具栏和状态栏

工具栏一般位于主框架窗口的上部,上面排列着一些图形按钮,称为工具按钮,工具按钮的ID通常是一个已定义的菜单命令ID。当用户用鼠标在某一按钮上单击时,程序就会执行相应的菜单命令;当鼠标在按钮上停留片刻后,会弹出一个黄色小窗口并显示工具按钮提示。AppWizard会为应用程序自动创建一个工具栏,工具栏上排列着一些常用的文件操作,剪贴操作的按钮,一个应用程序中可以存在多个工具栏。

130

第4章 MFC应用程序资源和资源编辑器

状态栏位于主框架窗口的底部,主要用来显示一些提示信息,可细分为几个窗格。AppWizard会为应用程序自动创建一个状态栏,该状态栏的主要功能是简要解释被选中的菜单命令或工具栏按钮命令,并显示Caps Lock、Scroll Lock和Num Lock按钮状态的描述框。

在MFC中,工具栏和状态栏分别由CToolBar和CStatusBar 类描述,它们是控制栏CControlBar的派生类,它在MFC类库中的层次位置如图4-23所示。

CObject CCmdTarget CWnd CControlBar CToolBar CStatusBar 图4-23 工具栏和状态栏的类继承层次

实际上工具栏和状态栏都对应一个窗口,它们的创建工作是在程序主框架类CMainFrame::OnCreate函数中完成的,OnCreate函数是在创建窗口时被调用的。

4.3.2自定义工具栏操作

本节我们将学习自定义工具栏的实现。使用AppWizard创建一个单文档视图应用程序(SDI应用程序),其他都接受默认选项,生成的应用程序会有一个工具栏,包含一些常用的按钮,如打开文件、存盘、打印等等,如图4-22 所示。下面首先剖析系统默认生成工具栏的实现代码。

首先,在主框架类CMainFrame中,加入了保护访问类型的CToolBar类的成员变量m_wndToolBar:

程序清单4-4:工具栏成员变量的定义 class CMainFrame : public CFrameWnd {...

protected: // control bar embedded members ... }

其次,在MainFrm.cpp文件的CMainFrame::OnCreate函数中加入粗体代码:

程序清单4-5:创建工具栏的CMainFrame::OnCreate函数 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {

if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;

if ( !m_wndToolBar.CreateEx ( this, TBSTYLE_FLAT,WS_CHILD| WS_VISIBLE|

CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|

CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) {

TRACE0(\CStatusBar m_wndStatusBar; CToolBar m_wndToolBar;

131

VC++6简明教程

}

}

return -1; // fail to create

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { }

TRACE0(\return -1; // fail to create

// TODO: Delete these three lines if you don't want the toolbar to // be dockable

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0;

OnCreate中创建工具栏的代码包括以下5个步骤: 1. 创建工具栏窗口

工具栏的创建使用了从CWnd类继承的创建函数Create或者CreateEx,创建窗口成功,将返回TRUE,否则返回FALSE。

程序清单中的代码将创建一个具有工具提示、大小可变、具有动态拖动手柄的浮动工具栏,且工具栏创建后可见。工具栏可以设置的样式风格见表4-5 所示。

表4-5工具栏风格

样式名称 WS_VISIBLE CBRS_BOTTOM CBRS_FLYBY CBRS_NOALIGN CBRS_TOOLTIPS CBRS_TOP CBRS_SIZE_DYNAMIC 含 义 设置工具栏窗口初始可见 窗口初始化时将工具栏放到窗口底部 鼠标光标在按钮上暂停时,显示工具按钮提示 防止控制栏在其父窗口大小改变时被复位 鼠标光标在按钮上暂停时,显示工具栏提示 窗口初始化时将工具栏放在窗口顶部 工具栏的大小可变

2. 加载工具栏资源

m_wndToolBar.LoadToolBar(IDR_MAINFRAME); LoadToolBar()函数的功能是为工具栏加载资源。调用Create或者CreateEx函数只能创建工具栏的一个空白窗口,没有内容,但获得了一个窗口句柄。工具栏窗口中的位图按钮的加载是靠LoadToolBar函数加载工具栏资源来完成的,系统自动生成的工具栏资源名为IDR_MAINFRAME。 LoadToolBar加载资源成功,将返回TRUE,否则返回FALSE。 3. 设置工具栏停靠特性

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking()函数设置工具栏的停靠特性,本例指示工具栏能够停靠在主窗口任何一边。标志

表4-6工具栏停靠风格

工具栏停靠位置的可以使用表4-6 所示参数的组合。

132

第4章 MFC应用程序资源和资源编辑器

样式名称 CBRS_ALIGN_TOP CBRS_ALIGN_BOTTOM CBRS_ALIGN_LEFT CBRS_ALIGN_RIGHT CBRS_ALIGN_ANY CBRS_FLOAT_MULTI 含 义 工具栏可以在客户区顶端停靠 工具栏可以在客户区底端停靠 工具栏可以在客户区左端停靠 工具栏可以在客户区右端停靠 工具栏可以在客户区任意位置停靠 允许在一个窗口内存在多个可移动控制栏

4. 设置框架窗口停靠特性

EnableDocking(CBRS_ALIGN_ANY);

使CMainFrame窗口工作区的任何一边均可停靠工具栏。EnableDocking()函数是框架类的成员函数,指示框架窗口允许它的子窗口控制栏可以以何种方式停靠。不管一个框架窗口中有多少个子窗口控制栏,该函数只需调用一次。

5. 指示工具栏停靠在框架窗口的具体位置

DockControlBar(&m_wndToolBar);

DockControlBar()是主框架类的成员函数,指示工具栏停靠在创建窗口规定的默认位置,即工作区顶部。

由上述可知,在MFC中,工具栏的功能由类CToolBar实现。工具栏资源和工具栏类CToolBar是工具栏的两个要素。自定义创建工具栏的基本步骤是:

(1) 创建自定义工具栏资源。 (2) 构建一个CToolBar对象。

(3) 调用CToolBar::Create()函数创建工具栏窗口。 (4) 调用CToolBar::LoadToolBar()函数装载工具栏资源。

【例4-4】为应用程序Exam4_1增加一条工具按钮,界面如图4-24所示。在应用程序的主窗口中常规工具栏下增加一工具条,上面有两个按钮,分别为“V”和“T”。在窗口中单击工具按钮“V”,执行菜单命令“版本”,则显示版本信息对话框;若在窗口中单击工具按钮“T”按钮,显示如图4-24所示的对话框。若单击“查看”菜单,也会弹出一个下拉菜单,单击其中的“用户工具条”项,可使新增加的用户工具条隐藏或出现。

单击“T”工具按钮弹出的消息框

图4-24 自定义工具栏示例程序

133

VC++6简明教程

1. 增加工具条资源

(1) 选择Insert 菜单中的Resource命令(或在Workspace窗口中ResourceView面板中单击鼠标右

键,选择Insert快捷菜单项),显示Insert Resource对话框。选择其中的Toolbar项,单击右

边的“New”按钮。

(2) 选择工作区中的ResoueceView标签,展开Toolbar工具栏资源,看到新增工具栏默认的ID为IDR_TOOLBAR1。

(3) 双击ID号,右边出现可编辑的工具栏。按图4-24 所示完成工具栏位图资源的设置。其中按

钮的位图显示的分别是文本“V”、“T”,编辑方法:单击工具栏上带虚框的矩形框,单击工具面板中的“A”按钮,这个按钮是用来在按钮上显示所需的文本,输入完文本后,关闭输入框。同理编辑其他工具按钮。

(4) 分别在二个按钮上双击鼠标左键,弹出属性对话框,如表4-7设置工具按钮的属性。

表4-7 工具栏按钮的属性

按钮 V T ID ID_VIEW_VERSION ID_VIEW_TEST 提示(Prompt) show version of application\\n version user-defined toolbar test\\n test

2. 映射工具按钮“T”命令处理函数

ID_VIEW_VERSION是已定义的菜单项“版本”的ID,所以工具按钮共用菜单命令处理函数。ID_VIEW_TEST是一个新定义的ID,要为其映射命令消息处理函数。

(1) 打开ClassWizard,在CMainFrame类中为ID_VIEW_TEST映射COMMAND命令消息, 单击

“Add Function”增加命令消息处理函数。

(2) 单击“Edit Code”,编辑函数,代码如程序清单4-6粗体部分所示所示。

程序清单4-6:工具栏命令消息处理函数显示信息 void CMainFrame::OnViewTest() { }

// TODO: Add your command handler code here

MessageBox(\

3. 菜单编辑

在“查看”菜单下增加“用户工具条”菜单项,菜单的ID为ID_VIEW_SHOWTOOLBAR。 4. 添加代码支持用户工具条

(1) 在CMainFrame类中加入一个CToolBar类型的成员变量m_myToolBar,访问类型为Protected。 (2) 在应用程序主窗口显示工具栏。在CMainFrame类的OnCreate函数中添加程序清单4-7中 粗

体部分所示的代码。

程序清单4-7:添加用户自定义工具栏

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

134

第4章 MFC应用程序资源和资源编辑器

return -1;

if(!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE| CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|

CBRS_FLYBY|BRS_SIZE_DYNAMIC) ||

!m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { }

if (!m_myToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |

CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS| CBRS_FLYBY| CBRS_SIZE_DYNAMIC) ||

!m_myToolBar.LoadToolBar(IDR_TOOLBAR1)) {

TRACE0(\return -1; // fail to create TRACE0(\return -1; // fail to create

}

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) {

TRACE0(\ return -1; // fail to create }

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

m_myToolBar.EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_myToolBar); return 0; }

5. 隐藏或显示用户自定义工具栏

(1) 打开ClassWizard,在CMainFrame类中为ID_VIEW_SHOWTOOLBAR映射COMMAND消

息和UPDATE_COMMAND_UI消息两个命令处理函数。

(2) 添加代码实现用户自定义工具栏的隐藏和显示的切换,代码如程序清单4-8所示。

程序清单4-8:实现用户自定义工具栏的隐藏或显示 void CMainFrame::OnViewShowtoolbar() { // TODO: Add your command handler code here

m_myToolBar.ShowWindow(m_myToolBar.IsWindowVisible()?SW_HIDE:SW_SHOW); this->RecalcLayout();

135

VC++6简明教程

}

void CMainFrame::OnUpdateViewShowtoolbar(CCmdUI* pCmdUI) { // TODO: Add your command update UI handler code here }

CWnd::IsWindowVisible()函数返回工具栏是否可见的信息,在窗口应用程序把工具栏作为窗口来处理,所以工具栏的显示或隐藏是通过调用CWnd::ShowWindow()函数实现的。当参数为SW_SHOW时,显示工具栏;当参数为SW_HIDE时,隐藏工具栏。调用CMainFrame::RecalcLayout()函数重新计算窗口框架的对象的位置。菜单更新命令消息处理函数调用CCmdUI::SetCheck()为菜单项设置选中标记,标记用户工具条的显示状态。 6. 编译运行应用程序,得到最终的结果

pCmdUI->SetCheck(m_myToolBar.IsWindowVisible());

4.3.3状态栏操作

使用AppWizard创建一个单文档视图应用程序(SDI应用程序),其他都接受默认选项。生成的应用程序自动生成具有默认状态栏的窗格。按键Caps Lock、Num Lock或者Scroll Lock时,相应状态栏的窗格将会切换显示窗格ID对应的字符串。同样首先剖析一下系统自动生成的支持状态栏工作的代码。

首先,在主框架类CMainFrame中,加入了保护访问类型的CStatusBar类的成员变量m_wndStatusBar:

程序清单4-9:状态栏成员变量的定义 class CMainFrame : public CFrameWnd {...

protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar; ... }

其次,在MainFrm.cpp文件中,定义外部静态数组indicators,用于记录状态栏的窗格对应的命令ID。

static UINT indicators[] =

{

ID_SEPARATOR, // 显示菜单命令提示 };

ID_INDICATOR_CAPS, //显示大写锁定键状态 ID_INDICATOR_NUM, //显示数字锁定键状态 ID_INDICATOR_SCRL, //显示滚动锁定键状态

136

第4章 MFC应用程序资源和资源编辑器

indicators数组的4个ID都是系统已定义的ID值。第一项一般是ID_SEPARATOR,该ID对应的窗格用来显示菜单命令提示信息;后三项是在String Table字符串资源表中定义的字符串ID,分别是CAP、NUM和SCRL,对应的3个窗格用来显示三个键盘按键的状态。

第三,状态栏的创建与工具栏的创建一样,由CMainFrame::OnCreate函数中完成,代码如下:

CWnd::Create()函数以主框架窗口为父窗口创建状态栏,创建后默认停靠在主框架窗口的底部。CWnd::SetIndicators(indicators,sizeof(indicators)/sizeof(UINT))函数将创建后的状态栏分隔为sizeof(indicators)/sizeof(UINT)个数的若干窗格,窗格的ID分别为indicators数组中的元素值。

一个应用程序只有一个状态栏,所以对状态栏的操作主要是对状态栏上窗格的操作。为了把一个窗格添加到默认的状态栏中,一般要完成下列步骤:

(1) 为新建窗格创建一个命令ID和缺省字符串。

(2) 添加窗格的命令ID到状态栏的描述数组indicators中。

(3) 为窗格创建一个命令更新处理程序。

删除一个窗格只需在indicators数组中删除对应的ID,由于窗格在状态栏上的显示位置与indicators数组元素顺序是相对应的,所以要调整窗格的位置只需调整indicators数组中元素的位置。

【例4-5】在应用程序Exam4_1的状态栏增加一个窗格显示当前系统时间,能不断地更新时间。运行后的状态栏如图4-25所示。

图4-25 增加时间窗格的状态栏

if (!m_wndStatusBar.Create(this) || { }

!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) TRACE0(\return -1; // fail to create

1. 增加一个状态栏窗格

每个状态栏的窗格都与一个ID相关联,可以使用Dummy Menu 增加一个新的ID。Dummy Menu是用来存储ID的菜单资源,但是不直接被一个菜单使用,ClassWizard可以为Dummy Menu增加消息映射。具体方法如下:

(1) 在ResourceView面板中,右击菜单资源,在快捷菜单中选择Insert菜单项,选中Menu资源 ,

单击“New”按钮。 (2) 打开新增菜单资源的编辑窗口,双击空白菜单项,打开属性窗口,在Caption中填入DummyMenu。

(3) 为DummyMenu设置它的下拉菜单。该菜单的ID为“ID_INDICATOR_TIME”;Caption为

“TIME”;Prompt为“HH:MM AM”。Prompt的内容为ID定义字符串资源,它的长度将作为

初始值决定窗格的大小,若不指定,在程序运行时,会出现“空文档”错误。

(4) 打开MainFrm.cpp,增加ID_INDICATOR_TIME到indicators数组中,ID的位置决定窗格在

状态栏上的显示顺序。同样indicators数组的元素个数决定程序状态栏的窗格个数。更改后的indicators数组如下:

137

VC++6简明教程

static UINT indicators[] =

{

ID_SEPARATOR, // status line indicator ID_INDICATOR_CAPS, ID_INDICATOR_NUM, ID_INDICATOR_SCRL, ID_INDICATOR_TIME, };

(5) 运行程序,查看状态栏的时间区。 2. 修改时间的显示,显示当前系统时间

(1) 打开ClassWizard窗口,(若弹出Adding a class对话框,选择Cancle按钮。)

(2) 在Message Map标签中,Class name列表中选择CMainFrame,Object IDs列表中选择

ID_INDICATOR_TIME;Messages列表中选择UPDATE_COMMAND_UI;单击按钮“Add Funcation”增加消息映射,修改函数的名称为OnUpdateTime。 (3) 完成消息处理函数的编码如下粗体部分代码:

程序清单4-10:设置窗格显示的消息函数OnUpdateTime void CMainFrame::OnUpdateTime(CCmdUI *pCmdUI)

{

CTime time=CTime::GetCurrentTime(); //获取系统当前时间给time 变量 CString sTime= time.Format(“%I:%M %p”); //时间值格式化复制给sTime pCmdUI->SetText(sTime); //窗格内容设置为当前时间 }

(4) 编译运行程序,查看状态栏的时间区,显示当前时间。 3. 使用定时器实时更新显示时间

(1) 在ClassView面板中选择CMainFrame类,展开该类的成员,在成员列表中双击OnCreate函

数进入编辑,在该函数中“return 0;”之前增加代码如下,设置一个定时器。 SetTimer(1,100,NULL);

SetTimer函数的第一个参数值指定定时器的ID,第二个参数则规定了定时器的时间间隔为100毫秒即0.1秒,这样,每隔0.1秒OnTimer函数会被调用一次;第三个参数NULL表示由系统调用OnTimer函数。

(2) 打开ClassWizard窗口,选择CMainFrame类,为消息WM_TIMER增加消息映射,生成OnTimer函数,该函数不需要增加代码,只需执行默认代码即可。 (3) 编译运行程序。

138

第4章 MFC应用程序资源和资源编辑器

实验 实验1:工具栏和状态栏的操作

程序功能:

生成两个自定义的工具栏:一个工具栏实现文件的常规操作:新建、打开和保存;另一个实现用户自定义的视图显示功能:显示问候语,显示版本。调整状态栏的显示,能够追踪鼠标在视图中的坐标,显示shift键的按键状态。 操作要求:

1. 使用AppWizard向导创建一个单文档应用程序Ex4_1,工程的资源语言使用英文,不生成默认的

工具栏。 2. 增加两个工具条,一个文件操作工具条,包括三个工具按钮:新建、打开和保存,用Create函数

创建;另一个视图显示工具条,包括三个工具按钮:问候(在视图窗口上输出一句问候语),版本

(显示版本信息消息框),清除(清除视图窗口上的信息),用CreateEx函数创建。文件操作工具条只能停靠在应用程序的顶部,视图显示工具条可以停靠在应用程序周边的任意一边。

3. 调整状态栏显示:第一个窗格显示鼠标在视图的坐标位置,第二个窗格显示Caps按键状态,第三

个窗格显示Num按键状态,第四个窗格显示TAB的按键状态。 4. 为窗口框架添加快捷键,作用是显示或隐藏两个工具条。

操作步骤:

1. 用AppWizard向导创建一个单文档应用程序Ex4_1

工程的资源语言使用英文,在AppWizard的第4步中,取消打印和打印预览功能,取消默认的工具栏,其它步骤按系统默认选项。 2. 插入新的工具栏资源

(1) 执行菜单命令Insert->Resource,在弹出的对话框中选择Toolbar,单击“New”按钮,生成新

的工具栏资源ID_TOOLBAR1,同样的操作可以得到工具栏资源ID_TOOLBAR2。 (2) 在ID_TOOLBAR1中创建三个视图显示工具按钮,工具按钮的式样、ID、作用如表4-8前三

个所示。

(3) 在ID_TOOLBAR2中创建三个文件操作工具按钮,工具按钮的式样、ID、作用如表4-8后三

个所示。

表4-8 工具栏按钮说明

按钮 ID ID_TOOLBAR_SAYHELLO ID_TOOLBAR_VERSION ID_TOOLBAR_CLEAR ID_FILE_NEW ID_FILE_OPEN ID_FILE_SAVE 提示(Prompt) Say hello on the view\\nHello Show version of Application\\n Version Clear the view\\nClear

3. 为工具栏资源指定类

每一个新的资源都要与一个类相关联,这个类可以是一个已存在的类,也可以为这个资源创建一

139

VC++6简明教程

个新的类。工具栏资源通常是由窗口框架类管理,所以只需将工具栏资源指定给窗口框架类。

(1) 在 ResourceView面板中,展开工具栏资源,选择ID_TOOLBAR1,在主菜单中选择

View->ClassWizard菜单项,打开ClassWizard窗口,同时弹出一个Adding a Class 对话框,如图4-26所示,选择Select a existing class,并单击“OK”选钮。

(2) 在弹出的Select Class对话框的Class list列表中选择CMainFrame,单击“Select”按钮,关闭ClassWizard窗口。

(3) 同样的步骤可以为ID_TOOLBAR2指定CMainFrame类。

图4-26为工具栏选择一个类

4. 为工具栏按钮映射命令消息处理函数

文件操作工具条中的工具按钮的ID是系统预先定义好的,而视图显示工具条中的工具按钮的ID是新定义,需要映射命令消息处理函数。

(1) 打开Class Wizard在类CEx4_1View中,为ID_TOOLBAR_SAYHELLO和

ID_TOOLBAR_CLEAR映射COMMAND消息处理函数。

(2) 在类CMainFrame中,为ID_TOOLBAR_VERSION映射COMMAND消息处理函数。 (3) 在类CEx4_1View中添加CString类型公有成员变量m_OutString,在构造函数中初始化为空串。 (4) 为三个消息处理函数添加代码,实现显示功能,代码如程序清单4-11所示的粗体部分。

程序清单4-11:视图显示工具栏按钮消息处理函数 void CEx4_1View::OnToolbarSayhello() { }

// TODO: Add your command handler code here m_OutString=\ this->Invalidate(true);

void CEx4_1View::OnToolbarClear() { }

// TODO: Add your command handler code here m_OutString=\ this->Invalidate(true);

140

第4章 MFC应用程序资源和资源编辑器

void CMainFrame::OnToolbarVersion() { }

// TODO: Add your command handler code here MessageBox(\ersion 1.0\

(5) 在CEx4_1View类的OnDraw函数中添加如程序清单4-12所示的粗体部分,实现视图窗口显

示成员变量m_OutString中的值。

程序清单4-12:能在视图窗口中显示文本的OnDraw函数 void CEx4_1View::OnDraw(CDC* pDC) { }

5. 在窗口框架中创建并装载两个工具条

(1) 在类CMainFrame中定义两个CToolBar类型的保护成员变量m_ToolBar1和m_ToolBar2。 (2) 在CMainFrame::OnCreate()函数中添加代码创建并装载两个工具条,代码如程序清单4-13中粗

体部分所示。

程序清单4-13:以不同的方法创建和装载两个工具栏 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {

if (CFrameWnd::OnCreate(lpCreateStruct) == -1)

return -1;

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) {

TRACE0(\CEx4_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc);

// TODO: add draw code for native data here pDC->TextOut (1,1,m_OutString);

return -1; // fail to create }

if (!m_ToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE |

CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS| CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||

!m_ToolBar1.LoadToolBar(IDR_TOOLBAR1))

{ TRACE0(\ return -1; // fail to create }

if (!m_ToolBar2.Create(this)||!m_ToolBar2.LoadToolBar(IDR_TOOLBAR2))

{ TRACE0(\

141

VC++6简明教程

return -1; // fail to create

}

m_ToolBar2.SetBarStyle(m_ToolBar2.GetBarStyle ()|CBRS_TOOLTIPS|

CBRS_FLYBY|CBRS_SIZE_DYNAMIC); m_ToolBar1.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_ToolBar1);

m_ToolBar2.EnableDocking(CBRS_ALIGN_TOP); DockControlBar(&m_ToolBar2);

return 0; }

(3) 运行程序,使用两个工具栏的工具按钮,并验证两个工具栏的停靠风格;如图4-27所示。

执行工具按钮version显示的对话框 执行工具按钮sayhello显示的文本 工具栏的停靠风格

图4-27 测试程序Ex4_1的工具栏

6. 为新增的窗格创建命令ID

(1) 执行菜单命令Insert->Resource插入新的菜单资源,顶层菜单项命名为Dummy menu。 (2) 添加一条下拉菜单项,获取一个命令ID作为窗格的ID,设置ID为ID_INDICATOR_TAB,

Caption为TAB,Prompt为TAB。

(3) 在CMainFrame类中的外部数组Indicators添加窗格ID,并调整数组元素如下:

static UINT indicators[] =

{

ID_SEPARATOR, // status line indicator

ID_INDICATOR_CAPS, ID_INDICATOR_NUM,

ID_INDICATOR_TAB, };

7. 实现TAB窗格的显示

142

第4章 MFC应用程序资源和资源编辑器

(1) 打开ClassWizard,在类CMainFrame中为ID_INDICATOR_TAB映射UPDATE_COMMAND_UI消息处理函数,修改函数名为OnUpdateTab。

(2) 编辑消息处理函数,实现当按下Tab键时,窗格显示“TAB”,代码如程序清单4-14粗体部分

所示。

程序清单4-14:更新TAB窗格的显示

void CMainFrame::OnUpdateTab(CCmdUI* pCmdUI) { }

窗口应用程序运行时,按下任何按键,系统都会为每一个命令发出更新消息UPDATE_COMMAND_UI ,即当按下“TAB”键时,命令ID_INDICATOR_TAB也会接到一个更新消息,此时系统调用OnUpdateTab()函数进行处理。::GetKeyState(VK_TAB)函数判断键盘按键TAB的状态,当返回值为负值时表示按下,调用pCmdUI::Enable()设置窗格显示菜单ID设置中Prompt的内容。 8. 显示鼠标的移动位置

(1) 打开ClassWizard,在CEx4_1View类中映射WM_MOUSEMOVE窗口消息处理函数。

(2) 编辑函数,实现鼠标在视图移动时,状态栏的第一个窗格显示鼠标位置,代码如程序清单4-15

粗体部分所示。

程序清单4-15:显示鼠标的移动位置

void CEx4_1View::OnMouseMove(UINT nFlags, CPoint point) { }

(3) Ex4_1View.cpp文件头部预编译命令前加入包含MainFrm.h的预编译语句。 (4) CMainFrame类中的m_wndStatusBar成员变量改成Public访问权限。 9. 运行程序,测试状态栏的显示如图4-28所示

// TODO: Add your message handler code here and/or call default

CMainFrame *pMainFrame=(CMainFrame*)AfxGetMainWnd(); CStatusBar *pStatusBar=&pMainFrame->m_wndStatusBar; if(pStatusBar) { }

CString str;

str.Format(\ pStatusBar->SetPaneText(0,str);

// TODO: Add your command update UI handler code here if(::GetKeyState(VK_TAB)<0) pCmdUI->Enable(true); else

pCmdUI->Enable(false);

CView::OnMouseMove(nFlags, point);

143

VC++6简明教程

图4-28 测试Ex4_1的状态栏

实验2:(独立练习)

在实验1中,通过添加一个菜单ID的方法获得一个命令ID作为窗格的ID,并且可以使用ClassWizard来定义一个菜单命令更新消息处理函数来更新状态栏的显示。同样也可以通过添加字符串ID的方法获得一个命令ID作为窗格的ID,试考虑若使用字符串ID作为窗格ID,如何定义更新消息处理函数来更新状态栏的显示?试用字符串ID的方法实现实验1中TAB显示窗格。

实验3:基于对话框的应用程序的菜单操作

在一个基于对话框的应用程序中增加一个菜单资源,并把它连接到对话框窗口中,运行时显示出来。 完成以后的程序其运行界面如图4-29所示。应用程序的标题为Application of Dialog based。其主窗口中有三个按钮,它们分别为“时间”、“显示”和“退出”,以及两个“文件”和“帮助”的菜单栏。单击“文件”菜单,出现一个下拉菜单,选择“时间”菜单,可以看到显示当前系统时间的消息框;单击菜单中的“显示”选项,则弹出一个显示基本信息的消息框;选择“退出”菜单,退出本应用程序。单击相应的按钮完成同样的效果。若单击“帮助”菜单,出现一个“关于应用程序”菜单项。

单击时间按钮后弹出此框

图4-29 Ex4_2程序主窗口

144

第4章 MFC应用程序资源和资源编辑器

1. 使用AppWizard创建一个对话框MFC(EXE程序)

(1) 在Visual C++主菜单栏中选择File菜单中的New选项,打开New对话框 。

(2) 选择Project标签页,并在该标签页中选择MFC AppWizard(exe)向导,在Project name编辑

框中输入工程文件名为Ex4_2,单击“OK”按钮。

(3) 在MFC AppWizard-Step1对话框中,选择Dialog based选项,在MFC AppWizard-Step 2 of 4

对话框中,在Please enter a title for your dialog编辑框中给应用程序主窗口标题命名为“Application of Dialog based”。单击“Finish”完成应用程序框架文件的创建。

2. 编辑对话框

(1) 选择项目工作区的ResourceView面板,切换到资源视图。展开Dialog对话框资源类型。双击

IDD_EX4_2_DIALOG菜单资源,将弹出对话框编辑窗口和一个控件工具栏面板如图4-30所示。

控件工具栏面板

图4-30 初始对话框编辑窗口

控件工具栏面板列出了VC中所可以建立的控件类型,用户只要把鼠标停在某个控件标识上,可显示该控件的类型提示。

(2) 删除对话框中默认生成的一个文本框和两个命令按钮。

(3) 按图4-29及表4-9所示编辑对话框的控件。单击控件工具栏面板中的Button控件,在对话框

编辑窗口适当的位置拖动到合适的大小,单击鼠标右键,在弹出的快捷菜单中选择Properties命令,显示属性窗口,完成各项的设置。如图4-31 所示。

表4-9 控件类型和属性表

控件类型 Button Button Button 名称 时间(&T) 显示(&S) 退出(&X) 属性 默认 默认 默认 ID号 IDC_TIME_BUTTON IDC_SHOW_BUTTON IDC_EXIT_BUTTON

145

VC++6简明教程

图4-31设置“时间”按钮的属性

3. 创建菜单资源

(1) 选择Insert 菜单中的Resource命令,或在Workspace窗口中单击鼠标右键,选择Insert快捷菜

单项,显示Insert Resource(增加资源)对话框,选择其中的Menu项,单击右边的“New”

按钮。

(2) 选择工作区中的ResourceView面板,展开Menu菜单资源,看到新增菜单默认的ID为

IDR_MENU1。双击ID号,右边出现菜单编辑器窗口。按实践要求和表4-10所示完成菜单的编辑。注意,在“退出”菜单前要插入一条分隔线。

表4-10 菜单项属性设置

菜单名(Caption) 时间(&T) 显示(&S) 退出(&X) 关于应用程序(&A) 菜单ID ID_TIME_MENU ID_SHOW_MENU ID_EXIT_MENU ID_ABOUT_MENU

4. 给菜单连接一个类

(1) 将鼠标移到编辑状态的菜单上,单击鼠标右键,在弹出的快捷菜单中选中ClassWizard命令,

首先弹出Adding a Class对话框,如图4-32所示。选择Select an existing class项。

图4-32 Adding a Class对话框

(2) 单击“OK”按钮后,在弹出的Select Class对话框的列表中选择CEX4_2Dlg,单击“Select”

按钮关闭该对话框。此时,在ClassWizard对话框的CEX4_2Dlg类的Object IDs列表框中增

加了新增菜单资源中菜单项的ID号。菜单IDR_MENU1已经和CEX4_2Dlg类连接起来了。

5. 连接菜单和应用程序的主窗口

菜单IDR_MENU1连接了一个类,这只是表示该菜单可以调用程序中这个类的成员函数和成员变量。此时在应用程序的主窗口中仍然没有显示菜单,这是因为菜单还没有和应用程序主窗口连接起来。菜单和应用程序对话框(即IDD_EX4_2_DIALOG)的连接方法如下:

(1) 在ResourceView面板中,双击Dialog资源中的IDD_EX4_2_DIALOG,弹出对话框编辑窗口。 (2) 在对话框的任何一个空白域单击鼠标右键,然后在弹出的快捷菜单中选择Properties命令,弹

出Dialog Properties对话框,如图4-33所示。在对话框的Menu组合框中选择IDR_MENU1。

146

第4章 MFC应用程序资源和资源编辑器

图4-33 Dialog Properties 对话框

6. 为菜单命令生成消息处理函数

(1) 按Ctrl+W组合键激活ClassWizard窗口,选择Message Map标签。

(2) 在Class name下拉列表框中选择CEX4_2Dlg类。在Object IDs中选择ID_TIME_MENU,在

Messages栏中双击COMMAND,弹出Add Member Function对话框,单击“OK”按钮接收默认的函数名为OnTimeMenu。

(3) 依次给ID_SHOW_MENU、ID_EXIT_MENU和ID_ABOUT_MENU映射COMMAND消息的成员函数OnShowMenu、OnExitMenu和OnAboutMenu。 (4) 编辑菜单命令成员函数,程序清单如下粗体部分所示:

程序清单4-16:菜单命令函数

void CEx4_2Dlg::OnAboutMenu() { // TODO: Add your command handler code here

AfxMessageBox(\ersion1.0! \

//弹出消息框显示字符串信息

}

void CEx4_2Dlg::OnExitMenu() { }

void CEx4_2Dlg::OnShowMenu() { }

// TODO: Add your command handler code here

AfxMessageBox(\// TODO: Add your command handler code here OnOK();

void CEx4_2Dlg::OnTimeMenu() { // TODO: Add your command handler code here

CTime time=CTime::GetCurrentTime (); //获取当前系统时间于变量time中

147

VC++6简明教程

}

CString sTime=time.Format(\ //时间转换成字符串类型

存于变量sTime中

AfxMessageBox(\

7. 为命令按钮生成消息处理函数

(1) 依次给ID_TIME_BUTTON、ID_SHOW_ BUTTON和ID_EXIT_ BUTTON三个命令按钮,在

CEX4_2Dlg类中映射BN_CLICKED消息的成员函数OnTimeButton、OnShowButton和OnExitButton。

(2) 因这三个命令按钮的功能与三个菜单项“时间”、“显示”和“退出”的功能完全一样,故直接

调用相应的菜单函数。程序清单如下粗体部分所示:

程序清单4-17:命令按钮处理函数

void CEx4_2Dlg::OnExitButton() { }

void CEx4_2Dlg::OnShowButton() { }

// TODO: Add your control notification handler code here OnShowMenu();

// TODO: Add your control notification handler code here OnExitMenu();

void CEx4_2Dlg::OnTimeButton() { // TODO: Add your control notification handler code here }

OnTimeMenu();

8. 编译运行应用程序,达到了设计的要求。

实验4:(独立练习)

创建一个包含“文件”、“编辑”和“画图”三个菜单的单文档应用程序。其中,“文件”菜单包含“打开”、“新建”、“保存”和“退出”基本功能的菜单项,“编辑”菜单包含“复制”、“粘贴”和“查找”功能的菜单项,“画图”菜单包含“矩形”、“椭圆”、“允许画图”和“禁止画图”的菜单项。另外,“矩形”和“椭圆”、“允许画图”和“禁止画图”为相互切换选中的菜单,要求增加选中标记“√”,且当“禁止画图”菜单被选中时,“画图”菜单中的“矩形”和“椭圆”为无效,即灰色禁止状态。否则为有效。

要求:只作菜单练习,具体画图功能不需要实现。

148

第4章 MFC应用程序资源和资源编辑器

自测题 1.每当创建一个新的资源或资源对象时,系统就会为其提供一个默认的 ,并赋一个整数值,该定义保存在 文件中。

2.在一个窗口应用程序中,菜单的组成分成两大类: 菜单和 菜单,前者指 ,后者指 。 3.在Caption文本框中,输入菜单选项名,如:“版本(&V)\\tCtrl+F12”,其中,“(&V)”是指 ;“\\tCtrl+F12”是指 。

4.一个应用程序可以存在 个工具栏,工具栏由 类的 函数创建。 5.一个状态栏由 个窗格组成,每一个窗格对应一个命令ID,外部数组 管理一组与窗格对应的命令ID, 决定着窗格在状态栏的位置。

小结 1. VC++以资源符号来标识每一个资源,并提供了管理资源的可视化编辑工具——资源管理器,以

简化程序开发中定义操作资源的复杂度,管理的资源有:加速键、位图、光标、对话框、图标、菜单、字符串表、工具栏、版本信息等。

2. 资源符号的定义保存在resource.h文件中,使用资源管理器创建和编辑的资源信息保存在与项目同

名的.rc文件中,一些资源文件如图标文件、位图文件等放在rec文件夹中。 3. 对资源的操作主要有:

(1) 创建资源:Insert->Resource (2) 保存资源:File->Save All

(3) 删除资源:直接选中资源,按“Delete”键

(4) 编辑资源:掌握各种资源编辑器的使用,主要操作都是在各种属性对话框中作设置。 4. 菜单分为顶层菜单和弹出菜单,弹出菜单主要有下拉菜单,子菜单和快捷菜单。顶层菜单是指位

于应用程序菜单栏中的菜单,AppWizard生成的单文档MFC应用程序的顶层菜单是ID号为IDR_MAINFRAME的菜单资源,在菜单编辑器选中一个菜单项的Pop-up属性,就能定义弹出菜单,如果具有Pop-up属性的菜单项位于顶层菜单,则继续向下添加下拉菜单,如果具有Pop-up

属性的菜单项位于下拉菜单,则继续向下添加子菜单,具有子菜单的菜单项的右边一个实心的三角形标记。快捷菜单是通过添加组件添加到项目中来的。

5. MFC已经提供了一些预定义的菜单命令ID,并提供了相应的消息处理函数,只需直接从ID列表

中选取使用;也可以由用户直接输入自定义的菜单命令ID,但需要为自定义的菜单ID映射消息处理函数。工具栏和加速键提供为菜单命令的快速执行方式,所以工具按钮和加速键的ID通常是

一个已定义的菜单项的命令ID,单击工具栏或按加速键实质就是调用相应的菜单命令消息处理函数。

6. 添加一个可执行的菜单项的步骤包括:

(1) 在菜单编辑器中添加一个菜单项,设置菜单的ID及其它属性;

(2) 使用ClassWizard为菜单项在合适的类中添加COMMAND消息处理函数; (3) 编辑函数代码,完成相应功能。

此外还可以为一些常用菜单命令考虑设置加速键和工具按钮,方便菜单命令的执行。

149

VC++6简明教程

7. 为菜单项映射UPDATE_COMMAND_UI消息处理函数,用于在程序运行时动态改变菜单显示外观,例如设置菜单是否有效,增加选择标记,改变菜单显示文本等 8. 一个应用程序可以存在多个工具栏,工具栏由CMainFrame类的OnCreate()函数创建。类CToolBar

提供了管理工具栏的成员函数,创建一个自定义的工具栏的步骤是: (1) 创建和编辑工具栏资源。

(2) 定义CToolBar类工具栏对象。

(3) 在CMainFrame的OnCreate()函数中完成工具栏的创建和设置。

9. 在窗口应用程序中工具栏被视为一个窗口,工具栏的隐藏和显示是通过窗口函数ShowWindow()

来实现的,IsWindowVisible()函数能够返回工具栏是否被调用的信息。 10. 状态栏也是由CMainFrame类的OnCreate()函数创建。类CStatusBar提供了管理状态栏的成员函数。

一个状态栏由多个窗格组成,每一个窗格对应一个命令ID,外部数组indicators管理一组与窗格对应的命令ID,数组元素的顺序决定着窗格在状态栏的位置。可以把每个窗格的显示视为一个菜单命令的Caption,通过对菜单更新命令消息的处理控制窗格的显示内容。

150

本文来源:https://www.bwwdw.com/article/mnk.html

Top