1、第三章对话框和常用控件第三章对话框和常用控件3.1 对话框的使用对话框的使用3.2 控件的创建和使用方法控件的创建和使用方法 3.3 常用控件常用控件 3.4 通用对话框和消息对话框通用对话框和消息对话框 3.5 综合应用综合应用3.1对话框的使用对话框的使用 在Visual C+6.0应用程序中,使用一个对话框通常有两种情形:一是直接创建一个对话框应用程序,二是在一个应用程序中进行调用。为不失一般性,这里介绍第二种对话框使用情况的一般过程,即依次如下:(1)添加对话框资源;(2)设置对话框的属性;(3)添加和布局控件;(4)创建对话框类;(5)添加对话框代码;(6)在程序中调用对话框。显然,
2、对于第一种对话框使用情况来说,其过程通常是从(2)到(5)。3.1.1 添加对话框资源 在对话框资源添加之前,先来创建一个默认的单文档应用程序Ex_SDI:(1)在“D:Visual C+应用”文件夹中,创建本章应用程序工作文件夹“第3章”。(2)启动Visual C+6.0,选择“文件”“新建”菜单,在弹出的“新建”对话框的工程标签页面中,选择MFC AppWizard(exe)的项目类型。单击位置框右侧的按钮,在弹出的对话框中,将该应用程序的文件夹定位在“D:Visual C+应用第3章”,并在工程编辑框中输入单文档应用程序名Ex_SDI。3.1对话框的使用对话框的使用 (3)单击确定按钮
3、,在出现的“步骤1”对话框中,选择“单个文档”应用程序类型。(4)单击完成按钮出现一个信息对话框,显示出用户在前面几个步骤中作出的选择内容,单击确定按钮系统开始创建,并又回到了Visual C+6.0的主界面。若无特别说明,以后凡遇到“创建一个默认的单文档应用程序创建一个默认的单文档应用程序Ex_XXXX”就是指上述的步骤,本书作此约定。其中,Ex_XXXX为创建的应用程序名。这样就可在单文档应用程序Ex_SDI中添加一个对话框资源,通常按下列步骤进行:(1)选择“插入”“资源”菜单,或按快捷键Ctrl+R打开“插入资源”对话框,在对话框中可以看到资源列表中存在Dialog项,若单击Dialo
4、g项左边的“+”号,将展开对话框资源的不同类型选项,如图3.1所示,表3.1列出各种类型的对话框资源的不同用途。图图3.1“插入资源插入资源”对话框对话框 其中,新建按钮是用来创建一个由“资源类型”列表中指定类型的新资源,自定义按钮是用来创建“资源类型”列表中没有的新类型的资源,引入按钮是用于将外部已有的位图、图标、光标或其他定制的资源添加到当前应用程序中。3.1对话框的使用对话框的使用表表3.1 对话框资源类型对话框资源类型类类 型型说说 明明IDD_DIALOGBAR对话条,往往和工具条停放一起IDD_FORMVIEW一个表单(一种样式的对话框),用于表单视图类的资源模板IDD_OLE_P
5、ROPPAGE_LARGE一个大的OLE属性页IDD_OLE_PROPPAGE_SMALL一个小的OLE属性页IDD_ PROPPAGE_LARGE一个大属性页,用于属性对话框IDD_ PROPPAGE_MEDIUM一个中等大小的属性页,用于属性对话框IDD_ PROPPAGE_SMALL一个小的属性页,用于属性对话框3.1对话框的使用对话框的使用 (3)对展开的不同类型的对话框资源不作任何选择,选中“Dialog”,单击新建按钮,系统就会自动为当前应用程序添加了一个对话框资源,并出现如图3.2所示的界面。对话框模对话框模板板控件工具控件工具栏栏布局工具布局工具栏栏默认标识默认标识符符图图3.
6、2 添加对话框资源后的开发环境添加对话框资源后的开发环境3.1对话框的使用对话框的使用 系统为对话框资源自动赋给它一个默认的标识符名称(第一次为IDD_DIALOG1,以后依次为IDD_DIALOG2、IDD_DIALOG3、.)。使用了通用的对话框模板创建新的对话框资源。对话框的默认标题为“对话”(Dialog),有确定和取消两个按钮,这两个按钮的标识符分别为IDOK和IDCANCEL。自动出现“对话框资源编辑器”窗口,在这里可以通过“控件工具栏”和“布局工具栏”向对话框添加和布局控件,并可设置对话框的属性。需要说明的是,第一次使用Visual C+6.0的对话框编辑器时,“控件工具栏”和“
7、布局工具栏”可能是浮动,可以将其拖放到指定位置(参看图3.2),以便让开发环境更易于操作。3.1.2 设置对话框属性设置对话框属性 在对话框模板的空白处右击鼠标,从弹出的快捷菜单中选择“属性”菜单项,出现如图3.3所示的对话框属性窗口。可以看出,对话框具有这几类属性:常规(General)、样式(Styles)、更多样式(More Styles)、扩展样式(Extended Styles)、更多扩展More Extended Styles(更多扩展样式)等部分,这里仅介绍最常用的常规(General)属性,如表4.2所示。3.1对话框的使用对话框的使用图图3.3 对话框属性窗口对话框属性窗口表
8、表3.2 对话框的常规(对话框的常规(General)属性)属性项项 目目说说 明明ID框修改或选择对话框的标识符名称标题框输入对话框的标题名称,中英文均可,如“我的对话框”字体按钮单击此按钮可选择字体的种类(如宋体)及尺寸(如9号)位置X/位置Y对话框左上角在父窗口中的X、Y坐标,都为0时表示居中菜单框默认值为无,当对话框需要菜单时输入或选择指定的菜单资源类名称框默认值为无,它提供C/C+语言编程时所需要的对话框类名,对MFC类库的资源文件来说,该项不被激活。3.1对话框的使用对话框的使用图3.3中,有一个 图标,当单击此图标后,图标变成,表示该对话框将一直显示直到用户关闭它。在 状态下,当
9、该对话框一旦失去活动状态后就会自动消失!将添加的对话框的属性进行以下3点修改,结果如图3.4所示:在ID框中,将对话框标识符IDD_DIALOG1改成IDD_DIALOG_FIRST;在标题框中,将对话框标题“对话”改为“我的第一个对话框”;单击字体按钮,通过弹出的字体对话框将对话框内的文本设置成“宋体,9”,以使自己的对话框和Windows中的对话框保持外观上的一致(这是界面设计的“一致性”原则)。3.1对话框的使用对话框的使用图图3.4 对话框属性修改后的界面对话框属性修改后的界面3.1对话框的使用对话框的使用 3.1.3 添加和布局控件 一旦对话框资源被打开或被创建,就会出现对话框编辑器
10、,通过它可以在对话框中进行控件的添加和布局等操作。1.控件的添加控件的添加对话框编辑器一旦打开,“控件”工具栏一般都会随之出现。若不出现,则可在开发环境的 工具栏区的空白处右击鼠标,从弹出的快捷菜单中选择“控件”。利用“控件”工具栏中的各个按钮可以顺利完成控件的添加。图3.5说明了各个按钮所对应的控件类型。控件的选择控件的选择静态文本静态文本组框组框复选框复选框组合框组合框水平滚动条水平滚动条旋转按钮旋转按钮滑动条滑动条列表视图列表视图标签标签复合编辑复合编辑月历月历用户定制控用户定制控件件静态图片静态图片编辑框编辑框按钮按钮单选框单选框列表框列表框垂直滚动条垂直滚动条进展条进展条热键热键树形
11、视图树形视图动画动画日期选择日期选择IP地址地址扩展组合框扩展组合框图图3.5 控件工具栏和各按钮含义控件工具栏和各按钮含义3.1对话框的使用对话框的使用 向对话框添加一个控件的方法有下列几种:在控件工具栏中单击某控件,此时的鼠标箭头在对话框内变成“十”字形状;在对话框指定位置单击鼠标左键,则此控件被添加到对话框的相应位置,再拖动刚添加控件的选择框可改变其大小和位置。在控件工具栏中单击某控件,此时的鼠标箭头对话框内变成“十”字形状;在指定位置处单击鼠标左键不放,拖动鼠标至满意位置,释放鼠标键。用鼠标左键点中控件工具栏中的某控件,并按住鼠标左键不放;在移动鼠标到对话框的指定位置的过程中,用户会看
12、到一个虚线框,下面带有该控件的标记;释放鼠标左键,新添加的控件立即出现在对话框中。2.控件的选取控件的选取 控件的删除、复制和布局操作一般都要先选取控件,若选取单个控件,则可以下列方法:用鼠标直接选取。首先保证在控件工具栏中的选择按钮()是被选中的,然后移动鼠标指针至指定的控件上,单击鼠标左键即可。用助记符来选取。如果控件的标题中带有下划线的字符,这个字符就是助记符,选择时直接按下该助记符键或“Alt+助记符”组合键即可。3.1对话框的使用对话框的使用 用Tab键选取。在对话框编辑器中,系统会根据控件的添加次序自动设置相应的Tab键次序。利用Tab键,用户可在对话框内的控件中进行选择。每按一次
13、Tab键依次 选取对话框中的下一个控件,若按住Shift键,再单击Tab键则选取上一个控件。对于多个控件的选取,可采用下列方法:先在对话框内按住鼠标左键不放,拖出一个大的虚框,然后释放鼠标,则被该虚框所包围的控件都将被选取。先按住Shift键不放,然后用鼠标选取控件,直到所需要的多个控件选取之后再释放Shift键。若在选取时,对已选取的控件再选取一下,则取消该控件选取。需要注意的是:(1)一旦单个控件被选取后,其四周由选择框包围着,选择框上还有几个(通常是八个)蓝色实心小方块,拖动它可改变控件的大小,如图3.6(a)所示。(2)多个控件被选取后,其中只有一个控件的选择框有几个蓝色实心小方块,这
14、个控件称为主要控件主要控件,而其他控件的选择框的小方块是空心的。如图3.6(b)所示。图图3.6 单个控件和多个控件的选择框单个控件和多个控件的选择框(a)(b)3.1对话框的使用对话框的使用3.控件的删除、复制和布局控件的删除、复制和布局 当单个控件或多个控件被选取后,按方向键或用鼠标拖动控件的选择框可移动控件。若在鼠标拖动过程中还按住Ctrl键则复制控件。若按Del键可将选取的控件删除。当然还有其他一些编辑操作,但这些操作方法和一般的文档编辑器基本相同,这里不再重复。对于控件的布局,对话框编辑器中提供了控件布局工具栏,如图3.7所示,它可以自动地排列对话框内的控件,并能改变控件的大小。靠齐
15、上边靠齐上边 左右间隔相左右间隔相等等 大小相同大小相同靠 齐 左 边靠 齐 左 边上 下 居 中上 下 居 中宽度相同宽度相同 显示标尺显示标尺 靠齐右边靠齐右边 左右居中左右居中 高度相同高度相同测 试 对 话 框测 试 对 话 框 靠 齐 下 边靠 齐 下 边 上 下 间 隔 相 等上 下 间 隔 相 等显示网格显示网格图图3.7 控件布局工具栏控件布局工具栏 3.1对话框的使用对话框的使用 需要说明的是:(1)随着对话框编辑器的打开,Visual C+6.0开发环境的菜单栏还出现“布局”菜单,它的命令与布局工具相对应,而且大部分命令名后面还显示出相应的快捷键,由于它们都是中文的(汉化过
16、),故这里不再列出。(2)大多数布置控件的命令使用前,都需要用户选取多个控件,且“主要控件”起到了关键作用。例如用户选取多个控件后,使用“大小相同”命令只改变其它控件的大小,并与“主 要控件”的尺寸一致。因此,在多个控件的布置过程中,常需要重新设置“主要控件”。设置的方法是按住Ctrl或Shift键,然后用鼠标单击所要指定的控件即可。(3)为了便于用户在对话框内精确定位各个控件,系统还提供了网格、标尺等辅助工具。在图3.7的控件布局工具栏的最后两个按钮分别用来网格和标尺的切换。一旦网格显示,添加或移动控件时都将自动定位在网格线上。3.1对话框的使用对话框的使用4.测试对话框测试对话框 “布局”
17、菜单下的“测试”命令或布局工具栏上的测试按钮是用来模拟所编辑的对话框的运行情况,帮助用户检验对话框是否符合用户的设计要求以及控件功能是否有效等。5.操作示例操作示例 (1)下面来向对话框添加三个静态文本控件(一个静态文本控件就是一个文本标签):(2)在控件工具栏上,单击 按钮,然后在对话框模板左上角单击鼠标左键不放,拖动 鼠标至满意位置,释放鼠标键。这样,第一个静态文本控件添加到对话框中了。(3)单击布局工具栏上的 按钮,打开对话框模板的网格。(4)在控件工具栏上,将 按钮拖放到对话框模板中的左中部。这样,第二个静态文本控件添加到对话框中了。同样的操作,将第三个静态文本控件拖放到对话框模板中的
18、左下部。(5)按住Shift键不放,依次单击刚才添加的三个静态文本控件,结果如图3.8所示。在布局工具栏上,依次单击“大小相同”按钮 、“靠左对齐”按钮 、“上下间隔相等”按钮 ,结果如图3.9所示。3.1对话框的使用对话框的使用图图3.8 布局前的静态文本控件布局前的静态文本控件 图图3.9 布局后的静态文本控件布局后的静态文本控件3.1.4 创建对话框类在对话框资源模板的空白区域(没有其他元素或控件)内双击鼠标或按Ctrl+W快捷键,将弹出一个对话框,询问是否为对话框资源创建一个新类。单击OK按钮,将弹出如图3.10所示的New Class(新类)对话框。在Name(名称)框中输入类名CF
19、irstDlg。Base class(基类)和Dialog ID(对话框标识符)内容是由系统自动设置的,一般无需修改。从Base class框的内容可以看出,用户对话框类是从基类CDialog派生而来的。3.1对话框的使用对话框的使用 单击OK按钮,一个基于对话框资源模板的对话框类CFirstDlg就创建好了。此时,出现MFC ClassWizard(MFC类向导)对话框。图图3.10“New Class”对话框对话框3.1对话框的使用对话框的使用 3.1.5 添加对话框代码 在MFC ClassWizard对话框,查看“Class name”列表中是否选择了CFirstDlg,若不是,则在I
20、Ds列表中选择CFirstDlg。在Messages框中找到并选定WM_INITDIALOG消息,如图3.11。单击Add Function按钮或双击WM_INITDIALOG消息,MFC ClassWizard自动为CFirstDlg类添加OnInitDialog函数。图图3.11“MFC ClassWizard”对话框对话框3.1对话框的使用对话框的使用 需要说明的是,WM_INITDIALOG是在对话框显示之前向父窗口发送的消息,由于建立了此消息和OnInitDialog函数的关联,系统在对话框显示之前就会调用此函数,因此常将对话框一些初始化代码添加到这个函数中。在Member func
21、tions列表框中选择刚添加的OnInitDialog函数,单击Edit Code按钮(或直接在函数名双击鼠标),将自动出现该函数代码编辑窗口,在此函数中添加下列代码:BOOL CFirstDlg:OnInitDialog()CDialog:OnInitDialog();/TODO:Add extra initialization herethis-SetWindowText(修改标题);return TRUE;/return TRUE unless you set the focus to a control /EXCEPTION:OCX Property Pages should retu
22、rn FALSE 代码中,SetWindowText是CWnd的一个成员函数,用来设置窗口的文本内容。对于对话框来说,它设置的是对话框标题。3.1对话框的使用对话框的使用 3.1.6 在程序中调用对话框 在程序中调用对话框,一般是通过映射事件的消息(如命令消息、鼠标消息、键盘消息等),在映射函数中进行调用。这样,相应事件产生后,就会调用其消息映射函数,从而调用对话框的代码初执行。例如,下面的步骤用来实现在单文档应用程序 Ex_SDI的客户区中单击鼠标左键,显示前面添加的对话框。(1)按Ctrl+W键,弹出MFC ClassWizard对话框。(2)在Message Maps页面中,从Class
23、 name列表中选择CEx_SDIView,在IDs列表中选择CEx_SDIView,然后在Messages框中找到并选中WM_LBUTTONDOWN消息。(3)单击Add Function按钮或双击WM_LBUTTONDOWN消息,则该消息的映射函数OnLButtonDown自动添加到Member Functions列表框中。(4)选中刚才添加的OnLButtonDown函数,单击Edit Code按钮(或直接双击函数名),在打开的文档窗口中的此成员函数中添加下列代码:void CEx_SDIView:OnLButtonDown(UINT nFlags,CPoint point)/TODO:
24、Add your message handler code here and/or call defaultCFirstDlg dlg;dlg.DoModal();CView:OnLButtonDown(nFlags,point);3.1对话框的使用对话框的使用 代码中,DoModal是CDialog基类成员函数,用来将对话框按模式方式来显示。(5)在CEx_SDIView 类的实现文件Ex_SDIView.cpp的前面添加CFirstDlg类的包含语句,即:#include Ex_SDIDoc.h#include Ex_SDIView.h#include FirstDlg.h (6)编译并运
25、行。在应用程序文档窗口的客户区中单击鼠标,就会出现如图3.12的对话框,这个对话框就是刚才添加的对话框,对话框的标题是程序代码所指定的结果。图图3.12 Ex_SDI运行的结果运行的结果3.1对话框的使用对话框的使用3.1.7 模式对话框和无模式对话框 上述通过DoModal成员函数来显示的对话框称为模式对话框模式对话框,所谓“模式对话框”是指当对话框被弹出,用户必须在对话框中作出相应的操作,在退出对话框之前,对话框所在应用程序的其它操作不能继续执行。模式对话框的应用范围较广,一般情况下,模式对话框会有确定(OK)和取消(Cancel)按钮。单出确定按钮,系统认定用户在对话框中的选择或输入有效
26、,对话框退出;单击取消按钮,对话框中的选择或输入无效,对话框退出,程序恢复原有状态。事实上,对话框还可以用“无模式”方式来显示,称为无模式对话框无模式对话框,所谓“无模式对话框”是指当对话框被弹出后,一直保留在屏幕上,用户可继续在对话框所在的应用程序中进行其它操作;当需要使用对话框时,只需象激活一般窗口一样单击对话框所在的区域即可激活。由于“无模式”方式还要涉及到其它一些编程工作,限于篇幅,这里不作讨论。3.2控件的创建和使用方法控件的创建和使用方法 3.2.1 控件的创建方法 控件的创建方式有以下两种:一种是在对话框模板资源中用编辑器来指定控件,这就是说,将控件的父窗口父窗口指定为对话框,这
27、样做的好处是明显的,因为当应用程序启动该对话框时,框架系统就会为对话框创建控件;而当对话框消失时,控件也随之清除。另一种方式是将控件看作是任一窗口的子窗口子窗口,并通过调用相应的Create函数来创建。例例Ex_Edit 使用编程方式来创建一个编辑框使用编程方式来创建一个编辑框 (1)启动Visual C+6.0,选择“文件”“新建”菜单,在弹出的“新建”对话框的工程标签页面中,选择MFC AppWizard(exe)的项目类型。单击位置框右侧的按钮,在弹出的对话框中,将该应用程序的文件夹定位在“D:Visual C+应用第3章”,并在工程编辑框中输入单文档应用程序名Ex_Edit。(2)单击
28、确定按钮,在出现的“步骤1”对话框中,选择“基本对话框”应用程序类型。(3)单击完成按钮出现一个信息对话框,显示出用户在前面几个步骤中作出的选择内容,单击确定按钮系统开始创建,并又回到了Visual C+6.0的主界面。若无特别说明,以后凡遇到“创建一个默认的基于对话框应用程序创建一个默认的基于对话框应用程序Ex_XXXX”就是指上述的步骤,本书作此约定。其中,Ex_XXXX为创建的应用程序名。3.2控件的创建和使用方法控件的创建和使用方法 (4)将项目工作区切换到ClassView页面,展开Ex_Edit所有的类结点,右击CEx_EditDlg类名,从快捷菜单中选择Add Member Va
29、riable(添加成员变量),在出现的对话框中定义一个CEdit类对象m_wndEdit,通常以“m_”来作为变量的开头,表示“成员”(member)的意思。如图3.13所示,单击确定按钮。在MFC中,每一个类型的控件都用相应的类来封装。如编辑框控件,它的类是CEdit,通过该类对象来访问其成员,从而实现编辑框的操作。图图3.13 添加成员变量添加成员变量3.2控件的创建和使用方法控件的创建和使用方法 (5)在项目工作区窗口的ClassView页面中,将CEx_EditDlg结点展开,双击OnInitDialog函数名,在该函数中添加下列代码(return true;语句之前添加):BOOL
30、CEx_EditDlg:OnInitDialog()CDialog:OnInitDialog();CRect rcClient;this-GetClientRect(rcClient);rcClient.right-=100;m_wndEdit.Create(ES_MULTILINE|WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_BORDER,rcClient,this,201);/创建 CFont*font=this-GetFont();/获取对话框的字体 m_wndEdit.SetFont(font);/设置控件字体 return TRUE;/return TRUE
31、unless you set the focus to a control 3.2控件的创建和使用方法控件的创建和使用方法 分析和说明:前面曾说过,由于OnInitDialog函数在对话框初始化时被调用,因此将对话框中的一些初始化代码都添加在此函数中。由于Windows操作系统使用的是图形界面,因此在MFC中,对于每种界面元素的几何大小和位置常使用CPoint类(点)、CSize类(大小)和CRect类(矩形)来描述(以后还会讨论)。代码中,GetClientRect 是对话框基类CWnd的成员函数,用来获取其客户区的位置和大小。对于对话框来说,其客户区是指除标题栏(如果有的话)和边框之外的那
32、部分区域。为了使创建的编辑框占用对话框整个客户区,且又不能覆盖对话框右侧的确定和取消按钮,故将右边的位置在原来的位置上减去100。代码中,CEdit类成员函数Create用来创建编辑框控件,该函数第一个参数用来指定指定控件的样式(样式),其中ES_MULTILINE(以ES_开头的)是编辑框类封装的预定义样式,表示创建的编辑框可以输入多行文本,WS_CHILD(子窗口)、WS_VISIBLE(可见)、WS_TABSTOP(可用Tab键选择)、WS_BORDER(带有边框)等都是CWnd类封装的预定义窗口样式,它们都可以直接引用,当多个样式指定时,需要使用按位或运算符按位或运算符“|”来连接。第
33、二个参数用来指定它在父窗口中的位置和大小,第三个参数用来指定父窗口指针,最后一个参数是指定该控件的标识值。3.2控件的创建和使用方法控件的创建和使用方法 由于编辑框是作为对话框的一个子窗口来创建的,因此WS_CHILD样式是必不可少的,且还要使用WS_VISIBLE使控件在创建后显示出来。(6)编译并运行,这样就可以在创建的编辑框中输入文本了,结果如图3.14所示。图图3.14 Ex_Edit运行结果运行结果3.2控件的创建和使用方法控件的创建和使用方法 3.2.2 控件的消息及消息映射1.控件的消息控件的消息 当控件的状态发生改变时,控件就会向其父窗口发送消息,这个消息称为通知消息通知消息。
34、对于一般控件来说,其通知消息通常是一条WM_COMMAND消息,这条消息的wParam参数的低位字中含有控件标识符,wParam参数的高位字则为通知代码,lParam参数则是指向控件的句柄。而对于有些控件,其通知消息通常是一条WM_NOTIFY消息,这条消息的wParam参数是发送通知消息的控件的标识符,而lParam参数则是指向一个结构指针。2.映射控件消息映射控件消息不管是什么控件消息,一般都可以用MFC ClassWizard对它们加以映射。例如:例例Ex_Btns 一个或多个按钮控件的映射一个或多个按钮控件的映射 (1)创建一个默认的基于对话框应用程序Ex_Btns。(2)在打开的对话
35、框资源模板中,删除“TODO:在这里设置对话控制。”静态文本控件,将确定和取消按钮向对话框左边移动一段位置,然后将鼠标移至对话框资源模板右下角的实心蓝色方块处,拖动鼠标,将对话框资源模板的大小缩小一些。3.2控件的创建和使用方法控件的创建和使用方法 (3)在对话框资源模板的左边依次添加三个按钮控件,保留其默认属性,并将其布局得整齐一些,且上下间隔相同。如图3.15所示。(4)按快捷键Ctrl+W,打开MFC ClassWizard对话框,查看“Class name”列表中是否选择了CEx_BtnsDlg,在IDs列表中选择 IDC_BUTTON1,这是添加第一个按钮后,系统自动为此按钮设置的默
36、认标识符,然后在Messages框中选择BN_CLICKED消息。图图3.15 添加三个按钮添加三个按钮 (5)单击Add Function按钮或双击BN_CLICKED消息,出现“Add Member Function”对话框,在这里可以输入成员函数的名称,系统默认的函数名为OnButton1。如图3.16所示。3.2控件的创建和使用方法控件的创建和使用方法图图3.16 添加按钮消息映射函数添加按钮消息映射函数3.2控件的创建和使用方法控件的创建和使用方法 需要说明的是:不同资源对象(控件、菜单命令等)所产生的消息是不相同的。例如,按钮控件IDC_BUTTON1的消息有两个:BN_CLICK
37、ED和BN_DOUBLECLICKED,分别表示当用户单击或双击该按钮时产生的通知消息。一般不需要对对话框中的确定(OK)与取消(Cancel)按钮进行消息映射,因为系统已自动设置了这两个按钮的动作,当用户单击这两个按钮都将自动关闭对话框,且确定(OK)按钮动作还使得对话框数据有效。(6)单击OK按钮,在MFC ClassWizard的“Member functions”列表中将列出新增加的成员函数。选择此函数,单击Edit Code按钮(或直接在函数名双击鼠标),开发环境的文档窗口中将自动打开该函数所在的源代码文件,并定位到该函数的实现代码处。在此成员函数中 添加下列代码:void CEx_
38、BtnsDlg:OnButton1()MessageBox(你按下了Button1按钮!);3.2控件的创建和使用方法控件的创建和使用方法 (7)编译并运行,当单击Button1按钮时,就会执行OnButton1函数,弹出一个消息对话框,显示“你按下了Button1按钮”。这就是按钮BN_CLICKED消息的映射过程,其他控件的消息也可以类似映射。3.映射控件通用消息映射控件通用消息 上述过程是映射一个控件的某一个消息,事实上也可通过WM_COMMAND消息的映射来处理一个或多个控件的通用消息,如下面的步骤:(1)打开MFC ClassWizard对话框,在“Class name”列表中是否选
39、择了CEx_BtnsDlg,在IDs列表中选择CEx_BtnsDlg,在Messages框中找到并双击OnCommand,这样OnCommand消息函数就添加好了,如图3.17所示。由于OnCommand函数是一个用来处理WM_COMMAND消息的虚函数,而这里添加的OnCommand函数事实上是一个在类中实际调用的函数,可称为实例函数实例函数。这样的映射操作,可以称之为对虚函数对虚函数OnCommand的重载的重载。3.2控件的创建和使用方法控件的创建和使用方法图图3.17 添加添加OnCommand函数重载函数重载3.2控件的创建和使用方法控件的创建和使用方法(2)单击Edit Code按
40、钮(或直接双击函数名),在OnCommand函数中添加下列代码:BOOL CEx_BtnsDlg:OnCommand(WPARAM wParam,LPARAM lParam)WORD nCode=HIWORD(wParam);/控件的通知消息WORD nID=LOWORD(wParam);/控件的ID值if(nID=IDC_BUTTON1)&(nCode=BN_CLICKED)MessageBox(这是在OnCommand处理Button1的结果!);if(nID=IDC_BUTTON2)&(nCode=BN_CLICKED)MessageBox(这是在OnCommand处理Button2的结
41、果!);if(nID=IDC_BUTTON3)&(nCode=BN_CLICKED)MessageBox(这是在OnCommand处理Button3的结果!);return CDialog:OnCommand(wParam,lParam);3.2控件的创建和使用方法控件的创建和使用方法 (3)编译运行并测试。需要说明的是:由于Button1按钮的BN_CLICKED消息处理同时存在两种函数,即OnButton1和OnCommand,因此若单击Button1按钮,系统会先执行哪一个函数呢?测试的结果表明,系统先执行OnCommand函数代码,然后执行OnButton1函数代码。之所 以还能执行O
42、nButton1函数代码,是因为OnCommand函数的最后一句代码“return CDialog:OnCommand(wParam,lParam);”,它将控件的消息交由对话框其他函数处理。3.2.3 控件的数据交换(DDX)和数据校验(DDV)使用MFC ClassWizard可以很方便地为一个控件设置相关联变量并可设置其数据范围。例如,设一对话框中有一个编辑框和一个按钮控件,单击按钮控件,则按钮控件的标题就是编辑框中输入的内容。(这个示例为3部分阐述:控件及控件变量的添加、理解DDX/DDV、使用UpdateData)例例Ex_DDX 控件的控件的DDX和和DDV 1.控件及控件变量的添
43、加控件及控件变量的添加 (1)创建一个默认的基于对话框应用程序Ex_DDX。(2)在打开的对话框资源模板中,删除“TODO:在这里设置对话控制。”静态文本控件,将确定和取消按钮向对话框左边移动一段位置,然后将鼠标移至对话框资源模板右下角的实心蓝色方块处,拖动鼠标,将对话框资源模板的大小缩小一些。图图3.18 添加编辑框和按钮添加编辑框和按钮3.2控件的创建和使用方法控件的创建和使用方法 (3)在对话框资源模板的左边添加一个编辑框控件和一个按钮控件,保留其默认属性,并将其布局得整齐一些。如图3.18所示。(4)按快捷键Ctrl+W,打开MFC ClassWizard对话框,并切换到Member
44、Variables页面,查看“Class name”列表中是否选择了CEx_DDXDlg,此时可以在Control IDs列表中看到刚才添加的控钮和编辑框的标识符IDC_BUTTON1和IDC_EDIT1,如图3.19所示。在Control IDs列表中,选定按钮控件标识符IDC_BUTTON1,双击鼠标左键或单击Add Variable按钮,弹出Add Member Variable对话框,如图3.20所示。图图3.19 “Member Variables”页面页面3.2控件的创建和使用方法控件的创建和使用方法 图图3.20 为按钮控件添加控件变量为按钮控件添加控件变量 图图3.21 为编辑
45、框控件添加控件变量为编辑框控件添加控件变量3.2控件的创建和使用方法控件的创建和使用方法 (6)在Member variable name框中填好与控件相关联的成员变量m_RelBtn,单击OK按钮,又回到MFC ClassWizard对话框的Member Variables页面中,在Control IDs列表中出现刚才添加的控件变量m_RelBtn。(7)在Control IDs列表中,选定编辑框控件标识符IDC_EDIT1,双击鼠标左键或单击Add Variable按钮,弹出Add Member Variable对话框。在Member variable name框中输入控件变量名m_str
46、Edit,保留Category的默认选项Value,在Variable type(变量值类型)中选择该变量的数据类型为CString(字符串类),结果如图3.21所示。(8)单击OK按钮,又回到MFC ClassWizard对话框的Member Variables页面。从图3.20和3.21的不同可以看出:对于大多数控件而言,Category框内可选择Value或Control两种类型。Control所对应的变量类型就是MFC为该控件封装的控件类,Value所对应的是数值类型。但按钮控件变量没有Value类型。不同的控件所提供的关联的数值类型各不相同。例如,对于编辑框来说,Variables
47、type中的数值类型可以有CString(字符串类)、int、UINT、long、DWORD、float、double、BYTE、short、BOOL等。3.2控件的创建和使用方法控件的创建和使用方法 但要注意:DDV/DDX技术中,允许为同一个控件关联多个变量,但必须保证这些变量名是互不相同的,且这些变量在同一个类型不能有多个变量,即在Value和Control类型中各自只能有一个关联变量。另外,通常将Value型控件变量称为控件值控件值变量变量。如果添加的关联变量是一个数值类型,则在MFC ClassWizard对话框的Member Variables页面下方还要求用户输入变量的范围,这就
48、是控件的数据校验设置。在Control IDs列表中,选定编辑框控件标识符IDC_EDIT1,此时就会下方位置处出现Maximum Characters(最大字符个数)框,用来设定该控件变量允许的最大字符个数。输入20,结果如图3.22所示,单击确定按钮。图图3.22 编辑框控件值变量的编辑框控件值变量的DDV设置设置 3.2控件的创建和使用方法控件的创建和使用方法 需要说明的是,若控件值变量的数据类型是整型或浮点型,则DDV框就变成设置最大和最小的两个数值框了。2.理解理解DDX/DDV 打开CEx_DDXDlg类源文件,可以发现MFC ClassWizard对上述操作作了以下三方面的修改:
49、(1)在Ex_DDXDlg.h文件中,添加了控件变量的声明,代码如下面的加粗斜体部分:/Dialog Data /AFX_DATA(CEx_DDXDlg)enum IDD=IDD_EX_DDX_DIALOG;/用枚举定义一个符号常量IDD,使其值等于IDD_EX_DDX_DIALOG CButtonm_RelBtn;CStringm_strEdit;/AFX_DATA (2)在Ex_DDXDlg.cpp文件中的CEx_DDXDlg构造函数实现代码处,添加了控件变量的一些初始代码(加粗斜体部分):3.2控件的创建和使用方法控件的创建和使用方法 CEx_DDXDlg:CEx_DDXDlg(CWnd
50、*pParent/*=NULL*/):CDialog(CEx_DDXDlg:IDD,pParent)/AFX_DATA_INIT(CEx_DDXDlg)m_strEdit=_T();/AFX_DATA_INIT/Note that LoadIcon does not require a subsequent DestroyIcon in Win32 在Ex_DDXDlg.cpp文件中的DoDataExchange函数体内,添加了控件的DDX/DDV代码(加粗斜体部分),它们都是一些以DDV_或DDX_开头的函数调用。void CEx_DDXDlg:DoDataExchange(CDataExc