为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

VC++6.0入门【第六章 创建和使用对话框】

2017-09-18 50页 doc 541KB 27阅读

用户头像

is_153723

暂无简介

举报
VC++6.0入门【第六章 创建和使用对话框】VC++6.0入门【第六章 创建和使用对话框】 第6章 创建和使用对话框 对话框是一种用户界面,几乎每一个Windows程序都使用对话框与用户进行交互。对话框可能是一 个简单的只含有OK按钮的消息框,也可以是一个复杂的数据输入表单。对话框上有一些方便用户输入 的控件,对话框依靠这些控件与用户进行交互,其实质是一个接收消息的窗口。 在本章节我们主要讲述模式对话框和无模式对话框的原理和使用方法,下一章将详细介绍各种控件 的使用。你将学习创建一个对话框,使用对话框模板编辑一个对话框资源,并在程序中调用对话框的方 法。 6.1...
VC++6.0入门【第六章 创建和使用对话框】
VC++6.0入门【第六章 创建和使用对话框】 第6章 创建和使用对话框 对话框是一种用户界面,几乎每一个Windows程序都使用对话框与用户进行交互。对话框可能是一 个简单的只含有OK按钮的消息框,也可以是一个复杂的数据输入表单。对话框上有一些方便用户输入 的控件,对话框依靠这些控件与用户进行交互,其实质是一个接收消息的窗口。 在本章节我们主要讲述模式对话框和无模式对话框的原理和使用方法,下一章将详细介绍各种控件 的使用。你将学习创建一个对话框,使用对话框模板编辑一个对话框资源,并在程序中调用对话框的方 法。 6.1 6.1.1 在创建一个对话框之前,我们先来了解一下对话框是如何工作的,对话框的数据来自三方面:对话 框资源、对话框对象、和一个文档对象: 1 对话框资源是一个用户输入或取得数据的图形界面。这个图形界面是使用Develop Studio的对话框 编辑器在对话框模板上创建的,程序员可以在对话框模板上增加并编辑控件,生成对话框资源。当应用 程序运行时,就可以得到一个对话框。 2 MFC使用CDialog类来描述对话框,它是CWnd类的派生类。在CWnd类的基础上增加了数据交换的功能。当创建一个新的对话框资源后,使用ClassWizard可以创建一个对话框类的派生类。对话框对象实现了对话框和应用程序之间的通信。在应用程序中定义一个对话框对象后,在对话框显示前,可 以通过访问对话框对象的成员变量为一个对话框的控件初始化,在对话框关闭后,可以通过访问对话框 对象的成员变量获得用户的输入数据。 3 MFC使用文档对象描述应用程序处理的数据,用户输入的数据要进一步的处理,通常要先存贮到 文档对象中。例如:一个学生记录处理的应用程序,用户通过一个对话框输入学生记录并贮存到一个文 件中。应用程序的处理顺序是:用户在对话框中输入信息,通过对话框对象得到输入信息,将输入信息 整理到文档对象中,使用序列化函数将文档对象存贮到一个文件中,所以文档对象扮演了一个很重要的 数据交换的角色。 MFC使用以上三者实现用户与应用程序之间数据交换,数据交换流程见图6-1所示,遵循四个步骤。 1 VC++6简明 document xxxxxxx xxxxxxx xxxxxxx Public: xxxxxxx data member 数据交换和验证 2 运行对话框,修改 4 创建对话框模板 文档对象 定义对话框类和 3 公有成员变量 图6-1 对话框基本原理 6.1.2 对话框分为模式对话框和无模式对话框两种。 当一个模式对话框打开了,在其关闭之前,用户不能转向其它用户界面对象,只能与该对话框进行 交互。我们平时接触到的对话框,大多数都是模式对话框,例如,一个执行菜单命令File->Save后,Save 对话框被打开后,用户不能再做其它工作,只能保存完文件或取消保存文件,关闭对话框窗口后,才能 做其它工作。 无模式对话框恰恰相反,当用户打开一个无模式对话框,对话框停留在屏幕上,仍然允许用户与其 它用户界面对象进行交互。无模式对话框最典型的例子是在Word中使用的查找与替换对话框,打开该对话框后,可以交替地进行文档编辑,和查找替换操作。 从第一节的介绍可以看到对话框的任务主要包括对话框资源模板的设计,对话框类的设计和对 话框的运行,绝大多数对话框的创建任务,模式对话框和无模式对话框都是相同的,只有在对话框与应 用程序代码的交互中,也就是对话框的运行中,两者有明显的区别。 6.2 6.2.1 使用AppWizard生成的单文档或多文档应用程序,只有一个默认的About对话框,用于显示应用程序版本信息。需要使用对话框模板创建自己的对话框资源。 Develop Studio提供的对话框模板创建了一个基本界面,包括一个OK(确定)按钮和一个Cancel (取消)按钮等。你可以移动、修改、删除这些控件,或者是增加新的控件到对话框模板,构成应用程 序所需的对话框资源。 创建一个对话框资源到工程的步骤: (1) 使用AppWizard生成一个单文档的MFC应用程序Exam6_1。 (2) 选择Insert->Resource菜单命令。 (3) 在弹出的Insert Resource对话框左边的列表中选择Dialog,单击New按钮。 2 第6章 创建和使用对话框 (4) 在项目工作区中选择ResourceView面板,展开Dialog文件夹,可以看到增加了一个对话框资源 IDD_DIALOG1,如图6-2所示,双击IDD_DIALOG1,在编辑区出现一个对话框模板。 控件工具栏 对话框资源ID 对话框模板 图6-2 Exam6_1对话框设计_新建对话框资源 6.2.2 一个控件是能够放置在一个对话框中,提供应用程序与用户交互的某种功能。例如,Edit Box提供 用户文本输入的场所,一组Radio Button提供用户对某一主的单项选择。MFC将控件设计为对话框窗口的子窗口,控件通过事件通知消息与父窗口联系。 在一个对话框资源中增加控件的操作十分方便,只需从图6-2所示的控件工具栏中选中要增加的控件,再将此控件拖拉至对话框模板中的确定位置上,松开鼠标按键即生成一个控件。调整控件的位置和 大小的操作与Word中对文本框的操作完全一样。 在默认情况下,控件工具栏总是打开的,如果没有打开,可以在Develop Studio工具栏后的空白处,单击鼠标右键,在弹出的快捷菜单中选择Controls,便可打开控件工具栏。 图6-3中列出了VC++6.0中支持的标准控件名称,我们可以很方便地从控件工具栏中生成新 的控件,但每一种控件都具有不同的特性,需要学习和掌握。 Selection Tool Picture Static Text Edit Control Group Box Button Check Box Radio Button Combo Box List Box Horizontal Scroll Bar Vertical Scroll Bar Spin Progress Slider Hot Key List Control Tree Control Tab Control Animate Rich Edit Date Time Picker 3 Month Calender IP Address Custom Control Extended Combo Box VC++6简明教程 图6-3 标准控件 下面我们试着设计一个可以输入5门功课成绩的输入窗口,在上一节生成的对话框资源 IDD_DIALOG1中做以下操作,得到如图6-4所示的对话框: (1) 调整对话框模板窗口大小,将OK和Cancel按钮移到窗口的底部。 (2) 控件工具栏中选中Static Text(静态文本)控件,拖到对话框模板中。 (3) 通过复制和粘贴操作,生成其它四个Static Text控件。 (4) 控件工具栏中选中Edit Box控件(编辑框),拖到对话框模板中。 (5) 通过复制和粘贴操作,生成其它四个Edit Box控件 图6-4 EX6对话框设计_增加控件 6.2.3 一个控件相关的属性设置决定了一个控件可操作行为和显示。例如,控件的ID是控件的一个重要属性,MFC内部是以控件ID来标识一个控件,当消息产生后,是哪一个控件需要进行处理,MFC 内部使用的是控件ID。 属性的设置是在与每个控件相对应的属性对话框中进行的,单击鼠标右键,在弹出的快捷菜单中选 择Properties,打开属性对话框。每一种控件的属性对话框都有所不同,与其特性相关,在下一章我们将 详细介绍一些常用控件的属性含义。 对上一节的对话框IDD_DIALOG1中的控件作属性设置: (1) 鼠标选中第一个Static Text对象,单击鼠标右键,在弹出的快捷菜单中选择Properties,弹出属 性对话框,如图6-5所示。 4 第6章 创建和使用对话框 图6-5 属性对话框设置 (2) 修改Caption右边的文本框,输入“高等数学”,单击关闭按钮,关闭属性对话框。 (3) 重复步骤(1)(2),将其它四个Static控件的Caption改为“大学物理”,“大学英语”,“哲学”和 “计算机基础”。 (4) 同样的操作打开5 个Edit Box控件的属性对话框,修改ID为IDC_SCORE1、IDC_SCORE2、 IDC_SCORE3、IDC_SCORE4、IDC_SCORE5。 (5) 打开按钮OK的属性对话框,修改Caption为“确定”。 (6) 打开按钮Cancel的属性对话框,修改Caption为“取消”。 操作完毕,对话框如图6-6所示。 图6-6 EX6对话框设计_设置属性 同样,对话框的属性设计也是在对话框的属性对话框中设置,在对话框任意空白处单击鼠标右键, 在弹出的快捷菜单中选择Properties,如图6-7所示。在Caption中填写“成绩录入”,将成为对话框的标题,单击Font会弹出字体对话框,能设置对话框中显示的字体格式。其它的几个标签页还提供了选项, 可以修改对话框窗口的显示样式,可以自己试一试。 图6-7 对话框属性设置 5 VC++6简明教程 6.2.4 当选择了一个对话框资源进入对话框编辑器时,Develop Studio的菜单栏上会增加一个菜单Layout, 如图6-8所示。Layout 菜单提供了在对话框模板中合理布置控件的功能菜单项。 Align提供了控件的六种对齐方式:左对齐、右对齐、上对齐、下 对齐、水平居中、垂直居中。 Space Evenly提供了两种等间距方式:垂直方向等间距、水平方 向等间距。 Make Same Size提供了三种等尺寸方式:宽相等、高相等、两者 都相等。 Arrange Button提供了两种组织按键的方式:底部排列、右边排 列。 Center in Dialog提供了两种居中方式:水平居中、垂直居中。 Flip用于水平反方向显示控件及窗口标题。 Size to Content命令根据内容决定控件的大小,例如,按钮的大小 由按钮上的显示文本决定。 图6-8 Layout下拉菜单 通过上面几个菜单项的操作能够很方便地齐整控件的摆放位置。现在我们可以整理一下 IDD_DIALOG1中 摆放凌乱的控件: (1) 确定第一个和最后一个Static Text控件的位置,同时选中5个Static Text控件,执行菜单命令 Layout->Make Same Size-width (2) 执行菜单命令Layout->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-9 EX6对话框设计_整理控件 在Windows环境中通常提供两种操作方法,鼠标操作方式和键盘操作方式,使用鼠标可以直接点击 控件进行访问,使用键盘访问控件需要通过Tab键顺次找到某个控件。Tab Order规定了使用Tab键访问 6 第6章 创建和使用对话框 控件的顺序,一般Tab Order是控件生成的顺序,执行菜单命令Layout->Tab Order可以显示并修改Tab Order,对IDD_DIALOG1执行菜单命令Tab Order 如图6-10所示。 图6-10 显示Tab Order 改变Tab Order的方法既简单又直观,执行了Tab Order命令出现了顺序号之后,按你所想要的访问 顺序依次点击每一个控件,完成后,点击空白处就可以了。读者可以试练习将上图的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-11 Exam6_1对话框设计_测试对话框 7 VC++6简明教程 6.3 一个对话框资源要加入到一个窗口应用程序中,首先要为它创建一个对话框类,是CDialog类的派生类。应用程序运行时,窗口操作系统使用对话框类为对话框在内存开辟空间。 在Win32 API类型的窗口应用程序中,都是直接通过控件ID来访问对话框上的控件的,而MFC提供了连接变量来标识控件,连接变量是对话框的成员变量,同时对话框类有一套交换和验证数据的方式。 6.3.1 创建对话框类的步骤如下: 1. 保存已创建好的对话框模板。 2. 确保新的对话框资源在对话框编辑器中打开状态下,打开ClassWizard窗口。 打开ClassWizard的方式有3种: (1) 窗口菜单命令View->ClassWizard (2) 快捷菜单命令ClassWizard (3) 快捷键:Ctrl+w 3. 在弹出的Adding a Class对话框中,如图6-12所示,选择Create a new class单选钮,单击OK按钮。 图6-12 “增加类”对话框 4. 在随后弹出的New Class对话框中,如图6-13所示,只需填写类的名称:CScoreDlg,单击OK按钮。 关闭ClassWizard,对话框类的创建就完成了。 8 第6章 创建和使用对话框 填写类名 图6-13 填写新类名称 在Workspace窗口的ClassView面板中,可以看到增加了一个新的类CScoreDlg,选择FileView面板,在Header Files和Source Files文件夹中,可以看到该类的头文件和实现文件,文件名是类名除去开 头的类标志“C”。 图6-14 新增对话框类及文件 在创建新类的时候,要注意新类的对话框ID一定要与对话框资源ID一致,这些ID告诉对话框类,在对话框窗口创建前,哪一个对话框资源要被检查,初始化控件并显示。尤其在创建好对话框后,不能 随意地改动对话框资源ID和删除对话框资源。 6.3.2 创建好一个对话框类后,可以增加类的成员变量来操作对话框上的控件。出于不同的操作目的, MFC提供了两种类型的成员变量,如表6-1所示。 表6-1 对话框类的成员变量类型 9 VC++6简明教程 Values 值类型的成员变量。用于控件的值控制,可以有多种数据类 型,由所连接的控件类型决定。例如,Edit Box控件可以有 CString型或int型。Radio Button可以是int型。 Controls 控件类型的成员变量,实质是该控件类的一个对象。创建了 一个控件对象,就可以通过该对象使用控件类的方法对控件 进行操作,例如,在程序运行时为Combo Box加入选择项, 设置控件是否有效或可见等。 例如,创建了CScoreDlg类后,需要为对话框中每一个Edit Box控件创建一个值类型的成员变量, 来取得用户在EditBox输入的数据,增加控件成员变量的步骤如下: (1) 打开ClassWizard窗口,选择Member Variables标签页,Class name下拉列表中选择CScoreDlg类。这时,对话框中可以创建成员变量的控件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) 如果增加成员变量时操作有误,例如变量名错误,变量类型错误,选择该成员变量,单击Delete Variable按钮删除该变量,再重新创建。 创建好的成员变量如图6-16所示。 10 第6章 创建和使用对话框 变量类型 变量名称 图6-16 成员变量列表 创建好成员变量后,我们来检查一下ClassWizard作了哪些工作: (1) 展开项目工作区的ClassView面板中的CScoreDlg类,在树上出现了刚创建的成员变量。 (2) 双击CScoreDlg的类名,进入该类的头文件ScoreDlg.h,可以找到对话框类定义的代码,如程 序清单6-1中所示。 class CScoreDlg : public CDialog { // Construction public: CScoreDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data //{{AFX_DATA(CScoreDlg) enum { IDD = IDD_DIALOG1 }; int m_score1; int m_scroe2; int m_score4; int m_score5; int m_score3; //}}AFX_DATA ... ... } 其中呈灰色显示的,在宏“{{AFX_DATA(CScoreDlg)......}}AFX_DATA”之间定义的是用ClassWizard 创建的成员变量。需要注意的是,所有ClassWizard 产生的灰色显示的代码,不要在文件中直接修改, 而应在ClassWizard工具中进行修改,不然容易引起错误。 11 VC++6简明教程 (3) 打开该类的构造函数,可以看到ClassWizard自动加入了成员变量的初始化代码,如程序清单 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_INIT } 6.3.3 对话框的值类型的成员变量存储了与控件相对应的数据,对框话打开时,用户可以修改控件的数据, 有时需要应用程序对用户的输入进行及时反馈,这时数据成员变量需要与控件交换数据,以完成输入输 出功能。对于这种功能MFC是靠CDataExchange类提供的数据交换(DDX:Dialog Data Exchange)机 制来完成的,该类提供了数据有效机制(DDV:Dialog Data Validation) 当在对话框类中增加一个数据成员变量,有时需要规定数据的有效性校验规则,例如,成绩录入对 话框中,应设置各门课的成绩应在0-100的范围内。在应用程序运行的时候,当用户输入数据拷贝到 数据成员变量时,DDV机制被调用,如果有效性校验失败,即用户输入一个不合理的数据时,将出现 一个错误信息对话框,并返回到出现错误输入的控件。 有效性校验的设置也是在ClassWizard中完成的。我们再回到成绩录入的Member Variables标签页, 选择表示成绩输入框的m_score1,在标签页的下方会出最大值和最小值的输入框,如图6-17所示,填 入0和100。如果一个CString型的数据成员变量对应的通常是字符串的长度。 12 第6章 创建和使用对话框 图6-17 添加数据成员变量的有效范围 对话框类调用DoDataExchange函数来实现DDV和DDX,对应图6-17的CScoreDlg类的 DoDataExchange代码如程序清单6-3所示。 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_SCORE3, 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, m_score1, 0, 100); // //}}AFX_DATA_MAP } pDX指针指向一个CDataExchange对象,DDX函数来完成控件和数据成员变量之间的数据交换, DDV完成数据有效性检查。DDX和DDV适用于文本框、复选框、单选按钮、列表框和组合框。 当程序需要交换数据时,不需要编写代码调用DoDataExchange函数,而应该调用CWnd::UpdateData() 函数,UpdateData()函数内部调用了DoDataExchange函数。UpdateData()函数只有一个BOOL类型的参 13 VC++6简明教程 数,决定数据交换的方向: (1) UpdateData(false) 将对话框对象的数据成员变量的值拷贝到对话框中的控件。 (2) UpdateData(true) 将对话框中控件的值拷贝到对话框对象的数据成员变量。 你可以随时在需要进行数据交换时调用相应的UpdateData()函数,例如,在成绩录入的对话框中增 加两个控件,一个是Edit Box用于显示总分,另一个是Button用于计算总分,则在Button的Click事件处理函数中,就需要先调用UpdateData(true)获取用户录入的5门功课的成绩,在计算总分后,调用 UpdateData(false),将总分显示在Edit Box中。 在默认的CDialog::OnInitDialog()函数中调用了UpdateData(false),这样在对话框创建的时候,数据 成员的初值就会反映到相应的控件上。若用户单击OK(确定)按钮关闭对话框,CDialog::OnOK()函数会调用UpdateData(true),将控件中的数据传给数据成员变量,如图6-18所示。图中说明了对话框的控件与对话框对象之间的数据交换是由框架自动完成的,而对话框对象与文档对象之间的数据交换则需要 编写代码。 DDX and DDV document Public: xxxxxxx data xxxxxxx xxxxxxx member xxxxxxx DDX 框架处理对话框和对象之间的编写代码在文档对象和对话框对象 数据交换和验证 之间交换数据 图6-18 数据交换和验证在应用程序中的实现 6.4 创建好一个对话框资源和对话框类,要在应用程序中运行对话框,通常要在一个菜单命令下打开一 个对话框。所以,首先要定义一个菜单项和相应的菜单命令处理函数,在函数中编写代码运行对话框。 运行模式对话框和无模式对话框有所不同,下面结合实例详细介绍两种对话框运行的方法。 6.4.1 在应用程序中使用得更多的还是模式对话框,模式对话框的运行分两个步骤: (1) 创建一个对话框对象 (2) 调用CDialog::DoModal()函数打开对话框 DoModal()函数负责模式对话框的创建和撤消。在创建对话框时,DoModal()的任务包括:装载对话框资源、调用OnInitDialog()初始化对话框和将对话框显示在屏幕上。完成对话框的创建后,DoModal()启动一个消息循环,以响应用户的输入。这时,用户只能与对话框进行交互,其它用户界面对象收不到 输入信息,只有终止模式对话框后才能进行其它工作。 若用户在对话框内单击了系统默认的OK(确定)按钮,则CDialog::OnOK()函数将被调用,OnOK()首先调用UpdateData(true)函数,将数据从对话框中的控件拷贝到数据成员变量,再调用 14 第6章 创建和使用对话框 CDialog::EndDialog()关闭对话框,并返回值IDOK。 若用户在对话框单击了系统默认的Cancel(取消)按钮,则CDialog::OnCancel()函数将被调用,该函数只调用CDialog::EndDialog()关闭对话框,并返回值IDCANCEL。程序可以根据返回值是IDOK还 是IDCANCEL来判断用户关闭对话框按的哪一个键。 下面我们将运行成绩录入对话框,当按“确定”按钮返回时,将其显示在主窗口视图上。为此,要 定义对应的文档对象。步骤如下: 1 int型成员变量数组score[5],存放5门课程成绩;int型成员变量TScore,用来存放总分。 在构造函数中设置数组score和TScore的初值都为0。 2 OnDraw 具体代码见程序清单6-4所示粗体部分。 void CExam6_1View::OnDraw(CDC* pDC) { CExam6_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->TextOut(0,0," ") ;// CString str;//int str.Format("%10d%16d%16d%16d%16d%18d",pDoc->score[0],pDoc->score[1], pDoc->score[2],pDoc->score[3],pDoc->score[4],pDoc->TScore ); pDC->TextOut(0,20,str); // } 3 在“编辑”菜单的最下面增加一个菜单项,Caption 为“成绩录入”,菜单ID为ID_SCOREFILLING。 4 用ClassWizard在文档类生成菜单命令处理函数OnScorefilling()。 5 (1) 创建对话框对象。 (2) 运行成绩录入对话框,并把对话框数据成员的值拷贝到文档类成员变量score数组中。 (3) 计算总分。 (4) 更新视图。 具体代码见程序清单6-5所示粗体部分。 void CExam6_1Doc::OnScorefilling() { // TODO: Add your command handler code here CScoreDlg dlg; // if(dlg.DoModal()==IDOK )//IDOK { // 15 VC++6简明教程 score[0]=dlg.m_score1 ; score[1]=dlg.m_score2 ; score[2]=dlg.m_score3 ; score[3]=dlg.m_score4 ; score[4]=dlg.m_score5 ; for(int i=0;i<5;i++) // TScore+=score[i]; this->UpdateAllViews(NULL); // } } 6 在Exam6_1Doc.cpp文件的头部的所有的include语句之后加入语句:#include “ScoreDlg.h” 7 执行菜单命令“编辑”->“成绩录入”,弹出“成绩录入”对话框,输入各门课的成绩后,按“确 定”退出对话框,应用程序主窗口中显示刚刚输入的各课成绩和总分。 6.4.2 对话框的初始化工作包括:为控件赋初始值(如:文本框的显示值,单选按钮,复选框的选中状态 等),或者设置控件的初始状态(如:控件是否可用、是否显示,下拉框中的选择项等)。 为控件赋初始值也就是为对话框对象的数据成员变量赋初值,可在两个位置进行: 1 系统一般在对话框类的构造函数中,为数据成员变量赋初值。 2 对话框对象一般在一个菜单命令处理函数中创建,创建后在对话框调用之前,也就是在DoModal () 函数调用之前,可以通过对象调用数据成员变量为其赋初值。 修改程序清单6-5中的OnScorefilling()函数,实现每次调用成绩录入对话框时,以文档对象score 数组中现有的成绩为初始值,作为对当前视图的修改。增加的代码见程序清单6-6所示粗体部分。 void CExam6_1Doc::OnScorefilling() { // TODO: Add your command handler code here CScoreDlg dlg; //创建对话框对象 dlg.m_score1=score[0]; // dlg.m_score2=score[1]; dlg.m_score3=score[2]; dlg.m_score4=score[3]; dlg.m_score5=score[4]; if(dlg.DoModal()==IDOK ) {score[0]=dlg.m_score1 ; score[1]=dlg.m_score2 ; 16 第6章 创建和使用对话框 score[2]=dlg.m_score3 ; score[3]=dlg.m_score4 ; score[4]=dlg.m_score5 ; for(int i=0;i<5;i++) TScore+=score[i]; this->UpdateAllViews(NULL); } } 修改后再次编译运行程序,可以看到每次对话框打开时,控件的初值都能反应当前视图的显示。程 序清单6-6也给出的调用对话框的一个范例,一般遵循四个基本步骤: (1) 创建对话框对象 (2) 初始化对话框 (3) 调用对话框 (4) 确定返回后的处理 图6-18中文档对象和对话框对象之间交换数据通常是在第(2)、(4)步编写代码完成的。 设置控件的初始状态,可以直接在对话框资源中各控件的属性对话框中进行,更灵活地方式是在对 话框类的OnInitDialog()函数中进行控件的设置。默认情况下,OnInitDialog()函数不出现在对话框类中, 需要映射对话框类的WM_INITDIALOG窗口消息。 下面继续修改应用程序Exam6_1,实现功能:打开成绩录入对话框时,“确定”按钮不可用,当任 意一个Edit Box 的内容修改后,“确定”按钮可以使用。实现步骤如下: (1) 打开ClassWizard的Member Variables标签页,增加数据成员变量如表6-2所示。 表6-2 EX6数据成员变量设置 IDC_SCORE1 m_Score1Edit control CEdit IDC_SCORE2 m_Score2Edit control CEdit IDC_SCORE3 m_Score3Edit control CEdit IDC_SCORE4 m_Score4Edit control CEdit IDC_SCORE5 m_Score5Edit control CEdit IDOK m_OK control CButton (2) 打开ClassWizard的Message Maps标签页,Class name中选择CScoreDlg类,Objects IDs中选 择CScoreDlg,Messages中选择WM_INITDIALOG窗口消息,单击Add Function按钮。在对话 框类CScoreDlg中增加了成员函数OnInitDialog()。 (3) 增加代码如程序清单6-7所示粗体部分。使对话框显示时,“确定”按钮灰色显示不能使用。 BOOL CScoreDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: Add extra initialization here m_OK.EnableWindow (false);// 17 VC++6简明教程 return TRUE; // return TRUE unless you 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所示粗体部分,使“确定”按钮可用。 void CScoreDlg::OnChangeScore1() { // TODO: Add your control notification handler code here m_OK.EnableWindow (true); } (6) 重复(4)、(5)两步,为每一个Edit Box控件映射EN_CHANGE事件处理函数,并添加代码,使 “确定”按钮可用。 (7) 编译运行程序。 6.4.3 无模式对话框与模式对话框的不同在于,用户打开无模式对话框后,仍然可以与其它用户界面交互。 创建无模式对话框的过程与模式对话框基本相同,都包括对话框资源的创建和对话框的创建,但在运行 对话框的设计上存在着差异: (1) Visible 在对话框的属性对话框More Styles标签页中,有Visible属性的设置,默认情况下,对话框模板是 不选择Visible属性。模式对话框不需要设置该属性,而无模式对话框没有选择该属性,窗口创建后, 对话框是不显示的,需要调用CWnd::ShowWindow(SW_SHOW)来显示对话框。 (2) 由于无模式对话框对象在程序运行时可以一直存在,所以不能以局部变量的形式创建,只能用new操作符动态创建,并且在调用对话框类的窗口类内声明一个指向对话框类的指针变量,通过指针访问对 话框对象。 (3) 无模式对话框的创建与普通窗口的创建是一样的,通过调用CWnd::Create()函数来创建对话框。由于Create()函数不会启动新的消息循环,对话框与应用程序共用一个消息循环,这样对话框就不会屏蔽 用户对其它界面对象的访问。Create()函数与DoModal()函数不同之处是:Create()创建了对话框后立即返回,而DoModal()函数要在对话框关闭后返回。 (4) 无模式对话框必须调用CWnd::DestoryWindow()来关闭对话框。模式对话框是调用 CDialog::EndDialog()关闭对话框。由于默认的对话框函数OnOK()和OnCancel()都是调用EndDialog()关 闭对话框的,所以无模式对话框类要用自己的OnOK()和OnCancel()函数,调用DestoryWindow()来关闭对话框。 (5) 18 第6章 创建和使用对话框 与创建对象的方式new操作相对应,使用delete操作删除一个无模式对话框对象。当屏幕上一个窗 口被删除后,框架会自动调用CWnd::PostNcDestroy(),这是一个函数,可以编写程序在这个函数中清理 无模式对话框对象。 (6) 因为在无模式对话框打开的情况下,用户有可能再次选择菜单命令执行打开对话框的操作,这是不 能再创建一个新的无模式对话框。所以程序在用户选择菜单命令后,应该能够判断是打开一个新的对话 框还是激活一个已打开的对话框。通常可以使用对话框对象指针来判断。对话框对象指针始终指向一个 对话框对象,当关闭对话框时,设置指针的值为NULL。 下面我们在工程Exam6_1中增加一个可以画圆的无模式对话框: 1 使用菜单命令Insert->Resource,增加一个新的对话框模板IDD_DIALOG2,如图6-19所示,增加相应控件并设置属性。 表6-3 数据成员变量 IDC_EDIT1 m_x value int IDC_EDIT2 m_y valuel int IDC_EDIT3 m_radius value int 图6-19 无模式对话框 2 打开ClassWizard,创建一个新的对话框类CModelessDlg,并按表6-3创建对话框类的数据成员变量。 3 使用ClassWizard按表6-4为CModelessDlg创建成员函数。 表6-4 定义消息处理函数 Object IDs Message IDOK BN_CLICKED 消息处理函数 IDCANCEL BN_CLICKED 消息处理函数 CModelessDlg PostNcDestroy 虚拟函数 4 (1) 在CExam6_1View视图类中增加CModelessDlg指针类型的公有成员变量m_pDlg。 (2) 在Exam6_1View.h文件的头部增加类的前向声明语句: 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视图类中映射命令处理函数 CExam6_1View::OnCircle()。 19 VC++6简明教程 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粗体部分所示。 CExam6_1View::CExam6_1View() { // TODO: add construction code here m_pDlg=NULL; } void CExam6_1View::OnCircle() { // TODO: Add your command handler code here if (m_pDlg) m_pDlg->SetActiveWindow();// else {// m_pDlg=new CModelessDlg(this); // m_pDlg->m_parent=this; // m_pDlg->Create (IDD_DIALOG2,this); // m_pDlg->ShowWindow(SW_SHOW);// } } 9 (1) OnOK()函数对应“ 画圆”按钮的按键事件,实现画圆。 (2) OnCancel()函数对应“取消”按钮的按键事件,实现删除对话框窗口。 20 第6章 创建和使用对话框 (3) PostNcDestroy()是重载的虚函数,当删除对话框窗口时由框架自动调用,清理对话框对象。 代码见程序清单6-10所示。 void CModelessDlg::OnOK() { // TODO: Add extra validation here UpdateData(true);// CClientDC dc(m_parent);//CClientDC // dc.Ellipse(m_x-m_radius,m_y-m_radius,m_x+m_radius,m_y+m_radius) ; //CDialog::OnOK() //CDialog::OnOK(); } void CModelessDlg::OnCancel() { // TODO: Add extra cleanup here // m_parent->m_pDlg =NULL; DestroyWindow(); //CDialog:: OnCancel() //CDialog::OnCancel(); } void CModelessDlg::PostNcDestroy() { // TODO: Add your specialized code here and/or call the base class delete this;// CDialog::PostNcDestroy(); } 10 执行菜单命令“查看”->“画圆”,弹出“设置”对话框,输入坐标和半径,单击“画图”按钮, 主窗口视图出现一个圆,可以反复执行在不同的地方画不同的圆,直至单击“取消”按钮关闭对话框。 在对话框打开的状态下,可以转向其它窗口操作。运行效果如图6-20所示。 21 VC++6简明教程 图6-20 无模式对话框运行效果 6.5 6.5.1 MFC的通用框库(CommDlg.dll)包含一套应用程序通用的对话框供程序员方便的加入到一个应用 程序,如表6-5所示。只有查找和替换对话框是无模式对话框,其它对话框都是模式对话框。 表6-5 通用对话框 CColorDialg 颜色对话框 模式对话框 CFileDialog 文件对话框 模式对话框 CFindReplaceDialog 查找/替换对话框 无模式对话框 CFontDialog 字体对话框 模式对话框 CPrintDialog 打印对话框 模式对话框 CPageSetupDialog 页面设置对话框 模式对话框 6.5.2 从表6-5中可以知道,每一种通用对话框都对应一个类。通用对话框类已定义了支持通用对话框功 能的大量的功能函数和属性。我们只需要做很少的工作就能使用通用对话框了。使用一个通用对话框通 常遵循下面3个步骤: (1) 创建一个通用对话框类的对象。 (2) 修改相应的数据成员,或使用方法或函数查询或设置属性值。 (3) 如果是模式对话框,调用DoModa()l函数打开对话框。 由于每一种对话框执行的任务不同,该类的方法和属性是不同的,它们的使用上有所不同,详细细 节请查阅MSDN。 22 第6章 创建和使用对话框 下一节我们将以颜色对话框为例,说明通用对话框的使用。 6.5.3 修改应用程序Exam6_1,在无模式对话框中增加功能,可以使用颜色对话框设置圆的填充颜色的功 能。实现步骤如下: (1) 为CModelessDlg类增加COLORREF类型的公有成员变量m_color,用以记录圆圈的填充色。 (2) 在CModelessDlg类构造函数中填写语句,初始化圆的填充色为白色。语句为: COLORREF=RGB(256,256,256); (3) 修改对话框资源IDD_DIALOG2,增加一个命令按钮,Caption为“Color”,ID为ID_COLOR。 (4) 为Color按钮在CModelessDlg类映射EN_CLICKED事件的消息处理函数OnColor()。 (5) 为OnColor()函数添加代码实现颜色对话框的调用。代码见程序清单6-11粗体部分。 void CModelessDlg::OnColor() { // TODO: Add your control notification handler code here CColorDialog dlg;// if(dlg.DoModal()==IDOK )// m_color=dlg.GetColor();//GetColor } (6) 修改OnOK()函数,设置画刷颜色实现填充。修改代码见程序清单6-12粗体部分。 void CModelessDlg::OnOK() { // TODO: Add extra validation here UpdateData(true);// 获取输入值 CClientDC dc(m_parent);//创建指向主窗口视图的CClientDC对象。 CBrush bs; bs. CreateSolidBrush(m_color); dc.SelectObject(&bs); //根据输入的位置和半径画圆 dc.Ellipse(m_x-m_radius,m_y-m_radius,m_x+m_radius,m_y+m_radius); //CDialog::OnOK(); } (7) 编辑运行程序,执行效果如下。打开“设置”对话框后,按“Color”按钮可以打开Windows 颜色对话框选择颜色,设置填充颜色。 23 VC++6简明教程 图6-21 使用颜色对话框 1 本程序实现的主要功能:程序启动时,在窗口中央显示字符串信息,当在窗口中双击鼠标左键时, 以双击处为中心画一个图形(圆形或正方形),当进行窗口最大化或最小化操作时,显示的内容仍然保 留在窗口中。菜单命令“设置”弹出对话框可以修改窗口中央显示的文本,以及图形的形状。运行效果 如图6-22所示。 图6-22 程序运行图 1 AppWizardEx6_1 工程的资源语言使用中文,取消对打印和打印预览的支持。 2 6-6Public 添加变量可以在项目工作区的ClassView面板中,直接选取Ex6_1Doc类的快捷命令Add member Variable逐个添加,可以直接在Ex6_1Doc.h文件中的CEx6_1Doc类的定义中适当位置中直接书写变量 24 第6章 创建和使用对话框 的定义语句,如程序清单6-13所示。 表6-6 文档类的成员变量设置 m_iPoint int -1 记录鼠标双击次数 m_PointArray[100] CPoint 记录鼠标双击坐标 m_type int 0 图形的形状0-方,1-圆 m_MouseMsg CString 请双击鼠标左键 显示的文本 class CEx6_1Doc : public CDocument { protected: // create from serialization only CEx6_1Doc(); DECLARE_DYNCREATE(CEx6_1Doc) // Attributes属性定义 public: // Operations方法定义 public: // Overrides重载虚拟函数定义 // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CEx6_1Doc) public: virtual BOOL OnNewDocument(); virtual void Serialize(CArchive& ar); //}}AFX_VIRTUAL // Implementation 文档类的实现-成员变量的添加位置 public: int m_iPoint; CPoint m_PointArray[100]; int m_type; CString m_MouseMsg; virtual ~CEx6_1Doc(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected: // Generated message map functions 消息处理函数定义 protected: //{{AFX_MSG(CEx6_1Doc) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() 25 VC++6简明教程 }; 3 在文档类的构造函数中为添加的变量按表6-6指定初始值。代码如程序清单6-14所示。 CEx6_1Doc::CEx6_1Doc() { // TODO: add one-time construction code here m_iPoint=-1; m_type=0; m_MouseMsg=""; } 4 在视图类的OnDraw()函数中添加代码,将文档类成员变量m_MouseMsg的内容显示在程序窗口的中央。 在视图类访问文档类的成员变量只需调用GetDocument()函数获得指向文档类的指针,再通过该指针访问文档类的成员变量。默认情况下在OnDraw()函数已有文档类指针的定义和GetDocumnt()函数 的调用语句,可以直接使用pDoc访问m_MouseMsg。要在视图的中央显示字符串,首先求得视图的中 央位置坐标,再把视图的原点调整到视图的中央位置,具体实现见程序清单6-15粗体部分。 void CEx6_1View::OnDraw(CDC* pDC) { CEx6_1Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CRect Rect; GetClientRect (Rect); //取得客户区 // 以客户区中心设置坐标原点 pDC->SetViewportOrg (Rect.Width ()/2,Rect.Height ()/2); pDC->TextOut(-60,-10,pDoc->m_MouseMsg );//输出字符串 } 5 使用ClassWizard在视图类添加鼠标左键双击的消息WM_LBUTTONDBLCLK映射函数 OnLButtonDblClk()。 6 OnLButtonDblClk() (1) 文档类变量m_iPoint增1。 (2) 在数组m_PointArray中记录当前鼠标双击的坐标。 (3) 更新视图。 实现代码见程序清单6-16所示粗体部分。 26 第6章 创建和使用对话框 void CEx6_1View::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default CEx6_1Doc* pDoc = GetDocument();//获取文档指针 pDoc->m_iPoint++;//文档类变量m_iPoint增1 //在数组m_PointArray中记录当前鼠标双击的坐标 pDoc->m_PointArray[pDoc->m_iPoint]=point; this->Invalidate(); //更新视图 CView::OnLButtonDblClk(nFlags, point); } 7 OnDraw 在m_PointArray数组中记录的坐标位置上画一图形,如果文档类成员变量m_type的值为0,画长 为20个像素的正方形,为1时,画半径为10个像素的圆形,添加的代码见程序清单6-17。 void CEx6_1View::OnDraw(CDC* pDC) { pDC->SetViewportOrg(0,0);//恢复坐标原点位置 CPoint org; int i; if(pDoc->m_type) //m_type=1时画圆 { for(i=0;i<=pDoc->m_iPoint;i++ ) { org=pDoc->m_PointArray[i];//取第i个图形的输出坐标 pDC->Ellipse(org.x-10,org.y-10,org.x+10,org.y+10);//画圆 } } else // m_type=0时画矩形 { for(i=0;i<=pDoc->m_iPoint;i++ ) { org=pDoc->m_PointArray[i]; pDC->Rectangle(org.x-10,org.y-10,org.x+10,org.y+10); } } } 8 ” (1) 使用菜单命令Insert->Resource添加一个对话框IDD_DIALOG1,打开对话框属性对话框,设置 Caption为“设置”。 (2) 按图6-23添加控件。增加两个Group Box控件,设置Caption为“形状”和“显示字符串”。 (3) 在“形状”Group Box上添加两个Radio Button控件,设置Caption为“方形”和“圆形”,ID 见表6-7。并选中“方形”按钮的“Group”属性。 (4) 在“显示字符串”Group Box上添加一个Edit Box控件,ID为ID_EDIT。将IDOK和IDCANCEL 两个按钮的Caption设置为“确定”和“取消”。 27 VC++6简明教程 图6-23“设置”对话框运行结果 表6-7对话框控件及连接属性 Radio Button ID_RECT m_type_edit int Radio Button ID_CIRCLE Edit Box ID_EDIT m_Msg CString Button IDOK Botton IDCANCLE 9 打开ClassWizard,为对话框创建一个新类CUpdateDlg,并按表6-7为CUpdateDlg类添加连接变量m_type_edit和m_Msg,并设置m_Msg的最大长度为50,如图6-24所示。 图6-24 创建连接变量 10 在编辑菜单下增加分隔线和菜单项“设置”,ID为ID_SETUP。用于调用“设置”对话框。 11 在文档类中为菜单项“设置” 增加COMMAND消息映射,函数为OnSetup()。 28 第6章 创建和使用对话框 12 OnSetup (1) 创建一个CUpdateDlg对话框类的对象。 (2) 用文档类成员变量m_MouseMsg和m_type的值初始化对话框对象。 (3) 调用对话框,并按用户输入来修改文档类成员变量m_MouseMsg和m_type的值。 (4) 更新视图。 代码见程序清单6-18所示粗体部分。 void CEx6_1Doc::OnSetup() { // TODO: Add your command handler code here CUpdateDlg dlg; //创建一个CUpdateDlg对话框类的对象 //初始化对话框对象 dlg.m_Msg=m_MouseMsg; dlg.m_type_edit=m_type; //调用对话框 if(dlg.DoModal()==IDOK ) {//按用户输入来修改文档类成员变量 m_MouseMsg=dlg.m_Msg ; m_type=dlg.m_type_edit; this->UpdateAllViews(NULL); //更新视图 } } 13 Ex6_1Doc.cppincludeUpdateDlg.h #include “UpdateDlg.h” 2 创建并使用一个带有一个编辑控件、OK按钮、CANCEL按钮的无模式对话框。操作要求如下: (1) 在视图窗口内部按下鼠标左键时打开对话框,但是只能打开一个对话框。 (2) 在视图窗口内部按下鼠标右键时关闭对话框。 (3) 对话框打开时,单击OK按钮和CANCEL按钮时都会发出一个自定义消息WM_SENDMSG。 (4) 该消息处理函数能判断:当单击OK按钮时,在主窗口视图中央输出编辑控件中的内容,并关 闭对话框;当单击CANCEL按钮时,仅仅关闭对话框窗口。 1 AppWizardEx6_2 工程的资源语言使用中文,取消对打印和打印预览的支持。 2 执行菜单命令Insert->Resource创建一个新的对话框,改变对话框的标题为Send Message。添加一 个Edit Box控件和Group Box控件。改变Group Box的标题为Message。其它都接受默认设置,调整控 件位置如图6-25所示。 29 VC++6简明教程 图6-25 send message对话框 3 ClassWizardCEx6_2Dlg 打开ClassWizard窗口,为对话框创建一个新类CEx6_2Dlg。 4 ClassWizardCEx6_2Dlg 打开ClassWizard的标签页Member Variables,为控件IDC_EDIT1增加Value类CString型连接变量m_strEdit。 5 ClassWizardCEx6_2Dlg 打开ClassWizard的标签页Message Maps,在CEx6_2Dlg类中,为控件IDOK和IDCANCEL映射EN_CLICKED消息处理函数CEx6_2Dlg::OnOK()和CEx6_2Dlg::OnCancel()。 6 Ex6_2Dlg.h 选择CEx6_2Dlg类,使用快捷菜单命令Add Member Variable 添加Public数据成员:CView类的视图指针m_pView。使用快捷菜单命令Add Member Function添加Public访问类型的函数原型: CEx6_2Dlg(CView *pView); 说明:CEx6_2Dlg(CView *pView)是用于无模式对话框构造函数原型,使用参数pView可以在创建对话框时传递与对话框相关联的视图指针。使用CView的灵活性更大。 7 CEx6_2Dlg6-19 在本例中有两个构造函数,一个是模式对话框的构造函数,另一个是新增的无模式对话框的构造函 数。虽然可以象6.4.3节中直接修改默认的构造函数,但有两个构造函数的对话框类同时支持两种模式 的对话框,更加灵活些。 CEx6_2Dlg::CEx6_2Dlg(CView *pView) { m_pView=pView; } 8 CEx6_2Dlg 在Ex6_2Dlg.h文件的类定义的前面定义用户自定义消息WM_SENDMSG: #define WM_SENDMSG WM_USER+5 9 OnOK()OnCancel() 编辑CEx6_2Dlg的OnOK()和OnCancel()函数,发出用户自定义消息WM_SENDMSG到视图,控件ID的消息包含在参数wParam中。代码见程序清单6-20所示粗体部分。 void CEx6_2Dlg::OnOK() 30 第6章 创建和使用对话框 { // TODO: Add extra validation here if(m_pView!=NULL) { this->UpdateData(true); m_pView->PostMessage(WM_SENDMSG,IDOK); } else { CDialog::OnOK(); } } void CEx6_2Dlg::OnCancel() { // TODO: Add extra cleanup here if(m_pView!=NULL) { m_pView->PostMessage(WM_SENDMSG,IDCANCEL); } else { CDialog::OnCancel(); } } 10 在视图类中,添加CEx6_2Dlg类的Private访问类型的成员变量指针m_pDlg。并在Ex6_2View.h文 件的开始增加声明: class CEx6_2Dlg; 11 修改视图类的构造函数和析构函数,在视图类的构造函数中使用new在堆上构造对话框对象,并在 视图类的析构函数中使用delete删除它。 CEx6_2View::CEx6_2View() { // TODO: add construction code here m_pDlg=new CEx6_2Dlg(this); } CEx6_2View::~CEx6_2View() { delete m_pDlg; } 12 ClassWizard 31 VC++6简明教程 打开ClassWizard的标签页Message Maps,为视图类映射窗口鼠标左键单击和鼠标右键单击消息处 理函数CEx6_2View::OnLButtonDown()和CEx6_2View::OnRButtonDown()。 13 编辑OnLButtonDown()打开对话框,编辑OnRButtonDown()关闭对话框。 void CEx6_2View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default if(m_pDlg->GetSafeHwnd()==0) m_pDlg->Create(IDD_DIALOG1,this); m_pDlg->ShowWindow(SW_SHOW); } void CEx6_2View::OnRButtonDown(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default m_pDlg->ShowWindow(SW_HIDE); } 14 OnDraw() void CEx6_2View::OnDraw(CDC* pDC) { CEx6_2Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here pDC->TextOut(0,0,"Press the left mouse button here"); pDC->TextOut (100,100,m_pDlg->m_strEdit); } 15 WM_SENDMSG (1) 在Ex6_2View.cpp中所有include语句之后添加: #include “Ex6_2Dlg.h” (2) 在Ex6_2View.h中的DECLARE_MESSAGE_MAP语句之前,而且在AFX_MSG括号外面,增 加如下函数原型: afx_msg LRESULT OnSendMsg(WPARAM wParam,LPARAM lParam); (3) 在Ex6_2View.cpp中,在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP这对宏之间,而且 在AFX_MSG_MAP语句的后面增加下面代码: ON_MESSAGE(WM_SENDMSG,OnSendMsg) (4) 在Ex6_2View.cpp中增加消息处理函数。函数见程序清单6-24。 LRESULT CEx6_2View::OnSendMsg(WPARAM wParam,LPARAM lParam) { 32 第6章 创建和使用对话框 if(wParam==IDOK) { this->Invalidate(); } m_pDlg->DestroyWindow(); return 0L; } 16 单击鼠标左键,弹出对话框Send Message,单击鼠标右键,则关闭对话框Send Message。对话框打开时,在编辑框中输入文本串,单击OK,在视图窗口显示文本,并关闭对话框。单击Cancel关闭对话框。 3 CFileDialog。 要求创建一个单文档应用程序,增加一个菜单项“选择文件”,该命令能使用CFileDialog类对话框选择一个文件名,并把用户选择的文件的路径显示在主窗口的视图上。 1.对话框的数据来自三方面: 、 、和 。 2.对话框分为 和 两种。 3.测试对话框的方法有: 、 、 。 4.一个对话框资源要加入到一个窗口应用程序中,首先要为它创建一个对话框类, 是 。 5.MFC的 包含一套应用程序通用的对话框供程序员方便的加入到一个应用程序。其中, 是无模式对话框, 是模式对话框。 6.什么是对话框资源,对话框类,对话框对象? 7.MFC是怎样组织应用程序与用户之间的交互的? 8.简介创建和使用对话框主要步骤? 9.模式对话框与无模式对话框有何区别,在编程上有何不同? 10.试列出模式对话框的初始化到结束过程中所调用的函数的顺序。 11.总结DDV对每种控件的有效性检查。 1. 对话框提供了方便用户输入输出的图形界面,实质是一个可以接收消息的窗口,对话框中的控件是 一个子窗口。 2. 程序员使用对话框模板创建对话框资源,资源管理器会自动生成和维护相应的代码;使用 33 VC++6简明教程 ClassWizard可以从MFC的CDialog类中继承一个应用程序对话框类,所对应的对话框对象用于处 理并存储用户输入操作。 3. MFC应用程序执行从对话框控件到对话框对象再到文档对象的双向数据流动路径,完成用户与应用 程序的信息交互。 4. 对话框分为模式对话框和无模式对话框。模式对话框一旦执行,用户只能与对话框交互,直到模式 对话框关闭。无模式对话框则不同,打开无模式对话框后,可以随时切换到其它用户界面对象。 5. 模式对话框和无模式对话框的设计同样包括三个部分:设计对话框资源,设计对话框类,对话框的 调用。 6. 在对话框编辑器中可以方便地完成对话框资源的插入、编辑和删除。对话框资源提供了所见即所得 的图形编辑界面,使用控件工具箱在对话框模板中添加所需要的控件,并在控件的属性页中,完成 控件的设置。使用Layout菜单组织和安排控件的布局。 7. 为对话框资源创建一个对话框类,关键在于选择CDialog类为Base class。 8. 使用ClassWizard可以为对话框类映射两类成员变量,value类变量映射控件值。数据类型由所映射 的控件所决定。Control类变量实质就是一个控件对象实例,可以使用控件对象的方法操作该对象。 9. CDataExchange类提供了数据交换机制来完成对话框类值类型变量和对话框控件之间的数据交换。 在打开对话框的时候,值类型变量的值自动传递给控件,在单击“确定”键关闭对话框时,控件的 值自动传递给值类型变量。 10. CDataExchange类提供了数据有效性机制根据程序员在Classwizard中的设定,检查数据的有效 性。 11. 在对话框运行时,程序与用户之间需要实时交互数据则要在程序中调用CWnd::UpdateData()函 数触使数据交换机制的执行。Updatedata(false);由对话框对象向控件传递数据,Updatedata(true ); 由控件向对话框对象传递数据。 12. 模式对话框的调用通过两步,一是创建一个对话框对象,二是通过对话框对话对象执行 DoModal方法打开对话框。 13. 单击“OK”键关闭对话框,返回IDOK;单击“CANCEL”键关闭对话框,返回IDCANCEL。 14. 控件的初始化途径有:(1)调用对话框前,通过对话框对象设置属性值(2)在对话框类的构造函 数设置成员变量初值 (3)映射对话框类WM_InitDialog窗口消息处理函数OnInitDialog()函数,设置 控件的初始状态。 15. 无模式对话框对象不能以局部变量的形式创建,而要通过new操作动态创建,使用结束后要使 用Delete操作符删除该对象。与无模式对话框创建相关的函数有:Create()函数、ShowWindow()函 数、DestroyWindow()函数。 16. 通用对话框类由MFC提供的,可以直接调用,包括颜色对话框、文件对话框、查找/替换对话 框、字体对话框、打印对话框和页面设置对话框,其中除查找/替换对话框是无模式对话框外,其它 都是模式对话框。 34
/
本文档为【VC++6&#46;0入门【第六章 创建和使用对话框】】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索