




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第6章 创建和使用对话框精讲对话框是一种用户界面,几乎每一个Windows程序都使用对话框与用户进行交互。对话框可能是一个简单的只含有OK按钮的消息框,也可以是一个复杂的数据输入表单。对话框上有一些方便用户输入的控件,对话框依靠这些控件与用户进行交互,其实质是一个接收消息的窗口。在本章节我们主要讲述模式对话框和无模式对话框的原理和使用方法,下一章将详细介绍各种控件的使用。你将学习创建一个对话框,使用对话框模板编辑一个对话框资源,并在程序中调用对话框的方法。6.1 对话框的基本原理6.1.1 对话框的工作原理在创建一个对话框之前,我们先来了解一下对话框是如何工作的,对话框的数据来自三方面:对话框
2、资源、对话框对象、和一个文档对象:1 对话框资源对话框资源是一个用户输入或取得数据的图形界面。这个图形界面是使用Develop Studio的对话框编辑器在对话框模板上创建的,程序员可以在对话框模板上增加并编辑控件,生成对话框资源。当应用程序运行时,就可以得到一个对话框。2 对话框对象MFC使用CDialog类来描述对话框,它是CWnd类的派生类。在CWnd类的基础上增加了数据交换的功能。当创建一个新的对话框资源后,使用ClassWizard可以创建一个对话框类的派生类。对话框对象实现了对话框和应用程序之间的通信。在应用程序中定义一个对话框对象后,在对话框显示前,可以通过访问对话框对象的成员变
3、量为一个对话框的控件初始化,在对话框关闭后,可以通过访问对话框对象的成员变量获得用户的输入数据。3 文档对象MFC使用文档对象描述应用程序处理的数据,用户输入的数据要进一步的处理,通常要先存贮到文档对象中。例如:一个学生记录处理的应用程序,用户通过一个对话框输入学生记录并贮存到一个文件中。应用程序的处理顺序是:用户在对话框中输入信息,通过对话框对象得到输入信息,将输入信息整理到文档对象中,使用序列化函数将文档对象存贮到一个文件中,所以文档对象扮演了一个很重要的数据交换的角色。MFC使用以上三者实现用户与应用程序之间数据交换,数据交换流程见图6-1所示,遵循四个步骤。Public:data me
4、mberdocumentxxxxxxxxxxxxxxxxxxxxxxxxxxxx创建对话框模板1数据交换和验证2定义对话框类和3公有成员变量运行对话框,修改4文档对象图6-1对话框基本原理6.1.2 对话框的类型对话框分为模式对话框和无模式对话框两种。当一个模式对话框打开了,在其关闭之前,用户不能转向其它用户界面对象,只能与该对话框进行交互。我们平时接触到的对话框,大多数都是模式对话框,例如,一个执行菜单命令File->Save后,Save对话框被打开后,用户不能再做其它工作,只能保存完文件或取消保存文件,关闭对话框窗口后,才能做其它工作。无模式对话框恰恰相反,当用户打开一个无模式对话框
5、,对话框停留在屏幕上,仍然允许用户与其它用户界面对象进行交互。无模式对话框最典型的例子是在Word中使用的查找与替换对话框,打开该对话框后,可以交替地进行文档编辑,和查找替换操作。从第一节的介绍可以看到对话框的设计任务主要包括对话框资源模板的设计,对话框类的设计和对话框的运行,绝大多数对话框的创建任务,模式对话框和无模式对话框都是相同的,只有在对话框与应用程序代码的交互中,也就是对话框的运行中,两者有明显的区别。6.2设计对话框资源6.2.1创建对话框使用AppWizard生成的单文档或多文档应用程序,只有一个默认的About对话框,用于显示应用程序版本信息。需要使用对话框模板创建自己的对话框
6、资源。Develop Studio提供的对话框模板创建了一个基本界面,包括一个OK(确定)按钮和一个Cancel(取消)按钮等。你可以移动、修改、删除这些控件,或者是增加新的控件到对话框模板,构成应用程序所需的对话框资源。创建一个对话框资源到工程的步骤:(1) 使用AppWizard生成一个单文档的MFC应用程序Exam6_1。(2) 选择Insert->Resource菜单命令。(3) 在弹出的Insert Resource对话框左边的列表中选择Dialog,单击New按钮。(4) 在项目工作区中选择ResourceView面板,展开Dialog文件夹,可以看到增加了一个对话框资源ID
7、D_DIALOG1,如图6-2所示,双击IDD_DIALOG1,在编辑区出现一个对话框模板。控件工具栏对话框模板对话框资源ID图6-2 Exam6_1对话框设计新建对话框资源6.2.2增加控件一个控件是能够放置在一个对话框中,提供应用程序与用户交互的某种功能。例如,Edit Box提供用户文本输入的场所,一组Radio Button提供用户对某一主题的单项选择。MFC将控件设计为对话框窗口的子窗口,控件通过事件通知消息与父窗口联系。在一个对话框资源中增加控件的操作十分方便,只需从图6-2所示的控件工具栏中选中要增加的控件,再将此控件拖拉至对话框模板中的确定位置上,松开鼠标按键即生成一个控件。调
8、整控件的位置和大小的操作与Word中对文本框的操作完全一样。在默认情况下,控件工具栏总是打开的,如果没有打开,可以在Develop Studio工具栏后的空白处,单击鼠标右键,在弹出的快捷菜单中选择Controls,便可打开控件工具栏。图6-3中列出了VC6.0中支持的标准控件名称,我们可以很方便地从控件工具栏中生成新的控件,但每一种控件都具有不同的特性,需要学习和掌握。Check BoxGroup BoxPicture Edit ControlVertical Scroll BarProgressHot KeyTree ControlAnimateDate Time PickerCustom
9、 ControlIP AddressExtended Combo BoxCombo BoxTab ControlMonth CalenderRadio ButtonButtonList BoxRich EditList ControlSliderSelection ToolStatic TextHorizontal Scroll BarSpin 图6-3 标准控件 下面我们试着设计一个可以输入5门功课成绩的输入窗口,在上一节生成的对话框资源IDD_DIALOG1中做以下操作,得到如图6-4所示的对话框:(1) 调整对话框模板窗口大小,将OK和Cancel按钮移到窗口的底部。(2) 控件工具栏中
10、选中Static Text(静态文本)控件,拖到对话框模板中。(3) 通过复制和粘贴操作,生成其它四个Static Text控件。(4) 控件工具栏中选中Edit Box控件(编辑框),拖到对话框模板中。(5) 通过复制和粘贴操作,生成其它四个Edit Box控件图6-4EX6对话框设计增加控件6.2.3设置控件属性一个控件相关的属性设置决定了一个控件可操作行为和显示。例如,控件的ID是控件的一个重要属性,MFC内部是以控件ID来标识一个控件,当消息产生后,是哪一个控件需要进行处理,MFC内部使用的是控件ID。属性的设置是在与每个控件相对应的属性对话框中进行的,单击鼠标右键,在弹出的快捷菜单中
11、选择Properties,打开属性对话框。每一种控件的属性对话框都有所不同,与其特性相关,在下一章我们将详细介绍一些常用控件的属性含义。对上一节的对话框IDDDIALOG1中的控件作属性设置:(1) 鼠标选中第一个Static Text对象,单击鼠标右键,在弹出的快捷菜单中选择Properties,弹出属性对话框,如图6-5所示。图6-5属性对话框设置(2) 修改Caption右边的文本框,输入“高等数学”,单击关闭按钮,关闭属性对话框。(3) 重复步骤(1)(2),将其它四个Static控件的Caption改为“大学物理”,“大学英语”,“哲学”和“计算机基础”。(4) 同样的操作打开5 个
12、Edit Box控件的属性对话框,修改ID为IDC_SCORE1、IDC_SCORE2、IDC_SCORE3、IDC_SCORE4、IDC_SCORE5。(5) 打开按钮OK的属性对话框,修改Caption为“确定”。(6) 打开按钮Cancel的属性对话框,修改Caption为“取消”。操作完毕,对话框如图6-6所示。图6-6EX6对话框设计设置属性同样,对话框的属性设计也是在对话框的属性对话框中设置,在对话框任意空白处单击鼠标右键,在弹出的快捷菜单中选择Properties,如图6-7所示。在Caption中填写“成绩录入”,将成为对话框的标题,单击Font会弹出字体对话框,能设置对话框中
13、显示的字体格式。其它的几个标签页还提供了选项,可以修改对话框窗口的显示样式,可以自己试一试。图6-7对话框属性设置6.2.4组织和安排控件当选择了一个对话框资源进入对话框编辑器时,Develop Studio的菜单栏上会增加一个菜单Layout,如图6-8所示。Layout 菜单提供了在对话框模板中合理布置控件的功能菜单项。Align提供了控件的六种对齐方式:左对齐、右对齐、上对齐、下对齐、水平居中、垂直居中。Space Evenly提供了两种等间距方式:垂直方向等间距、水平方向等间距。Make Same Size提供了三种等尺寸方式:宽相等、高相等、两者都相等。Arrange Button提
14、供了两种组织按键的方式:底部排列、右边排列。Center in Dialog提供了两种居中方式:水平居中、垂直居中。Flip用于水平反方向显示控件及窗口标题。Size to Content命令根据内容决定控件的大小,例如,按钮的大小由按钮上的显示文本决定。图6-8Layout下拉菜单通过上面几个菜单项的操作能够很方便地齐整控件的摆放位置。现在我们可以整理一下IDD_DIALOG1中 摆放凌乱的控件:(1) 确定第一个和最后一个Static Text控件的位置,同时选中5个Static Text控件,执行菜单命令Layout->Make Same Size-width(2) 执行菜单命令L
15、ayout->Align-Bottom,水平对齐5个控件。(3) 执行菜单命令Layout->Space Evenly-Across,使5个控件水平等间距。(4) 选择“哲学”,执行菜单命令Layout->Size to Content,微调控件位置(5) 确定第一个和最后一个Static Text控件的位置,同时选中5个Static Text控件,执行菜单命令Layout->Align->Bottom和Layout->Space Evenly->Across。操作完毕,可以看到控件整齐地排放在对话框模板上,如图6-9所示。图6-9EX6对话框设计整理
16、控件在Windows环境中通常提供两种操作方法,鼠标操作方式和键盘操作方式,使用鼠标可以直接点击控件进行访问,使用键盘访问控件需要通过Tab键顺次找到某个控件。Tab Order规定了使用Tab键访问控件的顺序,一般Tab Order是控件生成的顺序,执行菜单命令Layout->Tab Order可以显示并修改Tab Order,对IDD_DIALOG1执行菜单命令Tab Order 如图6-10所示。图6-10显示Tab Order改变Tab Order的方法既简单又直观,执行了Tab Order命令出现了顺序号之后,按你所想要的访问顺序依次点击每一个控件,完成后,点击空白处就可以了。
17、读者可以试练习将上图的Tab顺序变成先访问第一个Edit Box,访问完所有的Edit Box后再访问Button。6.2.5测试对话框当构造好一个对话框后,还不能立即在应用程序中运行对话框,MFC提供了Test命令,使程序员在设计阶段就能够测试对话框的运行效果。测试对话框的方法有:(1) 菜单命令Layout->Test(2) Dialog工具栏上的Test按钮(3) 快捷键Ctrl+T测试对话框IDD_DIALOG1,试着使用文本框输入,并使用Tab键是否符合要求。如图6-11所示。测试对话框窗口图6-11Exam6_1对话框设计测试对话框6.3设计对话框类一个对话框资源要加入到一个
18、窗口应用程序中,首先要为它创建一个对话框类,是CDialog类的派生类。应用程序运行时,窗口操作系统使用对话框类为对话框在内存开辟空间。在Win32 API类型的窗口应用程序中,都是直接通过控件ID来访问对话框上的控件的,而MFC提供了连接变量来标识控件,连接变量是对话框的成员变量,同时对话框类有一套交换和验证数据的方式。6.3.1 创建对话框类创建对话框类的步骤如下:1 保存已创建好的对话框模板。2 确保新的对话框资源在对话框编辑器中打开状态下,打开ClassWizard窗口。打开ClassWizard的方式有3种:(1) 窗口菜单命令View->ClassWizard(2) 快捷菜单
19、命令ClassWizard(3) 快捷键:Ctrl+w3 在弹出的Adding a Class对话框中,如图6-12所示,选择Create a new class单选钮,单击OK按钮。图6-12“增加类”对话框4 在随后弹出的New Class对话框中,如图6-13所示,只需填写类的名称:CScoreDlg,单击OK按钮。关闭ClassWizard,对话框类的创建就完成了。填写类名图6-13填写新类名称在Workspace窗口的ClassView面板中,可以看到增加了一个新的类CScoreDlg,选择FileView面板,在Header Files和Source Files文件夹中,可以看到该
20、类的头文件和实现文件,文件名是类名除去开头的类标志“C”。 图6-14新增对话框类及文件在创建新类的时候,要注意新类的对话框ID一定要与对话框资源ID一致,这些ID告诉对话框类,在对话框窗口创建前,哪一个对话框资源要被检查,初始化控件并显示。尤其在创建好对话框后,不能随意地改动对话框资源ID和删除对话框资源。6.3.2 创建对话框成员变量创建好一个对话框类后,可以增加类的成员变量来操作对话框上的控件。出于不同的操作目的,MFC提供了两种类型的成员变量,如表6-1所示。表6-1对话框类的成员变量类型类 型描 述Values值类型的成员变量。用于控件的值控制,可以有多种数据类型,由所连接的控件类型
21、决定。例如,Edit Box控件可以有CString型或int型。RadioButton可以是int型。Controls控件类型的成员变量,实质是该控件类的一个对象。创建了一个控件对象,就可以通过该对象使用控件类的方法对控件进行操作,例如,在程序运行时为Combo Box加入选择项,设置控件是否有效或可见等。例如,创建了CScoreDlg类后,需要为对话框中每一个Edit Box控件创建一个值类型的成员变量,来取得用户在EditBox输入的数据,增加控件成员变量的步骤如下:(1) 打开ClassWizard窗口,选择Member Variables标签页,Class name下拉列表中选择CS
22、coreDlg类。这时,对话框中可以创建成员变量的控件ID出现在下方的Control IDs列表中,如图6-15所示。图6-15增加一个对话框类的成员变量(2) 选择一个IDC_SCORE1,单击Add Variable按钮,弹出Add Member Variable对话框,Member variable name编辑框中填写变量名为:m_score1,确认Category下拉框中为:Value,在Variable type下拉框中选择为:int。(3) 单击OK按钮,回到ClassWizard窗口,可以看到新增的成员变量出现在列表中。同样的操作增加其它四个成员变量。(4) 如果增加成员变量时
23、操作有误,例如变量名错误,变量类型错误,选择该成员变量,单击Delete Variable按钮删除该变量,再重新创建。创建好的成员变量如图6-16所示。变量类型变量名称图6-16成员变量列表创建好成员变量后,我们来检查一下ClassWizard作了哪些工作:(1) 展开项目工作区的ClassView面板中的CScoreDlg类,在树目录上出现了刚创建的成员变量。(2) 双击CScoreDlg的类名,进入该类的头文件ScoreDlg.h,可以找到对话框类定义的代码,如程序清单6-1中所示。程序清单6-1:对话框成员变量定义示例class CScoreDlg : public CDialog/ C
24、onstructionpublic:CScoreDlg(CWnd* pParent = NULL); / standard constructor/ Dialog Data/AFX_DATA(CScoreDlg)enum IDD = IDD_DIALOG1 ;intm_score1;intm_scroe2;intm_score4;intm_score5;intm_score3;/AFX_DATA. .其中呈灰色显示的,在宏“AFX_DATA(CScoreDlg).AFX_DATA”之间定义的是用ClassWizard创建的成员变量。需要注意的是,所有ClassWizard 产生的灰色显示的代码
25、,不要在文件中直接修改,而应在ClassWizard工具中进行修改,不然容易引起错误。(3) 打开该类的构造函数,可以看到ClassWizard自动加入了成员变量的初始化代码,如程序清单6-2所示。程序清单6-2:对话框类的构造函数CScoreDlg:CScoreDlg(CWnd* pParent /*=NULL*/): CDialog(CScoreDlg:IDD, pParent)/AFX_DATA_INIT(CScoreDlg)m_score1 = 0;m_scroe2 = 0;m_score4 = 0;m_score5 = 0;m_score3 = 0;/AFX_DATA_INIT6.3
26、.3 对话框数据交换和校验对话框的值类型的成员变量存储了与控件相对应的数据,对框话打开时,用户可以修改控件的数据,有时需要应用程序对用户的输入进行及时反馈,这时数据成员变量需要与控件交换数据,以完成输入输出功能。对于这种功能MFC是靠CDataExchange类提供的数据交换(DDX:Dialog Data Exchange)机制来完成的,该类提供了数据有效机制(DDV:Dialog Data Validation)当在对话框类中增加一个数据成员变量,有时需要规定数据的有效性校验规则,例如,成绩录入对话框中,应设置各门课的成绩应在0100的范围内。在应用程序运行的时候,当用户输入数据拷贝到数据
27、成员变量时,DDV机制被调用,如果有效性校验失败,即用户输入一个不合理的数据时,将出现一个错误信息对话框,并返回到出现错误输入的控件。有效性校验的设置也是在ClassWizard中完成的。我们再回到成绩录入的Member Variables标签页,选择表示成绩输入框的m_score1,在标签页的下方会出最大值和最小值的输入框,如图6-17所示,填入0和100。如果一个CString型的数据成员变量对应的通常是字符串的长度。图6-17添加数据成员变量的有效范围对话框类调用DoDataExchange函数来实现DDV和DDX,对应图6-17的CScoreDlg类的DoDataExchange代码如
28、程序清单6-3所示。程序清单6-3:对话框类的DoDataExchange函数void CScoreDlg:DoDataExchange(CDataExchange* pDX)CDialog:DoDataExchange(pDX);/AFX_DATA_MAP(CScoreDlg)DDX_Control(pDX, IDOK, m_OK); /控件对象数据交换DDX_Control(pDX, IDC_SCORE5, m_Score5Edit); /文本框数据交换DDX_Control(pDX, IDC_SCORE4, m_Score4Edit);DDX_Control(pDX, IDC_SCORE
29、3, m_Score3Edit);DDX_Control(pDX, IDC_SCORE2, m_Score2Edit);DDX_Control(pDX, IDC_SCORE1, m_Score1Edit);DDX_Text(pDX, IDC_SCORE2, m_score2);DDX_Text(pDX, IDC_SCORE3, m_score3);DDX_Text(pDX, IDC_SCORE4, m_score4);DDX_Text(pDX, IDC_SCORE5, m_score5);DDX_Text(pDX, IDC_SCORE1, m_score1);DDV_MinMaxInt(pDX
30、, m_score1, 0, 100); /最大最小值检查/AFX_DATA_MAPpDX指针指向一个CDataExchange对象,DDX函数来完成控件和数据成员变量之间的数据交换,DDV完成数据有效性检查。DDX和DDV适用于文本框、复选框、单选按钮、列表框和组合框。当程序需要交换数据时,不需要编写代码调用DoDataExchange函数,而应该调用CWnd:UpdateData()函数,UpdateData()函数内部调用了DoDataExchange函数。UpdateData()函数只有一个BOOL类型的参数,决定数据交换的方向:(1) UpdateData(false)将对话框对象的
31、数据成员变量的值拷贝到对话框中的控件。(2) UpdateData(true)将对话框中控件的值拷贝到对话框对象的数据成员变量。你可以随时在需要进行数据交换时调用相应的UpdateData()函数,例如,在成绩录入的对话框中增加两个控件,一个是Edit Box用于显示总分,另一个是Button用于计算总分,则在Button的Click事件处理函数中,就需要先调用UpdateData(true)获取用户录入的5门功课的成绩,在计算总分后,调用UpdateData(false),将总分显示在Edit Box中。DDXPublic:data memberdocumentxxxxxxxxxxxxxxx
32、xxxxxxxxxxxxx框架处理对话框和对象之间的数据交换和验证编写代码在文档对象和对话框对象之间交换数据DDX and DDV在默认的CDialog:OnInitDialog()函数中调用了UpdateData(false),这样在对话框创建的时候,数据成员的初值就会反映到相应的控件上。若用户单击OK(确定)按钮关闭对话框,CDialog:OnOK()函数会调用UpdateData(true),将控件中的数据传给数据成员变量,如图6-18所示。图中说明了对话框的控件与对话框对象之间的数据交换是由框架自动完成的,而对话框对象与文档对象之间的数据交换则需要编写代码。图6-18数据交换和验证在应
33、用程序中的实现 6.4 运行对话框创建好一个对话框资源和对话框类,要在应用程序中运行对话框,通常要在一个菜单命令下打开一个对话框。所以,首先要定义一个菜单项和相应的菜单命令处理函数,在函数中编写代码运行对话框。运行模式对话框和无模式对话框有所不同,下面结合实例详细介绍两种对话框运行的方法。6.4.1模式对话框在应用程序中使用得更多的还是模式对话框,模式对话框的运行分两个步骤:(1) 创建一个对话框对象(2) 调用CDialog:DoModal()函数打开对话框DoModal()函数负责模式对话框的创建和撤消。在创建对话框时,DoModal()的任务包括:装载对话框资源、调用OnInitDial
34、og()初始化对话框和将对话框显示在屏幕上。完成对话框的创建后,DoModal()启动一个消息循环,以响应用户的输入。这时,用户只能与对话框进行交互,其它用户界面对象收不到输入信息,只有终止模式对话框后才能进行其它工作。若用户在对话框内单击了系统默认的OK(确定)按钮,则CDialog:OnOK()函数将被调用,OnOK()首先调用UpdateData(true)函数,将数据从对话框中的控件拷贝到数据成员变量,再调用CDialog:EndDialog()关闭对话框,并返回值IDOK。若用户在对话框单击了系统默认的Cancel(取消)按钮,则CDialog:OnCancel()函数将被调用,该函
35、数只调用CDialog:EndDialog()关闭对话框,并返回值IDCANCEL。程序可以根据返回值是IDOK还是IDCANCEL来判断用户关闭对话框按的哪一个键。下面我们将运行成绩录入对话框,当按“确定”按钮返回时,将其显示在主窗口视图上。为此,要定义对应的文档对象。步骤如下:1 增加文档类公有变量并设置初值int型成员变量数组score5,存放5门课程成绩;int型成员变量TScore,用来存放总分。在构造函数中设置数组score和TScore的初值都为0。2 在视图类OnDraw函数中添加代码实现成绩的输出具体代码见程序清单6-4所示粗体部分。程序清单6-4:OnDraw函数输出int
36、型文档类成员变量的值void CExam6_1View:OnDraw(CDC* pDC)CExam6_1Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);/ TODO: add draw code for native data herepDC->TextOut(0,0,"高等数学大学物理大学英语哲学计算机基础总分") ;/输出表头CString str;/将int型数据转换为格式字符串str.Format("%10d%16d%16d%16d%16d%18d",pDoc->score0,pDoc->
37、;score1,pDoc->score2,pDoc->score3,pDoc->score4,pDoc->TScore ); pDC->TextOut(0,20,str); /输出成绩3 增加一个菜单项在“编辑”菜单的最下面增加一个菜单项,Caption 为“成绩录入”,菜单ID为ID_SCOREFILLING。4 为新增菜单在文档类定义消息处理函数用ClassWizard在文档类生成菜单命令处理函数OnScorefilling()。5 编辑代码完成下面的功能(1) 创建对话框对象。(2) 运行成绩录入对话框,并把对话框数据成员的值拷贝到文档类成员变量score数
38、组中。(3) 计算总分。(4) 更新视图。具体代码见程序清单6-5所示粗体部分。程序清单6-5:调用模式对话框示例void CExam6_1Doc:OnScorefilling() / TODO: Add your command handler code hereCScoreDlg dlg; /创建对话框对象if(dlg.DoModal()=IDOK )/调用对话框并判断返回值为IDOK /使用对话框对象的成员变量的值修改文档对象的成员变量score0=dlg.m_score1 ; score1=dlg.m_score2 ; score2=dlg.m_score3 ; score3=dlg.
39、m_score4 ; score4=dlg.m_score5 ; for(int i=0;i<5;i+) /计算总分 TScore+=scorei; this->UpdateAllViews(NULL); /更新视图6 加入头文件在Exam6_1Doc.cpp文件的头部的所有的include语句之后加入语句:#include “ScoreDlg.h”7 编辑运行程序执行菜单命令“编辑”->“成绩录入”,弹出“成绩录入”对话框,输入各门课的成绩后,按“确定”退出对话框,应用程序主窗口中显示刚刚输入的各课成绩和总分。6.4.2对话框初始化对话框的初始化工作包括:为控件赋初始值(如
40、:文本框的显示值,单选按钮,复选框的选中状态等),或者设置控件的初始状态(如:控件是否可用、是否显示,下拉框中的选择项等)。为控件赋初始值也就是为对话框对象的数据成员变量赋初值,可在两个位置进行:1 对话框类的构造函数系统一般在对话框类的构造函数中,为数据成员变量赋初值。2 对话框对象创建后对话框对象一般在一个菜单命令处理函数中创建,创建后在对话框调用之前,也就是在DoModal ()函数调用之前,可以通过对象调用数据成员变量为其赋初值。修改程序清单6-5中的OnScorefilling()函数,实现每次调用成绩录入对话框时,以文档对象score数组中现有的成绩为初始值,作为对当前视图的修改。
41、增加的代码见程序清单6-6所示粗体部分。程序清单6-6:模式对话框数据成员赋初值void CExam6_1Doc:OnScorefilling() / TODO: Add your command handler code hereCScoreDlg dlg;/创建对话框对象dlg.m_score1=score0; /初始化对话框数据成员dlg.m_score2=score1;dlg.m_score3=score2;dlg.m_score4=score3;dlg.m_score5=score4;if(dlg.DoModal()=IDOK )score0=dlg.m_score1 ; score
42、1=dlg.m_score2 ; score2=dlg.m_score3 ; score3=dlg.m_score4 ; score4=dlg.m_score5 ; for(int i=0;i<5;i+) TScore+=scorei; this->UpdateAllViews(NULL);修改后再次编译运行程序,可以看到每次对话框打开时,控件的初值都能反应当前视图的显示。程序清单6-6也给出的调用对话框的一个范例,一般遵循四个基本步骤:(1) 创建对话框对象(2) 初始化对话框(3) 调用对话框(4) 确定返回后的处理图6-18中文档对象和对话框对象之间交换数据通常是在第(2)、
43、(4)步编写代码完成的。设置控件的初始状态,可以直接在对话框资源中各控件的属性对话框中进行,更灵活地方式是在对话框类的OnInitDialog()函数中进行控件的设置。默认情况下,OnInitDialog()函数不出现在对话框类中,需要映射对话框类的WM_INITDIALOG窗口消息。下面继续修改应用程序Exam6_1,实现功能:打开成绩录入对话框时,“确定”按钮不可用,当任意一个Edit Box 的内容修改后,“确定”按钮可以使用。实现步骤如下:(1) 打开ClassWizard的Member Variables标签页,增加数据成员变量如表6-2所示。表6-2EX6数据成员变量设置控件ID变
44、量名称分类数据类型IDC_SCORE1m_Score1EditcontrolCEditIDC_SCORE2m_Score2EditcontrolCEditIDC_SCORE3m_Score3EditcontrolCEditIDC_SCORE4m_Score4Edit controlCEditIDC_SCORE5m_Score5EditcontrolCEditIDOKm_OKcontrolCButton(2) 打开ClassWizard的Message Maps标签页,Class name中选择CScoreDlg类,Objects IDs中选择CScoreDlg,Messages中选择WM_IN
45、ITDIALOG窗口消息,单击Add Function按钮。在对话框类CScoreDlg中增加了成员函数OnInitDialog()。(3) 增加代码如程序清单6-7所示粗体部分。使对话框显示时,“确定”按钮灰色显示不能使用。程序清单6-7:初始化对话框函数示例BOOL CScoreDlg:OnInitDialog() CDialog:OnInitDialog();/ TODO: Add extra initialization here m_OK.EnableWindow (false);/禁止“确定”按钮使用,灰色显示return TRUE; / return TRUE unless yo
46、u set the focus to a control / EXCEPTION: OCX Property Pages should return FALSE(4) 打开ClassWizard 的Message Maps标签页,Class name中选择CScoreDlg,Object IDs中选择IDC_SCORE1,Messages中选择EN_CHANGE事件消息,单击Add Function按钮。对话框类CScoreDlg增加对Edit Box进行修改事件的处理函数OnChangeScore1()。(5) 在OnChangeScore1()函数中添加代码如程序清单6-8所示粗体部分,使
47、“确定”按钮可用。程序清单6-8:EditBox响应EN_CHANGE事件处理函数示例void CScoreDlg:OnChangeScore1() / TODO: Add your control notification handler code herem_OK.EnableWindow (true);(6) 重复(4)、(5)两步,为每一个Edit Box控件映射EN_CHANGE事件处理函数,并添加代码,使“确定”按钮可用。(7) 编译运行程序。6.4.3无模式对话框无模式对话框与模式对话框的不同在于,用户打开无模式对话框后,仍然可以与其它用户界面交互。创建无模式对话框的过程与模式对
48、话框基本相同,都包括对话框资源的创建和对话框的创建,但在运行对话框的设计上存在着差异:(1) Visible 属性在对话框的属性对话框More Styles标签页中,有Visible属性的设置,默认情况下,对话框模板是不选择Visible属性。模式对话框不需要设置该属性,而无模式对话框没有选择该属性,窗口创建后,对话框是不显示的,需要调用CWnd:ShowWindow(SW_SHOW)来显示对话框。(2) 创建方式由于无模式对话框对象在程序运行时可以一直存在,所以不能以局部变量的形式创建,只能用new操作符动态创建,并且在调用对话框类的窗口类内声明一个指向对话框类的指针变量,通过指针访问对话框
49、对象。(3) 窗口创建方式无模式对话框的创建与普通窗口的创建是一样的,通过调用CWnd:Create()函数来创建对话框。由于Create()函数不会启动新的消息循环,对话框与应用程序共用一个消息循环,这样对话框就不会屏蔽用户对其它界面对象的访问。Create()函数与DoModal()函数不同之处是:Create()创建了对话框后立即返回,而DoModal()函数要在对话框关闭后返回。(4) 窗口删除函数无模式对话框必须调用CWnd:DestoryWindow()来关闭对话框。模式对话框是调用CDialog:EndDialog()关闭对话框。由于默认的对话框函数OnOK()和OnCancel
50、()都是调用EndDialog()关闭对话框的,所以无模式对话框类要用自己的OnOK()和OnCancel()函数,调用DestoryWindow()来关闭对话框。(5) 清理对话框对象的方式与创建对象的方式new操作相对应,使用delete操作删除一个无模式对话框对象。当屏幕上一个窗口被删除后,框架会自动调用CWnd:PostNcDestroy(),这是一个函数,可以编写程序在这个函数中清理无模式对话框对象。(6) 无模式对话框不能重入因为在无模式对话框打开的情况下,用户有可能再次选择菜单命令执行打开对话框的操作,这是不能再创建一个新的无模式对话框。所以程序在用户选择菜单命令后,应该能够判断
51、是打开一个新的对话框还是激活一个已打开的对话框。通常可以使用对话框对象指针来判断。对话框对象指针始终指向一个对话框对象,当关闭对话框时,设置指针的值为NULL。下面我们在工程Exam6_1中增加一个可以画圆的无模式对话框:1 增加一个对话框模板使用菜单命令Insert->Resource,增加一个新的对话框模板IDD_DIALOG2,如图6-19所示,增加相应控件并设置属性。 表6-3数据成员变量控件ID变量名称分类数据类型IDC_EDIT1m_xvalueintIDC_EDIT2m_yvaluelintIDC_EDIT3m_radiusvalueint图6-19 无模式对话框 2 创建
52、对话框类打开ClassWizard,创建一个新的对话框类CModelessDlg,并按表6-3创建对话框类的数据成员变量。3 定义消息处理函数,重载虚函数使用ClassWizard按表6-4为CModelessDlg创建成员函数。表6-4定义消息处理函数Object IDsMessage备注IDOKBN_CLICKED消息处理函数IDCANCELBN_CLICKED消息处理函数CModelessDlgPostNcDestroy虚拟函数4 定义对话框指针(1) 在CExam6_1View视图类中增加CModelessDlg指针类型的公有成员变量m_pDlg。(2) 在Exam6_1View.h文
53、件的头部增加类的前向声明语句:class CModelessDlg;class CExam6_1Doc;类的向前声明语句的作用:由于在CExam6_1View类中有一个CModelessDlg类的指针和一个返回值为CExam6_1Doc指针的GetDocument()函数,因此必须保证CModelessDlg类和CExam6_1Doc类的声明出现在CExam6_1View之前,否则会产生编译错误。5 增加调用对话框的菜单命令(1) 在“查看”菜单的最下面增加一个菜单项:ID为ID_CIRCLE,Caption为“画圆”。(2) 使用ClassWizard为菜单项在CExam6_1View视图类
54、中映射命令处理函数CExam6_1View:OnCircle()。6 增加对话框类成员变量接收视图指针(1) 在CModelessDlg类增加CExam6_1View类指针类型的公有成员变量m_parent。“设置”对话框打开时,只要单击“画圆”按钮,就可以在主窗口视图上画一个圆,所以在对话框“画圆”按键事件的消息处理函数中要能获得主窗口视图的指针,并创建一个指向主窗口视图的CClientDc对象实现画圆。(2) 在ModelessDlg.h文件的头部预编译命令之前增加类的前向声明语句:class CExam6_1View;7 定义头文件在Exam6_1View.cpp文件的头部所有的include语句之后添加include 语句,将对话框类的头文件包含进来。#include "ModelessDlg.h"在ModelessDialog.cpp文件的头部所有的include语句之后添加include 语句将视图类的头文件包含进来。#include "CExam6_1View.h"8 实现视图类中的成员函数(1) 在构造函数中设置m_pDlg的初值为NULL。(2) 在菜单命令处理函数OnCircle()中判断对话框是否打开,若已打开则激活对话框,否则创建一个新的对话框。代码见程序清单6-9粗体部分所示。程序清单6-9:修改视图类的函数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 作协议合同范本
- 关于管道疏通合同范本
- 别墅弱电智能合同范本
- 产品合同范本模板写
- 农资代理合同范本
- 上海婚宴延期合同范本
- 上海小时工外包合同范本
- 个人续签合同范本
- 农村开发项目合同范本
- 写电子产品合同范本
- 中国食物成分表2020年权威完整改进版
- 【MOOC】影视鉴赏-扬州大学 中国大学慕课MOOC答案
- 危险性较大的分部分项工程清单安全管理措施
- 高压输电线路质量、检查、验收培训课件
- 二年级数学下册重点思维每日一练小纸条
- 混合型颈椎病课件
- 国家安全教育教案分享
- 2024公共数据授权运营实施方案
- 5A护理模式在老年手术患者VTE防控中的应用课件
- 电动车维护与保养操作手册
- 2024年广西高考化学试卷真题(含答案解析)
评论
0/150
提交评论