下载 - Visual C++ 程序设计精品课程

Download Report

Transcript 下载 - Visual C++ 程序设计精品课程

第4章 对话框与控件
引言

了解对话框的组成与分类

理解两种不同类型的对话框的编程过程

掌握基于对话框的应用程序的编程方法

掌握标准控件的编程方法

掌握公共控件的编程方法
4.1 对话框概述

在Windows应用程序中最重要的用户界面元素之一就是对
话框。几乎所有的Windows应用程序部要借助于对话框窗
口来和用户打交道。。
4.1.1 对话框的组成与分类

1.对话框的组成

a 对话框资源

b 对话框类

2.对话框的分类

对话框有两种类型:

a 模式对话框

b 无模式对话框。

(1)模式对话框

“模式对话框”是指对话框被弹出后,用户必须在对话框中
做出相应的操作。

(2)无模式对话框

无模式对话框是指当对话框被弹出后,它将一直保留在屏幕
上,但不影响其它应用程序的运行,用户可以继续在对话框
所在的应用程序中进行其它操作。

两种对话框在用对话框编辑器设计和进行编程时的方法基本
一致,但在创建和退出窗口时的方式有所不同。

① 在创建时,模式对话框式由系统自动分配内存空间,
因此,在退出对话框时,对话框对象会自动删除;而无模式
对话框则是需要用户来指定内存,退出时还需用户自己来删
除对话框对象。

② 在退出时,两种对话框所使用的终止函数不一样。
模式对话框通过调用CDialog::EndDialog来终止;而无模
式对话框通过调用CWnd::DestroyWindow来终止。
4.1.2 基于对话框的应用程序

可以直接利用MFC AppWizard应用程序向导创建一个基于
对话框的应用程序,这种应用程序运行后首先出现一个对话
框,如图4.1所示。


图4.1 Hello.exe的运行结果

图4.1是一个基于对话框的应用程序Hello.exe的运行结果,
这个应用程序很简单,显示“欢迎学习对话框知识!”字符串,
对话框只有两个默认按钮:【确定】和【退出】。

【例4.1】实现图4.1的基于对话框的应用程序

创建步骤如下:

(1) 在Visual C++ 2005中选择“文件”菜单的“新建”菜单
项下的“项目”,弹出的“新建项目”对话框。在对话框的
项目类型中选择“Visual C++”下的“MFC”,在模版中选
择“MFC应用程序”。在“名称”对话框填入项目名称
Hello,在“位置”对话框中选择项目存放的位置,这里直
接使用默认的存储位置“e:\Visual Studio 2005\Projects”。
在“解决方案”对话框中填入方案名称Hello。单击【确定】
按钮。

(2)在MFC应用程序向导中选择应用程序类型时,选择“基
于对话框”类型,其他接受系统缺省设置,单击【完成】按
钮,完成基于对话框的应用程序框架。

(3) 在创建的工程项目中,打开资源视图,单击 “Dialog”
下名为“IDD_HELLO_DIALOG”的对话框,会出现相应的
对话框编辑器和属性窗口,如图4.2所示。调整对话框的大
小,在属性窗口中将Caption的值设置为“学习对话框”,
将静态文本的Caption值由“TODO:在这里设置对话控制”
改为“欢迎学习对话框知识!”。

(4) 编译并运行程序
4.1.3 对话框类CDialog

MFC提供了一系列对话框类,并实现了对话框消息响应和处
理机制。用户在程序中创建的对话框类一般都是CDialog类
的派生类,CDialog类的派生关系如图4.3所示。

图4.3 CDialog类的派生关系

CDialog类是CWnd类的继承类,所以它继承了CWnd的基
本功能,如移动窗口、改变窗口大小、关闭窗口等。
CDialog类通过对话框的一些特定的特性扩展了基本功能。
这些特性包括生成和显示对话框的功能、遍历对话框的控件、
设置和恢复默认按钮等。CDialog类经常使用的成员函数列
于表4.1,在CDialog类的派生类中可以直接调用,另外大部
分函数是虚函数,可以在用户的派生类中重载,实现特定目
的。
表4.1 对话框的常用函数
成员函数
说明
CDialog::CDialog
构造函数,根据对话框资源模板定义一个对话框
CDialog::Create
创建无模式对话框窗口,若对话框不是Visible属性,
需调用CWnd::ShowWindow函数显示无模式对话
框窗口
CDialog::DoModal
激活模式对话框,显示对话框窗口
CDialog::OnInitDial
og
WM_INITDIALOG的消息处理函数,在调用
DoModal或Create函数时系统发送
WM_INITDIALOG消息,显示对话框前进行初始化
CDialog::EndDialog 关闭模式对话框窗口。
CDialog::OnOK
单击【确定】按钮调用该函数,接受对话框输入数
据,关闭对话框
CDialog::OnCancel
单击【取消】按钮或【Esc】键时调用该函数,
不结束对话框输入数据,关闭对话框
CWnd::ShowWindow
显示或隐藏对话框窗口
CWnd::DestoryWindow
关闭并销毁无模式对话框
CWnd::GetWindowText
获取对话框窗口的标题
CWnd::SetWindowText
设置对话框窗口的标题
CWnd::UpdateData
调用DoDataExchange设置或获取对话框控件
的数据
CWnd::DoDataExchang
e
被UpdateData调用实现对话框数据交换,不能
直接访问
CWnd::MoveWindow
移动对话框窗口
CWnd::EnableWindow
是窗口处于可用或禁用状态
表4.2 CDialog类中通常被重载的成员函数
成员函数
所响应的消息
重载目的
OnInitDialog()函数
WM_INITDIALOG
初始化对话框的控件
OnOK()函数
【确定】按钮的
BN_CLICKED
用户单击【确定】按钮
时响应
OnCancel()函数
【取消】按钮的
BN_CLICKED
用户单击【取消】按钮
时响应
4.1.4 对话框数据交换DDX和验证DDV

在Visual C++ 2005中为对话框数据交换和验证分别提供了
两种机制,分别是DDX(Dialog Data Exchange)和
DDV(Dialog Data Validation)。

对话数据交换(DDX)用于初始化对话框中的控件并获取用户
的数据输入,而对话框数据验证(DDV)则用于自动验证对话
框中的数据输入。

要在对话框中使用DDX和DDV,必须用MFC类向导创建数
据成员、设置数据类型并指定验证规则。

1.DDX机制

MFC提供的对话框数据交换(DDX)用来初始化对话框中的数
据,并向应用程序返回数据。DDX使用户向对话框窗口加载
对象数据的过程和当对话框关闭时恢复其中的数据这两个过
程自动化。

使用DDX机制,一般在OnInitDialog消息处理函数或构造函
数中设置成员变量的初始值。在对话框显示后,框架立即使
用DDX机制将数据成员的值传递给对应控件。在
OnInitDialog函数的默认实现中,会调用
CWnd::UpdateData函数以初始化对话框中的控件。
在 OnInitDialog 函数中初始化控件
在对话框构造函
数中初始化变量
对话框对象
屏幕上的对话框
画笔
成员
变量
默认
当控件更新时,
获取当前值
控件
对话框
确定
取消
调用 UpdateData 函数获取控件值

图4.4 对话框数据交换

对话框数据交换是在对话框类中由DoDataExchange函数
完成的,这个函数由UpdateData函数调出。

用户可在任何时候调用UpdateData函数,当UpdateData函
数中的参数为TRUE时系统会保存并使控件中的数据有效;
当参数为FALSE时,系统将用成员数据更新数据。

默认则CDialog::OnInitDialog函数和CDialog::OnOK函数
会调用UpdateData函数。

用户在对话框类中控件加入成员变量时,可以在属性窗口中
指定范围和长度有效化参数。

2.DDV机制

在前面的DoDataExchange函数中,可以注意到验证对话
框数据有效性的DDV函数,这些函数是用于将数据返回成员
变量之前按验证数据的长度和范围。如果验证失败,DDV函
数将显示消息框提示用户,并把焦点放在违反规则的控件中
以便用户重新输入数据。
4.1.5 提示信息对话框

提示信息对话框也称消息对话框,是用于显示简单信息的一
类对话框,不需要用户创建可以直接使用。在Visual C++
2005的MFC类库中提供了四个相应的函数来实现这样的功
能,这四个函数的原型如下:

int CWnd::MessageBox( LPCTSTR lpszText, LPCTSTR
lpszCaption = NULL, UINT nType = MB_OK );

int MessageBox(HWND hWnd, LPCTSTR lpText,
LPCTSTR lpCaption,UINT uType);

int AfxMessageBox( LPCTSTR lpszText, UINT nType =
MB_OK, UINT nIDHelp = 0 );

int AFXAPI AfxMessageBox(UINT nIDPrompt, UINT
nType = MB_OK, UINT nIDHelp = (UINT)-1);

这四个函数都是用来创建和显示提示信息对话框的,
AfxMessageBox函数实际上是对API函数MessageBox的
封装。四者的功能基本相同,但适用范围是有区别的。
AfxMessageBox函数和::MessageBox,在程序中的任何
位置都可调用;而CWnd::MessageBox函数只能用于象控
件、对话框和窗口等窗口类中。AfxMessageBox函数第一
种形式中消息框的标题将由MFC框架取为主应用程序名,第
二种形式中消息框的内容以nIDPrompt为ID号,从符号表中
获得ID所对应的字符串。
表4.3 提示信息对话框常用图标类型
表4.4 提示信息对话框常用按钮类型
按钮类型取值
按钮类型
MB_ABORTRETRYIGNORE 显示【关于】、【重试】、【忽略】3个按
钮
MB_HELP
显示【确定】、【帮助】按钮
MB_OK
显示【是】按钮
MB_OKCANCEL
显示【确定】、【取消】按钮
MB_RETRYCANCEL
显示【重试】、【取消】按钮
MB_YESNO
显示【是】、【否】按钮
MB_YESNOCANCEL
显示【是】、【否】、【取消】按钮

在实际使用中,图标类型及按钮类型的取值可通过“|”组合。
如:AfxMessageBox(_T(“是否要退出系
统”),MB_YESNO|MB_ICONWARNING)语句得到的提示
信息对话框如图4.5所示。

图4.5 警告信息对话框
表4.5 提示信息对话框的函数返回值
被单击的按钮
函数返回值
单击【终止】按钮
IDABORT
单击【取消】按钮
IDCANCEL
单击【继续】按钮
IDCONTINUE
单击【忽略】按钮
IDIGNORE
单击【否】按钮
IDNO
单击【确定】按钮
IDOK
单击【重试】按钮
IDRETRY
单击【重试】按钮
IDTRYAGAIN
单击【是】按钮
IDYES
4.2 使用对话框

使用对话框的一般步骤

1 首先要创建对话框资源和与其相关联的对话框类,

2 添加控件、与控件关联的成员变量和消息映射函数,

3 程序中显示对话框。
4.2.1 一般对话框工作流程

定义一个对话框类之后,就可以利用这个对话框类声明一个
对话框对象。定义自己的对话框类一般用CDialog类作为基
类,在声明一个对话框对象时调用了对话框类的构造函数,
并自动调用基类CDialog的构造函数。声明一个对话框对象
后,可以调用对话框类的成员函数DoModal建立对话框窗
口并显示对话框。假设定义了一个名为CHelloDlg的对话框
类,则以下代码用于显示对话框。

CHelloDlg hellodlg;

hellodlg.DoModal();

当DoModal函数被调用时,在“幕后”引起一系列的函数
调用,这些函数调用顺序如下:

CDialog::DoModal();

CHelloDlg::OnInitDialog();

CDialog::OnInitDialog();

CWnd::UpdateData(FALSE);

CHelloDlg::DoDataExchange();

对话框中大都有【确定】和【取消】按钮,当单击它们时关
闭对话框,结束对话框消息循环。单击【确定】按钮调用
CDialog::OnOK函数,单击【取消】按钮调用
CDialog::OnCancel函数。二者都结束DoModal函数的调
用,OnOK函数令DoModal函数返回IDOK,OnCancel函
数令DoModal函数返回IDCANCEL,可以根据DoModal函
数的返回值做出不同的选择。OnOK函数和OnCancel函数
都调用了EndDialog函数,该函数关闭当前对话框。

一般对话框的工作流程如图4.6所示,其中双向箭头表示调
用关系。
调用 CDialog::DoModal
调 用用户 定义的 对话框 类构 造
函数 CHelloDlg::CHelloDlg 创建
对话框对象
调用 CHelloDlg::OnInitDialog
调用 CDialog::OnInitDialog
调用 CHelloDlg::DoModal 显
示对话框窗口
调用 CWnd::UpdateData(FALSE)
确定/取消
取消
确定
调用 CHelloDlg::OnCancel,
返回 IDCANCEL
调用 CHelloDlg::OnOK,
返回 IDOK
从 CDialog::DoModal 返回

调用 CHelloDlg::DoDataExchange
调用 CWnd::UpdateData(TRUE)
接收数据
调用 CDialog:: EndDialog 关闭
对话框
图4.6 一般对话框的工作流程
4.2.2 创建对话框

在Windows中对话框是作为一种资源被使用的,在程序中
创建一个对话框,首先要创建一个对话框资源,然后创建一
个基于该对话框资源的对话框类。对话框资源指定了对话框
本身的属性和对话框中控件的属性,对话框类规定了对话框
和对话框中每个控件的行为。

【例4.2】创建一个应用程序Score,生成如图4.7所示的对
话框资源。
图4.7 生成的对话框资源

程序的实现过程如下:

(1)创建应用程序

(2)创建对话框资源

(3)创建对话框类
4.2.3 添加控件及关联的成员变量

如果没有控件,对话框不能完成具体功能,因此控件和对话
框有着密不可分的关系,结合对话框编辑器,利用控件工具
箱可给当前正在编辑的对话框模板资源添加控件。

1.添加控件

向对话框中添加控件时,在控件工具箱中选择所需要的控件,
按下鼠标的左键(不要松开),将鼠标拖到对话框中松开,
在对话框中添加一个指定的控件。按照修改对话框标题的方
法对每个控件的“ID”和“Caption”进行修改。

2.添加关联的成员变量

在类视图中选择“CScoreDlg”类,单击“项目”菜单下的
“添加变量”,弹出“添加成员变量向导”对话框。选择
“控件变量”单选框。在“控件ID”下拉菜单中选择控件的
ID“IDC_COMBO_DEPARTMENT”,在类别中选择
“Value”,则在控件类型默认为“COMBOBOX”,变量类
型中默认为“String”,在此采用默认值。在变量名的编辑
框中输入变量的名称“m_combo_department”,如图4.17
所示。这样就使成员变量“m_combo_department”和控
件“IDC_COMBO_DEPARTMENT”的数据之间建立了联系,
通过定义的类成员变量就可以和控件的数据进行交互访问。

在添加按钮的过程中,为了能让单选按钮正确工作,还需
要以下两件事:

按Ctrl+D键设置对话框上控件的跳转顺序。若对默认的跳
转顺序不满意,可用鼠标依次点击控件,从而确定跳转顺
序。

在属性窗口中,将每个控件组框中第一个控件的Group属
性设置为True。这个属性是基于跳转顺序的,因此应首先
设置跳转顺序。

3.添加成员变量后的程序分析

在对话框类中添加成员变量后,应用程序的源程序文件中增
加了一下代码:

(1)在头文件ScoreDlg.h的CScoreDlg类的定义中,增加了
映射变量的定义代码。

(2) 在实现文件ScoreDlg.cpp的CScoreDlg类的构造函数中,
增加了映射变量的初始化代码。

(3)在实现文件ScoreDlg.cpp的DoDataExchange函数中
增加了数据传递的实现代码。

4.映射变量的管理

(1)映射变量的定义

映射变量必须定义在下列代码之后,才能被系统识别和处理:

DECLARE_MESSAGE_MAP()

(2)映射变量的初始化

映射变量的初始化是在类的初始化函数列表中进行初始化的。

(3)映射变量与对话框控制间的数据传递

5.对话框类的实现

前面创建了对话框资源和对话框类,这里通过调用菜单项来
激活对话框。


【例4.3】为【例4.2】的应用程序添加一个菜单项“对话
框”,它有两个下拉菜单项:“输入”和“显示”,如图
4.18所示。选择“输入”菜单项后,出现“成绩录入”对话
框,输入信息后的对话框如图4.19所示。
图4.18 添加“对话框”菜单项后的菜单
程序的实现过程如下:

(1)打开【例4.2】的项目文件“Score.sln”。

(2)添加菜单项“对话框”和它的下拉菜单项

(3)为消息映射函数编写代码

(4)在CScoreView类的实现文件中加入对话框的头文件:
#include "ScoreDlg.h"
至此整个程序的代码输入完毕,然后编译运行就可以了。
4.2.4 无模式对话框

无模式对话框的实例应声明为全局对象,一般用new操作符
生成,使用结束后用delete操作符删除。模式和非模式对话
框共享相同的基类CDialog,并且它们都可以使用对话框编
辑器来创建对话框资源。

1.创建对话框

无模式对话框的创建由对话框类的成员函数Create完成。该
函数的原型如下:
BOOL Create( LPCTSTR lpszTemplateName,
CWnd* pParentWnd = NULL );
BOOL Create( UINT nIDTemplate, CWnd*
pParentWnd = NULL );

2.显示对话框

在创建无模式对话框时,一般没有设置对话框Visible属性,
需要调用CWnd::ShowWindow函数来显示无模式对话框窗
口,该函数的原型如下:

BOOL ShowWindow( int nCmdShow );

3.消息循环部分的处理

由于无模式对话框并不禁止应用程序向其他窗口发送消息,
因此,在WinMain函数的消息循环中必须包含截获发往无模
式对话框的消息,并将其发往相应的对话框处理函数进行处
理的语句。其消息循环过程的一般形式为:
while(GetMessage(&Msg,NULL,0,0))
{ if(!IsDialogMessage(&Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}

4.关闭对话框

无模式对话框调用函数CWnd::DestroyWindow关闭对话框,
该函数的原型为:

virtual BOOL DestroyWindow( );
4.2.5 公用对话框

Windows系统提供了一系列常用的公用对话框,如“颜色”
对话框、“字体”对话框、“打开”对话框、“保存”对话
框、“打印机设置”对话框等,这些对话框类都是从一个公
共的基类CCommonDialog派生出来的,而
CCommonDialog类又是CDialog类的派生类。
表4.10 MFC的公用对话框类
通用对话框类
用途
CFileDialog
文件对话框,用户可打开或保存对话框
CFontDialog
字体对话框,允许用户从列出的字体种选择所需要
的字体
CColorDialog
颜色对话框,用户可从中选择或创建颜色
CPageSetupDialog
页面设置对话框,允许用户设置页面参数
CPrintDialog
打印对话框,允许用户设置打印机的参数及打印文
档
CFindReplaceDialog 查找替换对话框,允许用户查找或替换指定字符串
COleDialog
该类及其派生类用于生成OLE应用程序对话框

这些公用对话框中,“查找替换”对话框是无模式对话框,
其他公用对话框都是模式对话框。公用对话框都只能获取信
息,但不对信息做出处理。

用户可以在程序中通过定义相应的公用对话框类的对象,然
后用DoModal()成员函数来显示该对话框。

1.文件对话框

MFC中类CFileDialog实现Windows标准文件的打开和保存
对话框。其构造函数如下所示:
CFileDialog(
BOOL bOpenFileDialog,
显示另存为对话框
// TRUE显示打开对话框,FALSE
LPCTSTR lpszDefExt = NULL, //指定默认的文件扩展名
LPCTSTR lpszFileName = NULL, // 指定默认的文件名
DWORD dwFlags = OFN_HIDEREADONLY |
OFN_OVERWRITEPROMPT,
//指定风格
LPCTSTR lpszFilter = NULL,//指定可供选择的文件类型和相应的扩展名
CWnd* pParentWnd = NULL,
DWORD dwSize = 0);
//指向对话框的父窗口的指针

CFileDialog类的常用函数如下所示:

DoModal:显示文件对话框,允许用户作出一个选择;

GetFileExt:返回所选中文件的扩展名;

GetFileName:返回所选中文件名;

GetFileTitle:返回所选中文件标题(不包括扩展名);

GetFolderPath:返回当前打开文件夹的路径和目录;

GetNextPathName:返回下一个选中文件的完整路径名;

GetPathName:得到完整的文件名,包括目录名和扩展名;

GetReadOnlyPref:返回所选文件的只读状态;

GetStartPosition:对于选择了多个文件的情况得到第一个文件位置;

SetTemplate:设定CFileDialog对象的对话框模板。

2.字体对话框

CFontDialog类支持字体选择对话框,其中列出系统上安装
的所有字体,用户可以从中选择一种字体,并将结果返回给
应用程序。其构造函数如下所示:

CFontDialog(LPLOGFONT lplfInitial = NULL,
//允许设置字体的属性

DWORD dwFlags = CF_EFFECTS |
CF_SCREENFONTS, //字体选择样式标识位
CDC* pdcPrinter = NULL, //指向一个打印设备上下文的

指针

CWnd* pParentWnd = NULL); //对话框的父窗口
CFontDialog类常用的成员函数如下所示:

GetCurrentFont:获得当前字体;

GetSize:返回所选字体的点阵大小,以10个像素为单位;

GetColor:返回所选字体的颜色,返回一个COLORREF型的值;

GetFaceName:返回所选字体的名称;

GetStyleName:返回所选字体的风格名称;

GetWeight:返回所选字体的磅值;

IsBold:确定字体是否为粗体;

IsItalic:确定字体是否为斜体;

IsStrikeOut:确定字体是否有删除线;

IsUnderline:确定字体是否有下划线。

3.颜色对话框

CColorDialog类用于实现颜色选择通用对话框。它可以让
用户选定一种颜色,并以COLORREF为类型返回选中的颜
色。其构造函数如下所示:
 CColorDialog(

COLORREF clrInit = 0,
//初始颜色值

DWORD dwFlags = 0,
//对话框样式标识位

CWnd* pParentWnd = NULL
//对话框的父窗口
 );

CColorDialog类常用的成员函数如下所示:

GetColor:获得用户选中的颜色;

GetSavedCustomColors:返回用户创建的自定义颜色;

SetCurrentColor:强制当前颜色选择为指定的颜色。

4.页面设置对话框

该对话框为打印机页面设置对话框,用来设置打印的纸张大
小、页边距、打印的方向等等。其构造函数如下所示:
 CPageSetupDialog(
 DWORD dwFlags =
PSD_MARGINS|PSD_INWININIINTLMEASURE,

//对话框样式标识位
 CWnd* pParentWnd = NULL);
//对话框的父窗口

CPageSetupDialog类常用的成员函数如下所示:

GetDeviceName:返回打印设备名称;

GetDevMode:返回打印模式,其返回值是一个指向
DEVMODE结构的指针;

GetDriverName:返回打印机驱动程序名;

GetMargins:返回页边距;

GetPaperSize:返回纸张大小;

GetPortName:返回打印机端口名

5.打印对话框

CPrintDialog类支持“打印”和“打印设置”对话框,用户
可以进行与打印有关的操作。其构造函数如下所示:
 CPrintDialog(

BOOL bPrintSetupOnly,// TRUE显示打印对话
框,FALSE显示打印设置对话框

DWORD dwFlags = PD_ALLPAGES |
PD_USEDEVMODECOPIES | PD_NOPAGENUMS

| PD_HIDEPRINTTOFILE |
PD_NOSELECTION,
//对话框样式标识位
 CWnd* pParentWnd = NULL);
//对话框的父窗口
CPrintDialog类常用的成员函数如下所示:

CreatePrinterDC:不显示“打印”对话框的情况下,构造
一个打印设备上下文;

GetCopies:返回打印的份数;

GetDefaults:不显示“打印”对话框的情况下,返回打印
设备默认值;

GetDeviceName:返回打印设备名;

GetDevMode:返回打印模式,是一个指向DEVMODE结
构的指针;

GetDriverName:返回打印机驱动程序名;

GetFromPage:返回打印的起始页面;

GetPortName:返回打印机的端口名称;

GetPrinterDC:返回指向打印设备上下文的句柄;

GetToPage:返回打印的终止页面;

PrintAll:用户是否选择了“页面范围”选项组中的“全部”
选项;

PrintRange:用户是否选择了“页面范围”选项组中的
“页码”选项;

PrintSelection:用户是否选择了“页面范围”选项组中的
“选定范围”选项。

6.查找替换对话框

CFindReplaceDialog类用于实现“查找”和“替换”对话
框,是无模式对话框,与其它几类通用对话框不同,它们的
初始化调用的是Create函数而不是DoModel函数。Create
函数如下所示:

BOOL Create(

BOOL bFindDialogOnly,

// TRUE显示查找对话框,FALSE显示替换对话框

LPCTSTR lpszFindWhat,//查找的源字符串

LPCTSTR lpszReplaceWith = NULL,

DWORD dwFlags = FR_DOWN, //对话框样式标识位

CWnd* pParentWnd = NULL); //对话框的父窗口
//替换字符串

CFindReplaceDialog类常用的成员函数如下所示:

FindNext:返回一个BOOL值,表示用户是否单击了“查找
下一个”按钮;

GetFindString:得到用户输入的查找内容;

GetNotifier:返回一个指向当前CFindReplaceDialog对话
框的指针;

GetReplaceString:返回一个包含替换字符串的CString对
象;

IsTerminating:返回一个BOOL值,表示用户是否单击了
“取消”按钮;

MatchCase:返回一个BOOL值,表示用户是否选择了对
话框中的“区分大小写”复选框;

MatchWholeWord:返回一个BOOL值,表示用户是否选
择了对话框中的“全字匹配”复选框;

ReplaceAll:返回一个BOOL值,表示用户是否单击了
“全部替换”按钮;

ReplaceCurrent:返回一个BOOL值,表示用户是否单击
了“替换”按钮;

SearchDown:返回一个BOOL值,返回TRUE表明搜索方
向向下,返回FALSE则向上搜索。
4.3 标准控件

Windows提供的控件有两种:标准控件和公共控件。

标准控件主要包括:按钮控件、滚动条控件、静态控件、列
表框控件、编辑框控件和组合框控件等,利用标准控件可以
满足用户大部分界面设计的要求。

公共控件包括旋转按钮、滑块、进度条、标签控件、图像列
表、列表视图控件、树形视图控件、动画控件、热键控件等。
4.3.1 控件概述

控件是Windows图形用户界面的主要组成部分之一,用户
通过操作控件对象完成与应用程序之间的交互。为了使
Windows编程更方便更灵活,MFC提供了一系列的类。这
些类封装了普通用户界面控件的功能。控件的使用集中体现
了Windows系统面向对象的特点。

使用MFC控件类有两个主要的优点。
 控件类可以使用户按照面向对象的方式与对话框中的控
件进行交互。
 这些控件类可以扩展来满足用户独特的要求。

控件的属性设置既可以通过其相应类提供的一些函数完成,
也可以通过修改属性窗口中相应属性值来实现,这里侧重
于第一种方法的说明。
表4.11 系统提供的标准控件
MFC类
说明
CButton
代表一个按钮的小长方形的子窗口(按钮控件)
CComboBox
代表一个选择列表框的子窗口(组合框控件)
CEdit
代表一个接收用户输入的文本输入子窗口(编辑框控件)
CListBox
代表字符串列表的子窗口(列表框控件)
CScrollBar
代表一个滚动条的子窗口(滚动条控件)
CStatic
代表一个显示静态文本的子窗口(静态控件)

作为一般窗口,控件具有通用的窗口属性。可以使用
ShowWindow函数和MoveWindow函数等窗口管理函数来
显示或隐藏控件、改变控件的位置、尺寸以及进行其他操
作。控件在应用程序中以独立的子窗口和对话框控件两种
形式存在。

控件的创建形式也有两种:
1.
一种是在对话框中创建控件;
2.
另一种是通过调用CreateWindow或CreateWindowEx函
数来创建控件。

HWND CreateWindow(

LPCTSTR lpClassName, // 子窗口的类名

LPCTSTR lpWindowName, // 窗口名称

DWORD dwStyle,

int x,
// 窗口左上角顶点的水平坐标

int y,
// 窗口左上角顶点的垂直坐标

int nWidth,
// 窗口宽度

int nHeight,
// 窗口高度

HWND hWndParent,

HMENU hMenu,

HINSTANCE hInstance, // 应用程序句柄,可以为NULL

LPVOID lpParam

);
// 窗口风格
// 父窗口句柄,可以为NULL
// 子窗口菜单句柄或子窗口标识符
// 指向lParam数值的指针
表4.12 窗口风格取值
风格
说明
WS_BORDER
创建带有窄边框的子窗口
WS_CAPTION
创建带有标题栏的子窗口,包含了WS_BORDER
WS_CHILD
创建不能带有菜单栏的子窗口,不能与
WS_POPUP同时使用
WS_CHILDWINDOW 同WS_CHILD
WS_CLIPCHILDREN 用于父窗口,不会被子窗口覆盖
WS_DISABLED
创建禁活的子窗口,不能接受用户信息
WS_DLGFRAME
创建一个对话框风格的窗口,不能与
WS_CAPTION同时使用
WS_GROUP
允许用户通过【Tab】键在子窗口间切换
WS_HSCROLL
创建带有水平滚动条的子窗口
WS_ICONIC
创建最小化的子窗口
WS_MAXIMIZE
创建最大化的子窗口
WS_MAXIMIZEBOX
创建带有最大化按钮的子窗口
WS_MINIMIZE
同WS_ICONIC
WS_MINIMIZEBOX
创建带有最小化按钮的子窗口
WS_OVERLAPPED
创建重叠窗口,带有标题栏和边框
WS_OVERLAPPED
WINDOW
创建带有WS_OVERLAPPED, WS_CAPTION,
WS_SYSMENU, WS_THICKFRAME,
WS_MINIMIZEBOX, 和WS_MAXIMIZEBOX风
格的重叠窗口
WS_POPUP
创建弹出子窗口,不能用于WS_CHILD
WS_POPUPWINDO
W
创建弹出子窗口,带有WS_BORDER,
WS_POPUP和WS_SYSMENU风格
WS_SIZEBOX
创建可缩放边框的子窗口
WS_SYSMENU
使子窗口有系统菜单
WS_TABSTOP
指定用户第一次按下【Tab】键时输入焦点所属
的子窗口
WS_THICKFRAME
同WS_SIZEBOX
WS_TILED
同WS_OVERLAPPED
WS_TILEDWINDOW 同WS_OVERLAPPEDWINDOW
WS_VISIBLE
创建初始化可视的子窗口
WS_VSCROLL
创建带有垂直滚动条的子窗口
4.3.2 控件的组织

1.添加和删除控件

添加控件的方法有两种:

(1)在控件工具箱中选择所需要的控件,按下鼠标的左键
(不要松开),将鼠标拖到对话框中松开,在对话框中添加
一个指定的控件。

(2)在控件工具箱中单击需要的控件,此时,控件呈凹下
状态,将鼠标拖到对话框,鼠标成“+”字形显示,在对话框
中按下鼠标左键拖到适当大小后松开,在对话框中添加一个
指定的控件。

删除已添加的控件,只要选择对话框中的控件,按下【Del】
键即可。

2.选择控件
被选区的控件为当前控件,在对话框中所进行的操作都只
对当前控件起作用,如:修改属性、改变大小等。被选取
的控件周围由选择框包围,并同时有8个蓝色实心小方框。
选择控件的方法如下:
1.
2.
选取单个按钮:单击工具栏中的选取按钮,然后移动鼠标
到对话框上的某个控件上,单击鼠标左键即可。
选取多个控件的方法有两种:
① 在对话框内按住鼠标左键不放,拖出一个虚框,释放鼠
标,则被虚框包围的控件全部被选取。
② 按住【Shift】键,用鼠标一次单击所要选取的控件,然
后放开【Shift】键。

3.调整控件的大小

对于静态文本控件,当输入标题内容时,控件的大小会自动
改变。对于其它控件,选取控件后,用鼠标指针指向其周围
的蓝色小方框,待鼠标光标形状变成双向箭头时,拖动鼠标
将控件变到所需要的大小时放开鼠标。

4.移动控件

当控件被选取后,按键盘上的方向键或用鼠标拖动到所需要
的位置即可。

5.复制控件

当控件被选取后,按下键盘上的【Ctrl】键不放,用鼠标拖
动到所需要的位置,然后放开【Ctrl】键即可;另外一种方
法是:当控件被选取后,按住【Ctrl+C】键复制,再粘贴,
把复制后的控件用鼠标移动到所需要的位置即可。

6.设置属性

将光标指向对话框中的控件,单击鼠标左键选中控件,则在
属性窗口中会出现控件的各种属性设置。用户可直接修改各
种属性,属性窗口如图4.22所示。

7.设置【Tab】键顺序

【Tab】键顺序是指当对话框拥有输入焦点时,每次按下
【Tab】键,对话框中的各个控件会依次拥有输入焦点的次
序。默认的次序是添加控件的次序,如果希望改变默认的次
序,则用以下的方法:选择“格式”菜单中的“Tab 键顺序”
菜单项,或直接按下【Ctrl+D】键,此时,对话框中每一个
控件的左上角会出现一个数字标签,这个数字标签代表了默
认的【Tab】键顺序。

8.测试对话框资源

选择菜单中的“格式”菜单下的“测试对话框”菜单项,就
可以测试对话框资源。
4.3.3 控件属性

向对话框中加入某个控件后,就可以对其属性进行设置。方
法是在对话框中的控件上单击鼠标左键,然后在属性窗口中
会出现控件的各种属性设置,用户可直接修改各种属性。
表4.13 控件的主要属性
项目
说明
ID
控件的标识符,每种控件都有缺省的标识符。
Caption
控件的标题,大多数控件都有缺省的标题。
Visible
指定控件初始化是否可见。选中表示控件可见;否则不可见。
Group
指定控件组中的第一个控件。选中表示控件后的所有控件均被
看成是同一组。成组的目的是为了让用户可以用键盘方向键在
同一组控件中进行切换。
Help ID
若该项选中,则为该控件建立一个上下文相关的帮助标识符。
Disabled
指定控件初始化时是否禁用。选中表示控件不可用,呈灰色显
示;否则可用
Tab stop
若该项被选中,则用户可以使用【Tab】键选择控件
4.3.4 静态控件

静态控件(Static Control)是一种包含正文或图形的小窗口,通常是用来
显示一个字符串、框、矩形、图标、位图或增强的图元文件的。

静态控件包括

静态文本(Static Text)、

组框(Group Box)

静态图片(Picture)3种。

应用程序通常使用静态控件标记其他控制窗口或分隔不同组别的控件。

一般情况下,静态控件既不接收用户输入也不发出消息,然
而,应用程序可通过设置静态控件的样式使其能够响应用户
输入,向应用程序发送消息。这时的静态文本在功能上相当
于超文本。管理静态文本控件和图片控件的MFC类是
CStatic类,而管理组框控件的MFC类是CButton类。

每一个静态文本控件最多可以显示255个字符,可以使用
“\n”换行符,并可以通过“外观”类的“Align text”下拉
列表框设置显示文本的左后或居中对齐方式,还可以设置空
间的凹陷、凸起及边框风格。
4.3.5 编辑框

编辑框(Edit Box)的主要作用在于接收用户键盘输入,用户
可在编辑框中编辑输入。编辑框是Windows应用程序中一
种重要的交互工具。MFC的CEdit类封装了编辑框的各种操
作。

编辑框通过选取相应的样式可具有以下功能特点:

① 可自动转换用户输入,如大小写转换等;

② 可使用某个字符(如*)代替显示用户的输入;

③ 可支持多行编辑等。
表4.14 编辑框的常用属性及其说明
属性
说明
Multiline
建立多行文本编辑框
Align text
设置文本对齐方式
Number
只能输入数字
Password
编辑框作为密码文本框的字符形式
Border
设置控件周围的边框
Uppercase
所有的字母都大写
Lowercase
所有的字母都小写
Read-Only
文本只读

1.编辑框的基本操作

为了能让编辑框控件允许不同类型数据的输入和读取,用
户需要使用DDV和DDX技术。DDX将控件的成员变量同对
话框类的控件相连接,这样使得数据在控件之间很容易地传
输;DDV用于数据的校验。

2.口令设置

口令设置就是把编辑框设置成一个可输入口令的输入框。
缺省的口令字符是“*”,应用程序可以使用成员函数
CEdit::SetPassWordChar来定义自己的口令字符,该函数
原型如下:

void SetPasswordChar( TCHAR ch );

3.选择文本

用鼠标选择文本的方法是:在要选择的文本的一端按下鼠标
左键并拖动鼠标,到另一端释放鼠标键;用键盘选择文本的
方法是:在按光标方向移动键的同时按住【Shift】键。

在应用程序中也可以通过编程选择文本,这时,需要通过调
用成员函数CEdit::SetSel来实现。这个函数确定了编辑框
内文本的选择范围,与该函数相应的还有CEdit::GetSel和
CEdit::ReplaceSel,它们分别用来获取编辑框控件中前一
选择的开始和结束的位置以及替换被选择的文本。

4.只读设置

只读设置就是把编辑框设置成一个只读的编辑框,这时该编
辑框只能读不能输入和修改。设置的方法是将编辑框的属性
窗口中的属性“Read Only”设置为“True”,就将编辑框设
置成一个只读的编辑框。也可以通过编程来实现编辑框的只
读设置,需要调用成员函数CEdit::SetReadOnly来实现,
该函数的原型说明如下:

BOOL SetReadOnly( BOOL bReadOnly = TRUE );

其中,参数bReadOnly为真,就将编辑框设置为只读;否
则该编辑框可读可写。

5.常见编辑框的通知消息

当编辑框控件的文本被修改或被滚动时,会向其父窗口发送
消息。常见编辑框的通知消息如表4.15所示。
表4.15 常见编辑框的通知消息类型
消息取值
说明
EN_CHANGE
用户在编辑框子窗口中更改了输入框中的数据
EN_ERRSPACE
编辑框的空间已用完
EN_HSCROLL
水平滚动条被按下并披激活
EN_KILLFOUCS
编辑框失去输入焦点
EN_MAXTEXT
输入的正文数超过了编辑框的最大容量
EN_SETFOUCS
编辑框子窗口获得输入焦点
EN_UPDATE
编辑框子窗口将更新显示内容
EN_VSCROLL
垂直滚动条被按下并激活
EN_ALIGN_LTR_EC
将编辑控件的方向从向左改为向右
EN_ALIGN_RTL_EC
将编辑控件的方向从向右改为向左
NM_THEMECHANGED 指示主题已更改

【例4.5】编写一个乘法器程序,当乘数和被乘数编辑框中
输入数字后,可以计算乘法结果。如图4.26所示。

图4.26 输入数据后程序的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
Multiply。

(2) 添加控件和关联的成员变量。
4.3.6 按钮

按钮(Button)是Windows对话框中最常用的控件之一。按
钮控件的类型主要有普通按钮、单选按钮和复选框按钮等。

(1)普通按钮(Button)

普通按钮是最常用的按钮,其外观为矩形条,按钮上可设置
文本或图标、位图等。该类型按钮的作用是帮助用户触发指
定动作。当用户单击按钮时,应用程序立即执行相应动作。

(2)单选按钮(Radio Button)

单选按钮的外形为按钮文本和其左侧的小圆框,当单选按钮
被选中时,该项的圆框将加点显示。单选按钮所包含的各选
项之间一般存在互斥性,即用户只能选择其中某个选项。

(3)复选框(Check Box)

复选框的外形为按钮文本和其左侧的小方框,当复选框按选
中时,该项的方框将加对号显示。复选框常用来显示一组选
项供用户选择。与单选按钮不同,其各选项之间不存在互斥
性,用户可同时选择其中一个或多个选项。

MFC的CButton类封装了按钮控件的各种操作,常见的按钮
通知消息如表4.17所示。
表4.17 常见按钮的通知消息类型
消息取值
说明
BN_CLICKED
用户在按钮子窗口中单击
BN_DOUBLECLICKED
用户在按钮子窗口中双击
BN_SETFOUCS
按钮获得输入焦点
BN_KILLFOUCS
按钮失去输入焦点

【例4.6】编写一个应用程序MyButton,该程序包括单选按
钮和复选框,程序的功能如下:可以在客户区画一个矩形,
利用单选按钮选择是放大显示还是缩小显示,利用复选框决
定是否在客户区和在编辑框中显示。当选择放大显示时,会
在当前矩形大小的基础上以黄色放大绘制矩形;选择缩小显
示时,会在当前矩形大小的基础上以紫色缩小绘制矩形。程
序执行结果如图4.28所示。
图4.28 用户设置后MyButton.exe的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
MyButton。

(2) 添加控件和关联的成员变量。

(3) 在MyButtonDlg.h头文件中添加变量 。

(4)在CMyButtonDlg.cpp中的OnInitDialog函数中对变量
times进行初始化。

(5)添加消息映射函数。
4.3.7 列表框

列表框(List Box)是一个允许用户从已有的项目中进行选择
的控件。列表框中的项目数是可灵活变化的,除了可以在资
源编辑器中通过设置列表框的属性来增减列表框外,还可以
在程序运行时向列表框中添加或删除某些项。MFC的
CListBox类封装了列表框控件的各种操作。

1.列表框的基本操作

列表框中的列表项可以用每一项各自的文本字符串来标识,
还可以通过每一列表项的索引来确定。索引表明项目在列表
框中的排列位置,它从0开始计数,即列表框中第一项的索
引是0,第二项的索引是1,……,以此类推。

(1)添加列表项

列表框创建时是一个空的列表,需要用户添加或插入一些列
表项。CListBox类成员函数AddString和InsertString分别
用来向列表框中增加列表项,其函数原型如下:

int AddString( LPCTSTR lpszItem );

int InsertString( int nIndex, LPCTSTR lpszItem );

(2)列表框的单项选择

当选中列表框中某个列表项时,用户可以使用
CListBox::GetCurSel函数来获取当前选中的列表项的索引
值。与该函数相对应的CListBox::SetCurSel函数是用来设
定某个列表项呈选中状态(高亮显示)。

(3)查找列表框

为了保证列表项不会重复地添加到列表框中,需要对列表框
进行查找,可用CListBox类的成员函数FindString和
FindStringExact在列表框中查找与其所匹配的列表项,其
中,FindStringExact函数的查找精度高。这两个函数的原
型如下:

int FindString( int nStartAfter, LPCTSTR lpszItem )
const;

int FindStringExact( int nIndexStart, LPCTSTR
lpszFind ) const;

(4)删除列表项

利用CListBox类的成员函数DeleteString和ResetContent
可删除指定的列表项或列表框的所有表目,它们的原型如下:

int DeleteString( UINT nIndex );

void ResetContent( );
表4.19 常见列表框的通知消息类型
消息取值
说明
LBN_DBLCLK
字符串列表框中的字符串被双击
LBN_ERRSPACE
分配给字符串列表框的内存已经用完
LBN_KILLFOUCS
字符串列表框失去焦点
LBN_SELCHANGE
在字符串列表框进行的选择发生了改变
LBN_SELCANCLE
指示取消了选定内容
LBN_SETFOUCS
字符串列表框获得输入焦点
NM_THEMECHANGED
指示主题已更改

【例4.7】编写一个应用程序MyList,程序的运行结果如图
4.29所示。该程序的功能是输入一联系人姓名,单击【添加】
按钮,可将其加入到右边的列表框中;在右边的列表框中选
择某一联系人姓名,单击【删除】按钮,可将选定的联系人
姓名删除。
图4.29 MyList.exe的运行结果

程序的实现过程如下:

(1) 利用MFC 应用程序向导创建一个基于对话框的应用程序
MyList。

(2) 添加控件和关联的成员变量。

(3) 添加消息映射函数。
4.3.8 组合框

作为用户输入的接口,组合框(Combo Box)结合了列表框
和编辑框控件的特点,取二者之长,从而完成较为复杂的输
入功能。按照组合框的主要风格特征,可把其分成3类:简
单组合框、下拉式组合框和下拉式列表框。

MFC的CComboBox类封装了组合框控件的各种操作,组
合框的操作可以调用CComboBox的成员函数来实现。
表4.21 常见组合框的通知消息类型
消息取值
说明
CBN_CLOSEUP
组合框的列表关闭
CBN_DBLCLK
选择列表框中的字符串被双击
CBN_DROPDOWN
选择列表框将被取消
CBN_EDITCHANGE
选择列表框中的正文将被修改
CBN_EDITUPDATE
选择列表框中的正文将被更新
CBN_ERRSPACE
分配给选择列表框的内存已用完
CBN_KILLFOUCS
选择列表框失去焦点
CBN_SELENDCANCEL
指示用户选定的内容被取消
CBN_SELENDOK
指示用户选定的内容有效
CBN_SELCHANGE
选择列表框中的选择项发生改变
CBN_SETFOUCS
选择列表框获得焦点
NM_THEMECHANGED
指示主题已更改

【例4.8】编写一个应用程序MyCombobox,该程序的功能
如下:如果在组合框中选择了某门课程,则在组合框下方显
示所选课程。例如,如果在组合框中选择202房间,则在组
合框下方显示“服务器位于202房间”如图4.30所示。

图4.30 用户选择后的MyCombobox.exe的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
MyCombobox。

(2) 添加控件和关联的成员变量。

(3) 在MyComboboxDlg.h头文件中添加成员变量msg和
m_change 。

(4) 添加消息映射函数。

(5)在MyComboboxDlg.cpp实现文件的OnPaint函数中添
加显示文本的代码如下,其中粗体部分为新添加的代码。
4.3.9 滚动条

滚动条(Scroll Bar)是一个独立的窗口,虽然它具有直接的
输入焦点,但却不能自动地滚动窗口的内容,滚动条可分为
水平滚动条和垂直滚动条两种。这两种类型的滚动条的组成
部分是一样的,两端都有两个箭头按钮,中间有一个可沿滚
动条方向移动的滚动块。滚动条控件的各种操作封装在MFC
的CScrollBar类中。

1.滚动条的基本操作

滚动条的基本操作一般包括设置和获取滚动条的范围及滚动
块的相应位置。

(1)设置和获取滚动条的范围

滚动条控件的缺省滚动范围是0-0,所以,如果不设置滚动
条的范围,滚动条的滚动块就无法滚动。可用CScrollBar类
的成员函数SetScrollRange设置滚动条的滚动范围,函数
原型如下:

void SetScrollRange( int nMinPos, int nMaxPos, BOOL
bRedraw = TRUE );

(2)设置和获取滚动块的位置

可用CScrollBar类的成员函数SetScrollPos设置滚动块的
位置,函数原型如下:

int SetScrollPos( int nPos, BOOL bRedraw = TRUE );

与SetScrollPos相应的函数是GetScrollPos,该函数获取
当前滚动块的位置,函数原型如下:

int GetScrollPos( ) const;

2.WM_HSCROLL和WM_VSCROLL消息

当用户对滚动条进行操作时,滚动条就会向其父窗口发送
WM_HSCROLL或WM_VSCROLL消息,这些消息是在滚
动条的父窗口中进行映射的,并产生相应的消息映射函数
OnHScroll和OnVScroll。表4.23列出了滚动条控件的通知
消息。
表4.23 滚动条控件的通知消息
通知消息
说明
SBM_ENABLE_ARROWS
使得一端或两端的滚动条箭头可用
SBM_GETPOS
滚动块的当前位置
SBM_GETRANGE
获取滚动块位置的最大最小值
SBM_GETSCROLLBARINFO
获取指定滚动条的信息
SBM_GETSCROLLINFO
滚动条的参数
SBM_SETPOS
设置滚动块的位置,若与当前位置值不同,
重画滚动条
SBM_SETRANGE
设置滚动块位置的最大最小值
SBM_SETRANGEREDRAW
将滚动块滚动到最小值或最大值位置,重
画滚动条
SBM_SETSCROLLINFO
设置指定滚动条的信息
4.4 公共控件

Visual C++ 2005支持公共控件,在控件工具箱中增加了旋
转按钮、滑块、进度条、标签控件、图像列表、列表视控件、
树形视控件、动画控件、热键控件等。
4.4.1 旋转按钮

旋转按钮控件(Spin)又称为上下控件(Up Down
Control)或微调控件,其主要功能是利用一对标有相反方
向箭头的小按钮,通过点击它来在一定范围内改变当前的数
值。旋转按钮控制的当前值通常显示在一个称为伙伴窗口
(Buddy Window)的控制中,可以是一个编辑框等。旋
转按钮控件的各种操作封装在MFC的CSpinButtonCtrl类中。

1.旋转按钮控件的基本操作

旋转按钮的基本操作包括基数、范围、位置设置和获取等。

(1)基数的设置和获取

CSpinButtonCtrl类的成员函数SetBase用来设置基数,这
个基数值决定了窗口显示的数字是十进制数还是十六进制数。
如果成功则返回先前的基数值;如果给出一个无效的基数则
返回0,该函数的原型如下:

int SetBase( int nBase );

与SetBase函数相应的函数是GetBase,它用于获取旋转按
钮控件的基数,该函数的原型为:

UINT GetBase( ) const;

(2)范围及位置的设置和获取

缺省时,旋转按钮控件的最大值是100,最小值是0,可用
成员函数SetRange或SetRange32来设置旋转按钮的范围,
SetRange32函数是设置旋转按钮的32位范围,这两个函数
的原型如下:

void SetRange( int nLower, int nUpper );

void SetRange32( int nLower, int nUpper );

2.旋转按钮控件的通知消息

旋转按钮控件的通知消息只有一个:UDN_DELTAPOS,它
是当控件的当前数值将要改变时向其父窗口发送的。

【例4.9】编写一个应用程序MySpin,该程序的功能如下:
根据用户选择的RGB值,点击“应用”后利用该值对应的
颜色在对话框的右边画一个矩形。例如红色选择255,绿色
选择255,蓝色选择0,点击“应用”后的对话框如图4.31所
示。

图4.31 用户选择后的MySpin.exe的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
MySpin。

(2) 添加控件和关联的成员变量。

(3) 在MySpinDlg.cpp实现文件的OnInitDialog函数中添加
如下代码,其中粗体部分为新添加的代码,设置旋转按钮的
初值。

(4)添加消息映射函数。
4.4.2 滑块

一个滑块(也称为滑动条或游标)是包含一个滑动块和可选
刻度线的窗口。当用鼠标或方向键拖动滑块时,该控件会发
送通知消息来表明这些改变。

滑块(Slider)是按照应用程序中指定的增量来移动的。滑块
控件的各种操作封装在了MFC的CSliderCtrl类中。

1.滑块的基本操作

(1)范围和位置的设置和获取

成员函数SetRange和SetPos分别用来设置滑块的范围和位
置,其原型如下:

void SetRange( int nMin, int nMax, BOOL bRedraw =
FALSE );

void SetPos( int nPos );

(2)选择范围的设置

成员函数SetSelection设置一个滑块控件中当前选择的开始
和结束位置,函数原型如下:

void SetSelection( int nMin, int nMax );

(3)刻度线尺寸的设置和清除

成员函数SetTic设置滑块控件的一个刻度线的位置,函数成
功调用后返回非零值,否则返回0。该函数的原型如下:

BOOL SetTic( int nTic );

成员函数SetTicFreq设置显示在滑块中的刻度线的疏密程度,
函数原型如下:

void SetTicFreq( int nFreq );

成员函数ClearTics用来从滑块控件中删除当前的刻度线,
函数原型如下: void ClearTics( BOOL bRedraw =
FALSE );

2.滑块的通知消息

滑块的通知消息有TB_BOTTOM、TB_ENDTRACK、
TB_LINEDOWN、TB_LINEUP、TB_PAGEDOWN、
TB_PAGEUP、TB_THUMBPOSITION、
TB_THUMBTRACK和TB_TOP等等。

【例4.10】编写一个应用程序MySlider,该程序的功能如下:
在对话框的右边利用用户选择的线宽和RGB值,点击“应
用”后画一个矩形。矩形外边缘为红色,宽度为线宽,矩形
内部为用户选择RGB值对应的颜色。例如红色选择0,绿色
选择255,蓝色选择0,线宽选择8,点击“应用”后的对话
框如图4.33所示。
图4.33 用户选择后的MySlider.exe的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
MySlider。

(2) 添加控件和关联的成员变量。

(3) 在MySliderDlg.cpp实现文件的OnInitDialog函数中添
加如下代码,其中粗体部分为新添加的代码,设置滑块控件
的初值。

(4)添加消息映射函数。

(5)在类视图中选择话框类CMySliderDlg,在属性窗口中单
击“消息”按钮,添加WM_HSCROLL水平滚动消息的处理
函数OnHScroll,当滑块的位置改变后,静态文本的内容随
之改变。
4.4.3 进度条

进度条(Progress)主要用来进行数据读写、文件拷贝和磁盘
格式等操作时的工作进度提示情况,如安装程序等。伴随工
作进度的进展,进度条的矩形区域从左到右利用当前活动窗
口标题条的颜色来不断填充。

MFC的CProgressCtrl类封装了进度条控件的各种操作,
CProgressCtrl类通常仅作为输出类控制,所以其操作主要
是设置进度条的范围和当前位置,并不断地更新当前位置。

(1)范围及位置的设置和获取

进度条的初始范围为0-100,可用成员函数SetRange或
SetRange32来设置进度条控件的范围,SetRange32函数
是设置旋转按钮的32位范围,这两个函数的原型如下:

void SetRange( short nLower, short nUpper );

void SetRange32( int nLower, int nUpper );

与SetRange函数相应的函数是GetRange,函数原型如下:

void GetRange( int& nLower, int& nUpper );

成员函数SetPos用来设置进度条控件的当前位置,初始值为0,
函数的原型如下:

int SetPos( int nPos );

与SetPos函数相应的函数是GetPos,函数的原型如下:

int GetPos( );

(2)设置色块的填充速度

可用成员函数SetStep设置步长,初始步长为10,函数原型
如下:

int SetStep( int nStep );

StepIt函数用来按照当前步长更新位置,OffsetPos函数用
来直接将当前位置移动一段距离。这两个函数的原型如下:

int StepIt( );

int OffsetPos( int nPos );

【例4.11】编写一个应用程序MyProgress,程序的功能是
当选择“打开”菜单项时,出现如图4.34所示的对话框。
图4.34 选择“打开”菜单项后MyProgress.exe的运行结果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
MyProgress。

(2) 添加控件和关联的成员变量。

(3) 添加菜单资源。

(4) 在MyProgressDlg.cpp实现文件的OnInitDialog函数中
添加如下代码,其中粗体部分为新添加的代码,设置进度条
的初值。

(5)添加消息映射函数。
4.4.4 标签控件、属性表和属性页

标签(Tab)控件也成为选项卡控件,是一个分割成多个页面
的窗口,各页按顺序排列,每次只能看到一个页(当前页)
中的控制,其它页只有标题可见。单击页的标题,可使相应
的页可见(置为当前页),使用【Tab】键可按顺序显示各
页内容。

MFC的CTabCtrl类封装了标签控件的各种操作,基本的操
作如下。

(1)添加标签

CTabCtrl类成员函数InsertItem用来向标签控件中增加标签,
其函数原型如下:

BOOL InsertItem( int nItem, TCITEM* pTabCtrlItem );

BOOL InsertItem( int nItem, LPCTSTR lpszItem );

BOOL InsertItem( int nItem, LPCTSTR lpszItem, int
nImage );

BOOL InsertItem( UINT nMask, int nItem, LPCTSTR
lpszItem, int nImage, LPARAM lParam );

(2)标签的单项选择

当选中某个标签时,用户可以使用CTabCtrl::GetCurSel函
数来获取当前选中的标签。与该函数相对应的
CTabCtrl::SetCurSel函数是用来设定某个标签呈选中状态
(高亮显示)。

int GetCurSel( ) const;

int SetCurSel( int nItem );

(3)删除标签

利用CTabCtrl类的成员函数DeleteItem和DeleteAllItems可删
除指定的标签或标签的所有表目,它们的原型如下:

BOOL DeleteItem( int nItem ); // nItem指定要删除的标签。

BOOL DeleteAllItems( );

(4)删除标签的图像列表

利用CTabCtrl类的成员函数RemoveImage删除标签的图像列
表,函数的原型如下:

void RemoveImage( int nImage );// nImage表示要删除的图
像的索引。

(5)绘制标签控制中的特定一项

绘制标签控制中的特定一项可用成员函数DrawItem实现,
该函数的原型如下:

void DrawItem( LPDRAWITEMSTRUCT
lpDrawItemStruct );

为了更直接实现标签对话框的功能,可以采用一种名为属性
表的窗口,MFC提供了实现属性表的两个类
CPropertySheet和CPropertyPage。

属性表(property sheet)也称为属性对话框,类似于标签对
话框。一个属性表由一个CPropertySheet类对象和多个
CPropertyPage类对象构成。其中,CPropertySheet类或
其派生类对象代表一个属性表,CPropertyPage派生类对
象代表每个属性页。每个属性页对应一个对话框,由于进行
数据的输入输出。CPropertyPage类派生于CDialog类,因
此每个属性页就是一个对话框。

属性表编程的主要步骤如下:
1.
为每个属性页创建属性对话框
2.
为属性对话框添加控件
3.
4.
为每个属性对话框创建CPropertyPage类的派生类,并添
加成员变量和消息处理函数
声明一个CPropertySheet类对象(属性表)和所有的
CPropertyPage派生类对象(属性页),调用函数
AddPage将属性页加入到属性表,显示该属性表。

【例4.12】编写一个应用程序MyTab,执行“画矩形”-“设
置”菜单命令打开一个标签对话框,对话框有两个标签页面,
在每个页面分别显示“设置颜色”和“设置线宽”对话框,
点击“设置颜色”页面后,显示的对话框如图4.35所示;点
击“设置线宽”页面后,显示的对话框如图4.36所示。该程
序实现的功能同【例4.10】。

程序的实现过程如下:
(1)利用MFC应用程序向导创建一个基于单文档的应用程序
MyTab。
(2)添加对话框资源和对话框类。
(3)添加控件和关联的成员变量。
(4)添加消息映射函数。
(5)在MyTabView.h头文件中定义成员变量。
(6)添加菜单项以及消息映射函数。
(7)在CMyTabView类实现文件MyTabView.cpp中的
OnDraw函数中添加如下代码,用于绘制一个矩形,其中粗
体部分为新添加的代码。
4.4.5 图像列表

图像列表(Image List)是相同大小图像的一个集合,每个集
合中均以0为图像的索引序号基数,图像列表通常由大图标
或位图构成,其中包含透明位图模式,图像列表控件提供了
控制图像列表的基本方法。MFC的CImageList类封装了图
像列表控件的各种操作,该类由CObject类派生而来。

图像列表控件的操作方法包括将一个图像列表绑定到一个对
象上、将对象上的图像列表解除绑定并返回句柄、删除一个
图像列表、将一个图像增加到图像列表中和将一个图像从图
像列表中删除等。

1.图像列表控件的基本操作

(1)将一个图像列表绑定到一个对象上

将一个图像列表绑定到一个对象上可用CImageList类的成
员函数Attach来实现,该函数的原型如下:

BOOL Attach( HIMAGELIST hImageList );// hImageList
是图像列表对象的指针。

(2)将对象上的图像列表解除绑定并返回句柄

CImageList类的成员函数Detach实现将对象上的图像列表
解除绑定并返回句柄,函数的原型如下:

HIMAGELIST Detach( );

(3)删除一个图像列表

删除一个图像列表可用CImageList类的成员函数
DeleteImageList来实现,该函数的原型如下:

BOOL DeleteImageList( );

(4)将一个图像增加到图像列表中

将一个图像增加到图像列表中可用CImageList类的成员函
数Add来实现,该函数的原型如下:

int Add( CBitmap* pbmImage, CBitmap* pbmMask );

int Add( CBitmap* pbmImage, COLORREF crMask );

int Add( HICON hIcon );

(5)将一个图像从图像列表中删除

将一个图像从图像列表中删除可用CImageList类的成员函
数Remove来实现,该函数的原型如下:

BOOL Remove( int nImage );// nImage表示删除的图像的
索引值。

2.图像列表控件的应用

图像列表控件不能单独使用,必须与列表控制、树控制和标
签控制相互结合应用。

(1)图像列表控件在列表控制中的应用

① 设置图像列表控件CListCtrl::SetImageList的调用格式
如下:

CImageList* SetImageList( CImageList* pImageList, int
nImageList );

② 取得图像列表控件CListCtrl::GetImageList的调用格式
如下:

CImageList* GetImageList( int nImageList ) const;

(2)图像列表控件在树形视图控制中的应用技巧

① 设置图像列表控件CTreeCtrl::SetImageList的调用格式
如下:

CImageList* SetImageList( CImageList * pImageList, int
nImageListType );

② 取得图像列表控件CTreeCtrl::GetImageList的调用格式
如下:

CImageList* GetImageList( UINT nImage );

(3)图像列表控件在标签控制中的应用技巧

① 设置图像列表控件CTabCtrl::SetImageList的调用格式

CImageList * SetImageList( CImageList * pImageList );

② 取得图像列表控件CTabCtrl::GetImageList的调用格式

HIMAGELIST GetImageList() const;
4.4.6 列表视控件

列表视(List View)控件也称为列表控件,是一种常用的控件。
当使用一个列表控件时,可以提供一个菜单或是其他方法使
用户可以在不同的显示模式中切换。与列表控件不同的是,
列表视控件可以显示由多个子项组成的项目,并允许以多种
方式显示信息。

列表控件提供了对Windows列表功能操作的基本方法,而
使用列表视的视函数可以对列表视进行各种操作,通过调用
成员函数GetListCtrl获取嵌在列表视内列表控制的引用,就
可以和列表控制一样进行各种操作。

列表控制的操作方法:

(1)插入和删除一个表项

可使用成员函数InsertItem和DeleteItem插入和删除一个表
项,这两个函数的原型如下:

int InsertItem( const LVITEM* pItem );

int InsertItem( int nItem, LPCTSTR lpszItem );

int InsertItem( int nItem, LPCTSTR lpszItem, int
nImage );

int InsertItem( UINT nMask, int nItem, LPCTSTR
lpszItem, UINT nState, UINT nStateMask, int nImage,
LPARAM lParam );

BOOL DeleteItem( int nItem ); // nItem指定要删除的表项
的索引值。

(2)插入和删除一个表列

成员函数InsertColumn和DeleteColumn用于插入和删除一
个表列,这两个函数的原型如下:

int InsertColumn( int nCol, const LVCOLUMN*
pColumn );

int InsertColumn( int nCol, LPCTSTR
lpszColumnHeading, int nFormat = LVCFMT_LEFT, int
nWidth = -1, int nSubItem = -1 );

BOOL DeleteColumn( int nCol ); //nCol表示要删除表列
的索引值。

(3)排序表项和测试列表的位置

成员函数SortItems和HitTest用于排序表项和测试列表的位
置,这两个函数的原型如下:

BOOL SortItems( PFNLVCOMPARE pfnCompare,
DWORD dwData );

int HitTest( LVHITTESTINFO* pHitTestInfo ) const;

int HitTest( CPoint pt, UINT* pFlags = NULL ) const;

(4)编辑一个表项文本和重绘一个表项

成员函数EditLabel和DrawItem用于编辑一个表项文本和重
绘一个表项,这两个函数的原型如下:

CEdit* EditLabel( int nItem );

virtual void DrawItem( LPDRAWITEMSTRUCT
lpDrawItemStruct );
4.4.7 树视控件

树视(Tree View)也称为树控件,主要用来显示具有一定
层次结构的数据项,如资源管理器中的磁盘目录等,以供用
户在其中进行各种选择。

树视控件中每个项目由项目名称和一个可选择的图标组成,
其中的项目分为父项目和子项目,一个父项目拥有一个子项
目列表,双击该父项目可以展开或折叠其中的子项目。树视
控件中最上一层的项目叫做根节点,最低一层的项目叫做叶
节点,介于它们之间的项目叫做枝节点。

对于树控制,MFC中也以两种形式来封装,即树控制
(CTreeCtrl类)和树视(CTreeView类),来满足用户的
不同需求。
树形视图控制的操作方法:
(1)展开或合拢树项的子项
 成员函数Expand用于展开或合拢树项的子项,该函数的
原型如下:

BOOL Expand( HTREEITEM hItem, UINT nCode );

(2)选中特定树项

成员函数SelectItem用于选中特定树项,该函数的原型
如下:

BOOL SelectItem( HTREEITEM hItem );//hItem表示树
项的句柄。

(3)选择一个树项作为第一个可视树项

成员函数SelectSetFirstVisible用于选择一个树项作为第一
个可视树项,该函数的原型如下:

BOOL SelectSetFirstVisible( HTREEITEM hItem );

(4)排序给定父树项的子树项

成员函数SortChildren用于排序给定父树项的子树项,该函
数的原型如下:

BOOL SortChildren( HTREEITEM hItem );
4.5 综合实例
4.5.1 计算器应用程序的设计

【例4.13】 计算器应用程序

该程序的运行结果如图4.37所示:选中【科学型】按钮,就
会出现如图4.38所示的运行结果。

图4.37 计算器应用程序的运行结果
图4.38 【科学型】按钮的计算器界面
4.5.2 资源管理器程序的设计

【例4.14】 资源管理器程序,该程序具有对磁盘文件的浏
览功能。该资源管理器能够通过树视控件和列表视控件浏览
磁盘文件,用户可以通过鼠标左键的单击查看文件和目录列
表,并且能够通过鼠标的右键和菜单对文件按照大图标、小
图标、列表和报表的方式查看文件。该资源管理器的实际效
果如图4.39所示。
图4.39 资源管理器的运行效果

程序的实现过程如下:

(1) 利用MFC应用程序向导创建一个基于对话框的应用程序
Myexplorer。

(2) 添加控件和关联的成员变量。

(3) 添加菜单资源

(4) 实现系统图标列表类CSystemImageList

(5) 实现树视控件类CTreeDirCtrl类

(6) 实现树视控件类CListDirCtrl类

(7) 实现资源管理器功能

(8) 创建快捷菜单