1.65k likes | 1.79k Views
第 4 章 对话框与控件. 引言. 了解 对话框的组成与分类 理解 两种不同类型的对话框的编程过程 掌握 基于对话框的应用程序的编程方法 掌握 标准控件的编程方法 掌握 公共控件的编程方法. 4.1 对话框概述. 在 Windows 应用程序中最重要的用户界面元素之一就是对话框。几乎所有的 Windows 应用程序部要借助于对话框窗口来和用户打交道。。. 4.1.1 对话框的组成与分类. 1 .对话框的组成 a 对话框资源 b 对话框类. 2 .对话框的分类 对话框有 两种类型 : a 模式对话框 b 无模式对话框 。
E N D
引言 • 了解对话框的组成与分类 • 理解两种不同类型的对话框的编程过程 • 掌握基于对话框的应用程序的编程方法 • 掌握标准控件的编程方法 • 掌握公共控件的编程方法
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是一个基于对话框的应用程序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类的派生类中可以直接调用,另外大部分函数是虚函数,可以在用户的派生类中重载,实现特定目的。CDialog类是CWnd类的继承类,所以它继承了CWnd的基本功能,如移动窗口、改变窗口大小、关闭窗口等。CDialog类通过对话框的一些特定的特性扩展了基本功能。这些特性包括生成和显示对话框的功能、遍历对话框的控件、设置和恢复默认按钮等。CDialog类经常使用的成员函数列于表4.1,在CDialog类的派生类中可以直接调用,另外大部分函数是虚函数,可以在用户的派生类中重载,实现特定目的。
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函数以初始化对话框中的控件。
对话框数据交换是在对话框类中由DoDataExchange函数完成的,这个函数由UpdateData函数调出。对话框数据交换是在对话框类中由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所对应的字符串。这四个函数都是用来创建和显示提示信息对话框的,AfxMessageBox函数实际上是对API函数MessageBox的封装。四者的功能基本相同,但适用范围是有区别的。AfxMessageBox函数和::MessageBox,在程序中的任何位置都可调用;而CWnd::MessageBox函数只能用于象控件、对话框和窗口等窗口类中。AfxMessageBox函数第一种形式中消息框的标题将由MFC框架取为主应用程序名,第二种形式中消息框的内容以nIDPrompt为ID号,从符号表中获得ID所对应的字符串。
在实际使用中,图标类型及按钮类型的取值可通过“|”组合。如:AfxMessageBox(_T(“是否要退出系统”),MB_YESNO|MB_ICONWARNING)语句得到的提示信息对话框如图4.5所示。在实际使用中,图标类型及按钮类型的取值可通过“|”组合。如:AfxMessageBox(_T(“是否要退出系统”),MB_YESNO|MB_ICONWARNING)语句得到的提示信息对话框如图4.5所示。 • 图4.5 警告信息对话框
4.2 使用对话框 • 使用对话框的一般步骤 • 1 首先要创建对话框资源和与其相关联的对话框类, • 2 添加控件、与控件关联的成员变量和消息映射函数, • 3 程序中显示对话框。
4.2.1 一般对话框工作流程 • 定义一个对话框类之后,就可以利用这个对话框类声明一个对话框对象。定义自己的对话框类一般用CDialog类作为基类,在声明一个对话框对象时调用了对话框类的构造函数,并自动调用基类CDialog的构造函数。声明一个对话框对象后,可以调用对话框类的成员函数DoModal建立对话框窗口并显示对话框。假设定义了一个名为CHelloDlg的对话框类,则以下代码用于显示对话框。 • CHelloDlg hellodlg; • hellodlg.DoModal();
当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函数,该函数关闭当前对话框。对话框中大都有【确定】和【取消】按钮,当单击它们时关闭对话框,结束对话框消息循环。单击【确定】按钮调用CDialog::OnOK函数,单击【取消】按钮调用CDialog::OnCancel函数。二者都结束DoModal函数的调用,OnOK函数令DoModal函数返回IDOK,OnCancel函数令DoModal函数返回IDCANCEL,可以根据DoModal函数的返回值做出不同的选择。OnOK函数和OnCancel函数都调用了EndDialog函数,该函数关闭当前对话框。 • 一般对话框的工作流程如图4.6所示,其中双向箭头表示调用关系。
4.2.2 创建对话框 • 在Windows中对话框是作为一种资源被使用的,在程序中创建一个对话框,首先要创建一个对话框资源,然后创建一个基于该对话框资源的对话框类。对话框资源指定了对话框本身的属性和对话框中控件的属性,对话框类规定了对话框和对话框中每个控件的行为。 • 【例4.2】创建一个应用程序Score,生成如图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.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类的派生类。