【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2505|回复: 4

对话框编程-vc++编程指南

[复制链接]
发表于 2006-1-13 11:06:01 | 显示全部楼层 |阅读模式
第五课 对话框<BR><BR>  对话框是一种用户界面,它的主要功能是输出信息和接收用户的输入。对话框与控件是密不可分的,在每个对话框内一般都有一些控件,对话框依靠这些控件与用户进行交互.一个典型的对话框例子是选择了File-Open命令后弹出的文件对话框.<BR><BR>  对话框是一种复杂的用户界面,本章的讨论将围绕对话框和基本控件进行。<BR>5.1.1对话框的基本概念<BR><BR>  对话框(Dialog)实际上是一个窗口.在MFC中,对话框的功能被封装在了CDialog类中,CDialog类是CWnd类的派生类.<BR><BR>  对话框分为模态对话框和非模态对话框两种.大部分读者都会有这样的经历,当你通过File-Open命令打开一个文件对话框后,再用鼠标去选择菜单将只会发出嘟嘟声,这是因为文件对话框是一个模态对话框.模态对话框垄断了用户的输入,当一个模态对话框打开时,用户只能与该对话框进行交互,而其它用户界面对象收不到输入信息.我们平时所遇到的大部分对话框都是模态对话框。非模态对话框的典型例子是Windows95提供的写字板程序中的搜索对话框,搜索对话框不垄断用户的输入,打开搜索对话框后,仍可与其它用户界面对象进行交互,用户可以一边搜索,一边修改文章,这样就大大方便了使用.<BR><BR>本节主要介绍模态对话框,在第四节将介绍非模态对话框.<BR><BR>  从MFC编程的角度来看,一个对话框由两部分组成:<BR><BR>对话框模板资源.对话框模板用于指定对话框的控件及其分布,Windows根据对话框模板来创建并显示对话框.<BR><BR>对话框类.对话框类用来实现对话框的功能,由于对话框行使的功能各不相同,因此一般需要从CDialog类派生一个新类,以完成特定的功能.<BR><BR>  相应地,对话框的设计包括对话框模板的设计和对话框类的设计两个主要方面.<BR><BR>与对话框有关的消息主要包括WM_INITDIALOG消息和控件通知消息。在对话框创建时,会收到WM_INITDIALOG消息,对话框对该消息的处理函数是OnInitDialog 。<BR><BR>OnInitDialog的主要用处是初始化对话框。对话框的控件会向对话框发送控件通知消息,以表明控件的状态发生了变化。<BR><BR>5.1.2控件的基本概念<BR>&gt;<BR>控件(Control)是独立的小部件,在对话框与用户的交互过程中,控件担任着主要角色.控件的种类较多,图5.1显示了对话框中的一些基本的控件.MFC的控件类封装了控件的功能,表5.1介绍了一些常用的控件及其对应的控件类.<BR><BR>表5.1<BR><BR>控件 功能 对应控件类 <BR>静态正文(Static Text) 显示正文,一般不能接受输入信息。 CStatic <BR>图片(Picture) 显式位图、图标、方框和图元文件,一般不能接受输入信息. CStatic <BR>编辑框(Edit Box) 输入并编辑正文,支持单行和多行编辑. CEdit <BR>命令按钮(Pushbutton) 响应用户的输入,触发相应的事件. CButton <BR>检查框(Check Box) 用作选择标记,可以有选中、不选中和不确定三种状态。 CButton <BR>单选按钮(Radio Button) 用来从两个或多个选项中选中一项. CButton <BR>组框(Group Box) 显示正文和方框,主要用来将相关的一些控件聚成一组. CButton <BR>列表框(List Box) 显示一个列表,用户可以从该列表中选择一项或多项. CListBox <BR>组合框(Combo Box) 是一个编辑框和一个列表框的组合.分为简易式、下拉式和下拉列表式. CComboBox <BR>滚动条(Scroll Bar) 主要用来从一个预定义范围值中迅速而有效地选取一个整数值. CScrollBar <BR><BR>  控件实际上都是窗口,所有的控件类都是CWnd类的派生类.控件通常是作为对话框的子窗口而创建的,控件也可以出现在视窗口,工具条和状态条中.<BR>
 楼主| 发表于 2006-1-13 11:06:46 | 显示全部楼层
<>5.2对话框模板的设计<BR><BR>  利用Developer Studio提供的可视化设计工具,用户可以方便地设计对话框模板. <BR><BR>  请读者按前面章节介绍的方法利用AppWizard建立一个名为Register的MFC应用程序,并在进入MFC AppWizard对话框后按下面几步操作:  <BR><BR>在第1步中选中Single document以建立一个单文档应用程序.  <BR>在第4步中使Docking toolbar项不选中,这样AppWizard就不会创建工具条.  <BR>在第6步中先选择CRegisterView,然后在Base class栏中选择CEditView,这样CRegisterView将是CEditView的继承类,从而使视图具有了编辑功能.  <BR>  编译并运行Register,读者会发现Register居然是个编辑器,它可以打开、编辑和保存文本文件. 当然,Register的目的不仅仅是个编辑器。假设要对某一地区的就业情况进行调查,我们希望Register程序能够登录就业情况数据并将数据存储起来. <BR><BR>  要登录数据,用对话框是再合适不过了。一个典型的就业情况登录对话框如图5.1所示,本节的任务就是设计如图5.1的中文对话框模板. <BR><BR>  切换至资源视图,选择Insert-Resource命令,并在Insert Resource对话框中双击Dialog项。完成后在资源视图中会出现一个名为IDD_DIALOG1的新的对话框模板资源。双击IDD_DIALOG1,则会打开该对话框模板的编辑窗口,如图5.2所示。缺省的对话框模板有OK和Cancel两个按钮,在窗口的旁边有一个控件面板,在控件面板上用鼠标选择一个控件,然后在对话框中点击,则相应的控件就被放置到了对话框模板中。图5.3显示了控件面板上的按钮所代表的控件。读者不用记忆图5.3的内容,如果不能确定控件的类型,可将鼠标在某个控件按钮上停留片刻,则会显示一个工具提示,指出该按钮所代表控件的名称。 <BR>&gt;<BR>&gt;<BR>提示:若读者看不到控件面板,请在Developer Studio的工具条的空白处单击鼠标右键,并在随之弹出的菜单中选中Controls。  <BR><BR>  读者可以在对话框模板中随意加几个控件试试看。当用鼠标选择对话框或控件时,会出现一个围绕它的虚框,拖动虚框的边界可以改变对话框或控件的大小,在Developer Studio的状态条中会显示出所选对象的坐标和尺寸。控件可以被拖动,也可以按箭头键来移动选中的控件。在拖动控件时若按住Ctrl键,则控件会被复制。 <BR><BR>  用户可以一次选择多个控件,选择的方法有两个:1。 在对话框的空白处拖动鼠标,则拖动出来的虚线框内的控件将被选中。2。在选择控件时按住Ctrl键,则可以多重选择。 <BR><BR>  选中控件或对话框后按回车键,则会弹出一个属性对话框,属性对话框用来设置控件或对话框的各种属性。属性对话框是标签式对话框,第一页是常规属性(General)。一个典型的控件属性对话框如图5.4所示.如果对属性对话框中的选项的意思不明白,可以按F1键获得帮助. <BR>&gt;<BR>在控件属性对话框的常规属性中,有一些控件共同的属性: <BR><BR> ID属性。用于指定控件的标识符,Windows依靠ID来区分不同的控件。 <BR><BR> Caption(标题)属性。静态正文、组框、按钮、检查框、单选按钮等控件可以显示标题,用来对控件进行文字说明。控件标题中的字符&amp;使紧跟其后的字符有下划线,按Alt+下划线将启动该控件。若控件是一个单选按钮,则Alt+下划线字符将选择该按钮;若是检查框,则相当于对该检查框按空格键;若是按钮,则将激活按钮命令;若控件是一个静态正文,则将激活按tab顺序紧随其后的下一个控件。 <BR><BR> Visible属性。用来指定控件是否是可见的。 <BR><BR> Disable属性。使控件允许或禁止,一个禁止的控件呈灰色显示,不能接收任何输入。  <BR> Tabstop属性。用户可以按Tab键移动到具有Tabstop属性的控件上。Tab移动的顺序可以由用户指定。按Ctrl+D则Tab顺序会显示出来,如图5.5,用户可以用鼠标来重新指定Tab顺序。缺省的Tab顺序是控件的创建次序。  <BR> Group属性。用来指定一组控件,用户可以用箭头键在该组控件内移动。在同一组内的单选按钮具有互斥的特性,即在这些单选按钮中只能有一个是选中的。如果一个控件具有Group属性,则这个控件以及按Tab顺序紧随其后的所有控件都属于一组的,直到遇到另一个有Group属性的控件为止。  <BR>  现在就开始进行对话框模板的设计。首先,用鼠标选中对话框,按回车键,在弹出的属性对话框中将ID改为IDD_REGISTER并指定对话框的标题为“登录数据”。需要注意的是,由于要在对话框中显示汉字,因此必须设定正确的语种和字体。请读者在工作区资源视图的Dialog类型中单击鼠标选中IDD_REGISTER项,然后按Alt+Enter键,并在弹出的属性对话框中的Language栏中选择Chinese(P.R.C.)。接着,打开模板的属性对话框,单击Font...按钮,并选择“宋体”。 <BR><BR>  接着,请将对话框模板上的所有控件删除,删除的办法是选择控件后按Del键。为了容纳所有需要的控件,需将对话框的尺寸扩大到280×180。然后,请读者按图5.1和表5.2来设计对话框模板。 <BR><BR> 提示:对话框的尺寸单位不是象素,而是与字体的大小有关。X方向上一个单位等于字符平均宽度的1/4,Y方向上一个单位等于字符平均高度的1/8。这样,随着字体的改变,对话框单位也会改变,对话框本身的总体比例保持不变。 <BR>表5.2 <BR><BR> 控件类型   ID   标题(Caption)   其它属性  <BR> 组框(个人情况)   缺省   个人情况   缺省  <BR> 组框(单位情况)   缺省   单位情况   缺省  <BR> 静态正文(姓名)   缺省   姓名   缺省  <BR> 编辑框(姓名)   IDC_NAME       缺省  <BR> 检查框(婚否)   IDC_MARRIED   婚否   缺省  <BR> 静态正文(年龄)   缺省   年龄   缺省  <BR> 编辑框(年龄)   IDC_AGE       缺省  <BR> 组框(性别)   缺省   性别   缺省  <BR> 单选按钮(男)   IDC_SEX   男   Group、Tabstop  <BR> 单选按钮(女)   缺省   女   缺省  <BR> 组框(就业状况)   缺省   就业状况   缺省  <BR> 单选按钮(在职)   IDC_WORK   在职   Group、Tabstop  <BR> 单选按钮(下岗)   IDC_WORK1   下岗   缺省  <BR> 静态正文(工作单位)   缺省   工作单位   缺省  <BR> 编辑框(工作单位)   IDC_UNIT       缺省  <BR> 静态正文(单位性质)   缺省   单位性质   缺省  <BR> 组合框(单位性质)   IDC_KIND       Drop List、不排序(不选中Sort风格)、初始化列表项(见下文说明)  <BR> 静态正文(工资收入)   缺省   工资收入   缺省  <BR> 列表框(工资收入)   IDC_INCOME       不排序(不选中Sort)  <BR> 按钮(确定)   IDOK   确定(&amp;Y)   缺省  <BR> 按钮(取消)   IDCANCEL   取消(&amp;C)   缺省  <BR><BR>  请注意组合框IDC_KIND的Drop List属性,Drop List属性是在属性对话框的Styles(风格)页的Type栏中选择的,这使得IDC_KIND成为一个下拉列表式组合框。组合框有简易式(Simple)、下拉式(Dropdown)和下拉列表式(Drop List)三种。简易式组合框包含一个编辑框和一个总是显示的列表框。下拉式组合框同简易式组合框的区别在于仅当单击下滚箭头时才出现列表框。下拉列表式组合框也有一个下拉的列表框,但它的编辑框是只读的,不能输入字符。组合框IDC_KIND不要自动排序,因此需在Styles页中使Sort项不被选中。 <BR><BR>  组合框的列表项可以在设计模板时初始化,而列表框的初始化只能在程序中进行。请读者在组合框IDC_KIND的属性对话框的General页中输入以下几个列表项,以作为单位性质的选项。输入时要注意,换行时不要按回车键,而应按Ctrl+回车键。 <BR><BR> 国有企事业 <BR><BR> 集体企业 <BR><BR> 私有企业 <BR><BR> 中外合资 <BR><BR> 外商独资 <BR><BR>  组合框控件的一个与众不同之处是它有两个尺寸,一个是下拉前的尺寸,一个是下拉后的尺寸。当用鼠标点击组合框上的箭头后,可设定下拉后的尺寸。 <BR><BR>  控件最好都放在对话框模板的蓝色虚框内,控件之间的距离不要太近,否则有可能造成不正确的显示。 <BR><BR>  安置好控件之后,下一步的任务是指定Tab顺序。按Ctrl+D键后,会显示当前的Tab顺序,通过用鼠标点击控件可以设定新的Tab顺序,如果想放弃本次修改,在对话框的空白处点击一下即可。请读者按图5.5安排Tab顺序。 <BR>&gt;<BR>最后,需要测试一下对话框。按Ctrl+T,则会弹出一个当前模板的测试对话框,这个对话框的外观和基本行为与程序中将要弹出的对话框一样。这样,读者不用编译运行程序,通过测试对话框就可以评估对话框是否合乎要求。如果发现了错误或不满意的地方,可按ESC键退出测试对话框并重新修改对话框模板。 <BR><BR>  至此,对话框模板的设计就完成了。 <BR><BR></P>
 楼主| 发表于 2006-1-13 11:07:54 | 显示全部楼层
<>5.3 对话框类的设计<BR><BR>  完成对话框模板的设计后,就需要设计一个对话框类以实现对话框的功能。设计对话框类主要包括下面几步: <BR><BR> 创建对话框类。该类应从CDialog类派生。 <BR><BR> 为对话框类加入与控件相对应的成员变量。 <BR><BR> 为对话框进行初始化工作。 <BR><BR> 增加对控件通知消息的处理 <BR><BR>   <BR><BR> 5.3.1对话框类的创建 <BR><BR>  利用ClassWizard,程序员可以十分方便的创建MFC窗口类的派生类,对话框类也不例外。请读者按以下几步操作: <BR><BR>  打开IDD_REGISTER对话框模板,然后按Ctrl+W进入ClassWizard。 <BR><BR>  进入ClassWizard后,ClassWizard发现IDD_REGISTER是一个新的对话框模板,于是它会询问是否要为IDD_REGISTER创建一个对话框类。按OK键确认。 <BR><BR>  如图5.6在Create New Class对话框中,在Name栏中输入CRegisterDialog,在Base class栏中选择CDialog,在Dialog ID栏中选择IDD_REGISTER。按Create按钮后,对话框类CRegisterDialog即被创建。 <BR>&gt;<BR>ClassWizard自动使类CRegesterDialog与IDD_REGISTER模板联系起来。 <BR><BR> 提示:只要想创建的类是某一MFC窗口类的派生类,一般都可以利用ClassWizard来自动完成创建。创建的一般方法是:打开ClassWizard,选择Add Class-&gt;New,然后在Create New Class对话框中输入新类的类名,选择其MFC基类,如果是对话框类,则还要选择对话框的ID。  <BR><BR> 5.3.2为对话框类加入成员变量 <BR><BR>   <BR><BR>   对话框的主要功能是输出和输入数据,例子中的登录数据对话框的任务就是输入数据。对话框需要有一组成员变量来存储数据。在对话框中,控件用来表示或输入数据,因此,存储数据的成员变量应该与控件相对应。 <BR><BR>  与控件对应的成员变量即可以是一个数据,也可以是一个控件对象,这将由具体需要来确定。例如,可以为一个编辑框控件指定一个数据变量,这样就可以很方便地取得或设置编辑框控件所代表的数据,如果想对编辑框控件进行控制,则应该为编辑框指定一个CEdit对象,通过CEdit对象,程序员可以控制控件的行为。需要指出的是,不同类的控件对应的数据变量的类型往往是不一样的,而且一个控件对应的数据变量的类型也可能有多种。表5.3说明了控件的数据变量的类型。 <BR><BR> 表5.3 <BR><BR> 控件   数据变量的类型  <BR> 编辑框   CString, int, UINT, long, DWORD, float, double, short, BOOL, COleDateTime, COleCurrency  <BR> 普通检查框   BOOL(真表示被选中,假表示未选中)  <BR> 三态检查框   int(0表示未选中,1表示选中,2表示不确定状态)  <BR> 单选按钮(组中的第一个按钮)   int(0表示选择了组中第一个单选按钮,1表示选择了第二个...,-1表示没有一个被选中)  <BR> 不排序的列表框   CString(为空则表示没有一个列表项被选中),   <BR> int(0表示选择了第一项,1表示选了第二项,-1表示没有一项被选中)  <BR><BR> 下拉式组合框   CString, int(含义同上)  <BR> 其它列表框和组合框   CString(含义同上)  <BR><BR>  利用ClassWizard可以很方便地为对话框类CRegisterDialog加入成员变量。请读者按下列步骤操作。 <BR><BR> 按Ctrl+W进入ClassWizard。 <BR><BR> 选择ClassWizard上部的Member Variables标签,然后在Class name栏中选择CRegisterDialog。这时,在下面的变量列表中会出现对话框控件的ID,如图5.7所示。<BR>&gt;<BR>双击列表中的ID_AGE会弹出Add Member Variable对话框,如图5.8所示。在Member variable name栏中输入m_nAge,在Category栏中选择Value,在Variable type栏中选择UINT。按OK按钮后,数据变量m_nAge就会被加入到变量列表中。<BR>&gt;<BR>仿照第3步和表5.4,为各个控件加入相应的成员变量。 <BR><BR>  将m_nAge的值限制在16到65之间。方法是先选择m_nAge,然后在ClassWizard对话框的左下角输入最大和最小值。m_nAge代表年龄,这里规定被调查的人的年龄应在16岁以上,64岁以下。有了这个限制后,对话框会对输入的年龄值进行有效性检查,若输入的值不在限制范围内,则对话框会提示用户输入有效的值。 <BR><BR> 表5.4 <BR><BR> 控件ID   变量类型   变量名  <BR> IDC_AGE   UINT   m_nAge  <BR> IDC_INCOME   CString   m_strIncome  <BR> IDC_INCOME   CListBox   m_ctrlIncome  <BR> IDC_KIND   CString  m_strKind  <BR> IDC_MARRIED   BOOL   m_bMarried  <BR> IDC_NAME   CString   m_strName  <BR> IDC_SEX   int   m_nSex  <BR> IDC_UNIT   CString   m_strUnit  <BR> IDC_WORK   int   m_nWork  <BR><BR><BR>  读者会注意到控件IDC_INCOME居然有两个变量,一个是CString型的,一个是CListBox型的,这是完全合法的,不会引起任何冲突。之所以要加入CListBox型的变量,是因为列表框的初始化要通过CListBox对象进行。 <BR><BR> 提示:在ClassWizard中可分别为一个控件指定一个数据变量和一个控件对象,这样做的好处是即能方便地获得数据,又能方便地控制控件。  <BR><BR></P>
 楼主| 发表于 2006-1-13 11:08:09 | 显示全部楼层
<>5.3.3对话框的初始化 <BR><BR>  对话框的初始化工作一般在构造函数和OnInitDialog函数中完成。在构造函数中的初始化主要是针对对话框的数据成员。读者可以找到CRegisterDialog的构造函数,如清单5.1所示。 <BR><BR>   <BR><BR> 清单5.1 CRegisterDialog的构造函数 <BR></P>
<> CRegisterDialog::CRegisterDialog(CWnd* pParent /*=NULL*/) <BR><BR> : CDialog(CRegisterDialog::IDD, pParent) <BR><BR> { <BR><BR> //{{AFX_DATA_INIT(CRegisterDialog) <BR><BR> m_nAge = 0; <BR><BR> m_strIncome = _T(""); <BR><BR> m_strKind = _T(""); <BR><BR> m_bMarried = FALSE; <BR><BR> m_strName = _T(""); <BR><BR> m_nSex = -1; <BR><BR> m_strUnit = _T(""); <BR><BR> m_nWork = -1; <BR><BR> //}}AFX_DATA_INIT <BR><BR> }</P>
<><BR>  可以看出,对数据成员的初始化是由ClassWizard自动完成的。若读者对初值的含义还不太清楚,请参看表5.3。 <BR><BR>  在对话框创建时,会收到WM_INITDIALOG消息,对话框对该消息的处理函数是OnInitDialog。调用OnInitDialog时,对话框已初步创建,对话框的窗口句柄也已有效,但对话框还未被显示出来。因此,可以在OnInitDialog中做一些影响对话框外观的初始化工作。OnInitDialog对对话框的作用与OnCreate对CMainFrame的作用类似。 <BR><BR> 提示:MFC窗口的初始化工作一般在OnCreate成员函数中进行,但对话框的初始化工作最好在OnInitDialog中进行。  <BR><BR>  OnInitDialog是WM_INITDIALOG消息的处理函数,所以要用ClassWizard为RegisteritDialog类增加一个WM_INITDIALOG消息的处理函数,增加的方法是进入ClassWizard后,先选中MessageMaps标签,然后在Class name中选择CRegisterDialog,在Object IDs栏中选择CRegisterDialog,在Messages栏中找到WM_INITDIALOG并双击之,最后按OK按钮退出ClassWizard。 <BR><BR>  请读者按清单5.2修改OnInitDialog函数。 <BR><BR>   <BR><BR> 清单5.2 OnInitDialog函数 <BR></P>
<> BOOL CRegisterDialog::OnInitDialog()  <BR><BR> { <BR><BR> CDialog::OnInitDialog(); <BR><BR>   <BR><BR> // TODO: Add extra initialization here <BR><BR>   <BR><BR> m_ctrlIncome.AddString("500元以下"); <BR><BR> m_ctrlIncome.AddString("500-1000元"); <BR><BR> m_ctrlIncome.AddString("1000-2000元"); <BR><BR> m_ctrlIncome.AddString("2000元以上"); <BR><BR>   <BR><BR> return TRUE; // return TRUE unless you set the focus to a control <BR><BR> // EXCEPTION: OCX Property Pages should return FALSE <BR><BR> }</P>
<><BR>  CRegisterDialog::OnInitDialog()的主要任务是对工资收入列表框的列表项进行初始化。调用CListBox::AddString可将指定的字符串加入到列表框中。由于该列表是不自动排序的,因此AddString将表项加在列表框的末尾。 <BR><BR> 5.3.4对话框的数据交换机制 <BR><BR>  对话框的数据成员变量存储了与控件相对应的数据。数据变量需要和控件交换数据,以完成输入或输出功能。例如,一个编辑框即可以用来输入,也可以用来输出:用作输入时,用户在其中输入了字符后,对应的数据成员应该更新;用作输出时,应及时刷新编辑框的内容以反映相应数据成员的变化。对话框需要一种机制来实现这种数据交换功能,这对对话框来说是至关重要的。 <BR><BR>  MFC提供了类CDataExchange来实现对话框类与控件之间的数据交换(DDX),该类还提供了数据有效机制(DDV)。数据交换和数据有效机制适用于编辑框、检查框、单选按钮、列表框和组合框。 <BR><BR>  数据交换的工作由CDialog:oDataExchange来完成。读者可以找到CRegisterDialog:oDataExchange函数,如清单5.3所示。 <BR><BR> 清单5.3 DoDataExchange函数 <BR></P>
<> void CRegisterDialog:oDataExchange(CDataExchange* pDX) <BR><BR> { <BR><BR> CDialog:oDataExchange(pDX); <BR><BR> //{{AFX_DATA_MAP(CRegisterDialog) <BR><BR> DDX_Control(pDX, IDC_INCOME, m_ctrlIncome); <BR><BR> DDX_LBString(pDX, IDC_INCOME, m_strIncome); <BR><BR> DDX_CBString(pDX, IDC_KIND, m_strKind); <BR><BR> DDX_Check(pDX, IDC_MARRIED, m_bMarried); <BR><BR> DDX_Text(pDX, IDC_NAME, m_strName); <BR><BR> DDX_Radio(pDX, IDC_SEX, m_nSex); <BR><BR> DDX_Text(pDX, IDC_UNIT, m_strUnit); <BR><BR> DDX_Radio(pDX, IDC_WORK, m_nWork); <BR><BR> DDX_Text(pDX, IDC_AGE, m_nAge); <BR><BR> DDV_MinMaxUInt(pDX, m_nAge, 16, 65); <BR><BR> //}}AFX_DATA_MAP <BR><BR> } </P>
<><BR>  读者可以看出,该函数中的代码是由ClassWizard自动加入的。DoDataExchange只有一个参数,即一个CDataExchange对象的指针pDX。在该函数中调用了DDX函数来完成数据交换,调用DDV函数来进行数据有效检查。 <BR><BR>  当程序需要交换数据时,不要直接调用DoDataExchange函数,而应该调用CWnd::UpdateData。UpdataData函数内部调用了DoDataExchange。该函数只有一个布尔型参数,它决定了数据传送的方向。调用UpdateData(TRUE)将数据从对话框的控件中传送到对应的数据成员中,调用UpdateData(FALSE)则将数据从数据成员中传送给对应的控件。 <BR><BR>  在缺省的CDialog::OnInitDialog中调用了UpdateData(FALSE),这样,在对话框创建时,数据成员的初值就会反映到相应的控件上。若用户是按了OK(确定)按钮退出对话框,则对话框认为输入有效,就会调用UpdataData(TRUE)将控件中的数据传给数据成员。图5.9描绘了对话框的这种数据交换机制。<BR></P>
 楼主| 发表于 2006-1-13 11:08:41 | 显示全部楼层
<>5.3.5对话框的运行机制 <BR><BR>  在程序中运行模态对话框有两个步骤: <BR><BR> 在堆栈上以变量的形式构建一个对话框对象。 <BR><BR> 调用CDialog:oModal ( )。 <BR><BR>   <BR><BR>  DoModal负责对模态话框的创建和撤销。在创建对话框时,DoModal的任务包括载入对话框模板资源、调用OnInitDialog初始化对话框和将对话框显示在屏幕上。完成对话框的创建后,DoModal启动一个消息循环,以响应用户的输入。由于该消息循环截获了几乎所有的输入消息,使主消息循环收不到对对话框的输入,致使用户只能与模态对话框进行交互,而其它用户界面对象收不到输入信息。 <BR><BR>  若用户在对话框内点击了ID为IDOK的按钮(通常该按钮的标题是“确定”或“OK”),或按了回车键,则CDialog::OnOK将被调用。OnOK首先调用UpdateData(TRUE)将数据从控件传给对话框成员变量,然后调用CDialog::EndDialog关闭对话框。关闭对话框后,DoModal会返回值IDOK。 <BR><BR>  若用户点击了ID为IDCANCEL的按钮(通常其标题为“取消”或“Cancel”),或按了ESC键,则会导致CDialog::OnCancel的调用。该函数只调用CDialog::EndDialog关闭对话框。关闭对话框后,DoModal会返回值IDCANCEL。 <BR><BR>  程序根据DoModal的返回值是IDOK还是IDCANCEL就可以判断出用户是确定还是取消了对对话框的操作。 <BR><BR>  在弄清了对话框的运行机制后,下面让我们来就可以实现Register程序登录数据的功能。 <BR><BR>  首先,将Register工程的工作区切换至资源视图。打开IDR_MAINFRAME菜单资源,在Edit菜单的底端加入一个名为“登录数据”的新菜单项,并令其ID为ID_EDIT_REGISTER(最好在该项之前加一条分隔线,以便和前面的菜单项分开)。注意不要忘了把菜单资源的语种设置成中文,否则菜单中将显示不出中文来。设置的方法是先在工作区资源视图中选择IDR_MAINFRAME菜单资源,然后按Alt+Enter键,并在弹出的属性对话框中的Language栏中选择Chinese(P.R.C.)。 <BR><BR>  接着,用ClassWizard为该菜单命令创建命令处理函数CRegisterView::OnEditRegister。注意,OnEditRegister是类CRegisterView的成员函数,这是因为CRegisterView要负责打开和关闭登录数据对话框,并将从对话框中输入的数据在视图中输出。 <BR><BR>  然后,请读者在RegisterView.cpp文件的开头加入下面一行 <BR><BR>  #include "RegisterDialog.h" <BR><BR>  最后,按清单5.4修改程序。 <BR><BR>  清单5.4 OnEditRegister函数 <BR></P>
<> void CRegisterView::OnEditRegister()  <BR><BR> { <BR><BR> // TODO: Add your command handler code here <BR><BR> CRegisterDialog dlg; <BR><BR> if(dlg.DoModal()==IDOK) <BR><BR> { <BR><BR> CString str; <BR><BR> //获取编辑正文 <BR><BR> GetWindowText(str); <BR><BR> //换行 <BR><BR> str+="\r\n"; <BR><BR> str+="姓名:"; <BR><BR> str+=dlg.m_strName; <BR><BR> str+="\r\n"; <BR><BR> str+="性别:"; <BR><BR> str+=dlg.m_nSex?"女":"男"; <BR><BR> str+="\r\n"; <BR><BR> str+="年龄:"; <BR><BR> CString str1; <BR><BR> //将数据格式输出到字符串对象中 <BR><BR> str1.Format("%d",dlg.m_nAge); <BR><BR> str+=str1; <BR><BR> str+="\r\n"; <BR><BR> str+="婚否:"; <BR><BR> str+=dlg.m_bMarried?"已婚":"未婚"; <BR><BR> str+="\r\n"; <BR><BR> str+="就业状况:"; <BR><BR> str+=dlg.m_nWork?"下岗":"在职"; <BR><BR> str+="\r\n"; <BR><BR> str+="工作单位:"; <BR><BR> str+=dlg.m_strUnit; <BR><BR> str+="\r\n"; <BR><BR> str+="单位性质:"; <BR><BR> str+=dlg.m_strKind; <BR><BR> str+="\r\n"; <BR><BR> str+="工资收入:"; <BR><BR> str+=dlg.m_strIncome; <BR><BR> str+="\r\n"; <BR><BR> //更新编辑视图中的正文 <BR><BR> SetWindowText(str); <BR><BR> } <BR><BR> } </P>
<><BR>  在OnEditRegister函数中,首先构建了一个CRegisterDialog对象,然后调用CDialog:oModal来实现模态对话框。如果DoModal返回IDOK,则说明用户确认了登录数据的操作,程序需要将录入的数据在编辑视图中输出。程序用一个CString对象来作为编辑正文的缓冲区,CString是一个功能强大的字符串类,它的最大特点在于可以存储动态改变大小的字符串,这样,用户不必担心字符串的长度超过缓冲区的大小, 使用十分方便。 <BR><BR>  在输出数据时,程序首先调用CWnd::GetWindowText获得编辑正文,这是一个多行的编辑正文。CWnd::GetWindowText用来获取窗口的标题,若该窗口是一个控件,则获取的是控件内的正文。CRegisterView是CEditView的继承类,而CEditView实际上包含了一个编辑控件,因此在CRegisterView中调用GetWindowText获得的是编辑正文。 <BR><BR>  然后,程序在该编辑正文的末尾加入新的数据。在程序中大量使用了CString类的重载操作符“+=”,该操作符的功能是将操作符右侧字符串添加到操作符左侧的字符串的末尾。注意在多行编辑控件中每行末尾都有一对回车和换行符。在程序中还调用了CString::Format来将数据格式化输出到字符串中,Format的功能与sprintf类似。最后,调用CWnd::SetWindowText来更新编辑视图中的正文。 <BR><BR>  编译并运行Register,打开登录数据对话框,输入一些数据试试。现在,Register已经是一个简易的数据库应用程序了,它可以将与就业情况有关的数据输出到一个编辑视图中。用户可以编辑视图中的正文,并将结果保存在文本文件中。 <BR></P>
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 03:57

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表