1.34k likes | 1.51k Views
第 4 章 对话框和常用控件. 对话框是 Windows 应用程序中最重要的用户界面元素之一,是与用户交互的重要 手段。在程序运行过程中,对话框可用于捕捉用户的输入信息或数据。对话框是 一个特殊类型的窗口,任何对窗口进行的操作 ( 如移动、最大化、最小化等 ) 也可 在对话框中实施。一般来说,在对话框中通过各种控件 ( 如按钮、编辑框、列表 框、组合框等 ) 来和用户进行交互,控件是在系统内部定义的用于和用户交互的 基本单元。 4.1 对话框的使用 在 Visual C++ 6.0 应用程序中,使用一个对话框的一般过程是:①添加对话框资
E N D
第4章 对话框和常用控件 • 对话框是Windows应用程序中最重要的用户界面元素之一,是与用户交互的重要 • 手段。在程序运行过程中,对话框可用于捕捉用户的输入信息或数据。对话框是 • 一个特殊类型的窗口,任何对窗口进行的操作(如移动、最大化、最小化等)也可 • 在对话框中实施。一般来说,在对话框中通过各种控件(如按钮、编辑框、列表 • 框、组合框等)来和用户进行交互,控件是在系统内部定义的用于和用户交互的 • 基本单元。 • 4.1 对话框的使用 • 在Visual C++ 6.0应用程序中,使用一个对话框的一般过程是:①添加对话框资 • 源;②设置对话框的属性;③添加和布局控件;④创建对话框类;⑤添加对话框 • 代码;⑥在程序中调用对话框。
资源类别 资源标识符 图4.1 Ex_SDI资源视图 4.1.1 资源与资源标识 • 1. 资源的分类 • 先用MFC AppWizard创建一个单文档应用程序Ex_SDI,然后项目工作区窗口切换到“ResourceView”页面,展开所有的节点,如图4.1所示。
1. 资源的分类 • 可以看出,一个单文档应用程序所使用的资源可分为下列几类: • (1) 快捷键列表(Accelerator)。一系列组合键的集合,被应用程序用来引发一个 • 动作。该列表一般与菜单命令相关联,用来代替鼠标操作。 • (2) 对话框(Dialog)。含有按钮、列表框、编辑框等各种控件的窗口。 • (3) 图标(Icon)。代表应用程序显示在Windows桌面上的位图,它同时有32x32像 • 素和16x16像素两种规格。 • (4) 菜单(Menu)。用户通过菜单可以完成应用程序的大部分操作。 • (5) 字串表(String Table)。应用程序使用的全局字符串或其他标识符。 • (6) 工具栏按钮(Toolbar)。工具栏外观是以一系列具有相同尺寸的位图组成的, • 它通常与一些菜单命令相对应,用以提高用户的工作效率。 • (7) 版本信息(Version)。包含应用程序的版本、用户注册码等相关信息。 • 除了上述常用资源类别外,Visual C++ 6.0应用程序中还可有鼠标指针、HTML • 等,也可以自己添加新的资源类别。
4.1.1 资源与资源标识 • 2. ID标识符 • 一般地,要遵循下列规则: • 在标识符名称中允许使用字母a~z、A~Z、0~9以及下划线。 • 标识符名称不区分大小写字母,如new_idd与New_Idd是相同的标识符。 • 不能以数字开头,如8BIT是不合法的标识符名。 • 除了上述规则外,出于习惯,Visual C++还提供了一些常用的定义标识符名称的前缀供用 • 户使用、参考,见表4.1。
图4.2 “插入资源”对话框 4.1.2 添加对话框资源 • 在一个MFC应用程序中添加对话框资源,通常按下列步骤进行: • (1) 选择“插入”→“资源”菜单,或按快捷键Ctrl+R打开“插入资源”对话框,在对话框中 • 可以看到资源列表中存在Dialog项,若单击Dialog项左边的“+”号,将展开对话框资源 • 的不同类型选项,如图4.2所示,表4.2列出各种类型的对话框资源的不同用途。
4.1.2 添加对话框资源 其中,[新建]按钮是用来创建一个由“资源类型”列表中指定类型的新资源,[定制]按钮是用来创建“资源类型”列表中没有的新类型的资源,[导入]按钮是用于将外部已有的位图、图标、光标或其他定制的资源添加到当前应用程序中。 表4.2 对话框资源类型
控件工具栏 默认标识符 对话框模板 布局工具栏 4.1.2 添加对话框资源 • (2) 对展开的不同类型的对话框资源不作任何选择,选中“Dialog”,单击[新建]按 • 钮,系统就会自动为当前应用程序添加了一个对话框资源,并出现如图4.3所示 • 的界面。 图4.3 添加对话框资源后的开发环境
4.1.3 设置对话框属性 • 在对话框模板处右击鼠标,从弹出的快捷菜单中选择“属性”菜单项,出现如图4.4 • 所示的对话框属性窗口。 图4.4 对话框属性窗口
4.1.3 设置对话框属性 • 可以看出,对话框的属性有General(一般)、Styles(风格)、More Styles(更多风 • 格)、Extended Styles(扩展风格)、More Extended Styles(更多扩展风格)等部 • 分,这里仅介绍最常用的General属性,如表4.3所示。 表4.3 对话框的General属性
4.1.3 设置对话框属性 • 将添加的对话框的属性进行以下3点修改,结果如图4.5所示: • ● 将对话框标识符改成IDD_DIALOG_FIRST; • ● 将对话框标题改为“我的第一个对话框”; • ● 单击[字体]按钮,通过弹出的字体对话框将对话框内的文本设置成“宋体,9” ,以使自己 • 的对话框和Windows中的对话框保持外观上的一致。 图4.5 对话框属性修改后的界面
控件的选择 静态图片 静态文本 编辑框 组框 按钮 复选框 单选框 组合框 列表框 水平滚动条 垂直滚动条 旋转按钮 进展条 滑动条 热键 列表视图 树形视图 标签 动画 复合编辑 日期选择 月历 IP地址 用户定制控件 扩展组合框 4.1.4 添加和布局控件 • 一旦对话框资源被打开或被创建,就会出现对话框编辑器,通过它可以在对话框中进行控 • 件的添加和布局等操作。 • 1. 控件的添加 • 对话框编辑器最初打开时,控件工具栏是随之出现的,利用此工具栏中的各个按钮可以顺 • 利完成控件的添加。图4.6说明了各个按钮所对应的控件类型。 图4.6 控件工具栏和各按钮含义
4.1.4 添加和布局控件 • 在对话框中添加一个控件的方法有下列几种: • ● 在控件工具栏中单击某控件,此时的鼠标箭头在对话框内变成“十”字形状;在 • 对话框指定位置单击鼠标左键,则此控件被添加到对话框的相应位置,再拖动刚 • 添加控件的选择框可改变其大小和位置。 • ● 在控件工具栏中单击某控件,此时的鼠标箭头对话框内变成“十”字形状;在指 • 定位置处单击鼠标左键不放,拖动鼠标至满意位置,释放鼠标键。 • ● 用鼠标左键点中控件工具栏中的某控件,并按住鼠标左键不放;在移动鼠标到 • 对话框的指定位置的过程中,用户会看到一个虚线框,下面带有该控件的标记; • 释放鼠标左键,新添加的控件立即出现在对话框中。
4.1.4 添加和布局控件 • 2. 控件的选取 • 控件的删除、复制和布局操作一般都要先选取控件,若选取单个控件,则可以下 • 列方法: • ● 用鼠标直接选取。首先保证在控件工具栏中的选择按钮()是被选中的,然后移 • 动鼠标指针至指定的控件上,单击鼠标左键即可。 • ● 用助记符来选取。如果控件的标题中带有下划线的字符,这个字符就是助记 • 符,选择时直接按下该助记符键或“Alt+助记符”组合键即可。 • ● 用Tab键选取。在对话框编辑器中,系统会根据控件的添加次序自动设置相应 • 的Tab键次序。利用Tab键,用户可在对话框内的控件中进行选择。每按一次Tab • 键依次选取对话框中的下一个控件,若按住Shift键,再单击Tab键则选取上一个 • 控件。 • 对于多个控件的选取,可采用下列方法: • ● 先在对话框内按住鼠标左键不放,拖出一个大的虚框,然后释放鼠标,则被该 • 虚框所包围的控件都将被选取。 • ● 先按住Shift键不放,然后用鼠标选取控件,直到所需要的多个控件选取之后再 • 释放Shift键。若在选取时,对已选取的控件再选取一下,则取消该控件选取。
(b) 图4.7 单个控件和多个控件的选择框 (a) 4.1.4 添加和布局控件 • 需要注意的是: • (1) 一旦单个控件被选取后,其四周由选择框包围着,选择框上还有几个(通常是 • 八个)蓝色实心小方块,拖动它可改变控件的大小,如图4.7(a)所示。 • (2) 多个控件被选取后,其中只有一个控件的选择框有几个蓝色实心小方块,这 • 个控件称为主要控件,而其他控件的选择框的小方块是空心的。如图4.7(b)所示。
4.1.4 添加和布局控件 • 3. 控件的删除、复制和布局 • 当单个控件或多个控件被选取后,按方向键或用鼠标拖动控件的选择框可移动控 • 件。若在鼠标拖动过程中还按住Ctrl键则复制控件。若按Del键可将选取的控件删 • 除。当然还有其他一些编辑操作,但这些操作方法和一般的文档编辑器基本相 • 同,这里不再重复。 • 对于控件的布局,对话框编辑器中提供了控件布局工具栏,如图4.8所示,它可 • 以自动地排列对话框内的控件,并能改变控件的大小。 图4.8 控件布局工具栏
3. 控件的删除、复制和布局 • 与布局工具相对应的菜单命令在“编排”菜单下,而且大部分命令均有相应的快捷 • 键,如图4.9所示。表4.4还列出菜单命令及其相应的功能与快捷键描述。“编排” • 菜单不是在Visual C++ 6.0开发环境一开始就出现的,而是随着对话框编辑器的 • 打开而显示的。 表4.4 “编排”菜单命令的快捷键及功能描述 图4.9 “编排”菜单命令项
4.1.4 添加和布局控件 • 4. 测试对话框 • “编排”菜单下的Test命令或布局工具栏上的测试按钮是用来模拟所编辑的对话框的运行情 • 况,帮助用户检验对话框是否符合用户的设计要求以及控件功能是否有效等。 • 5. 操作示例 • 下面来向对话框添加一个静态文本控件。一个静态文本控件就是一个文本标签,如图4.10 • 所示。右击添加的控件,从弹出的快捷菜单中选择“属性”,出现如图4.11所示的属性对话 • 框。 图4.11 静态文本控件的属性对话框 图4.10 添加的静态文本控件
4.1.5 创建对话框类 • 在对话框资源模板的空白区域(没有其他元素或控件)内双击鼠标,将弹出如图 • 4.12所示的对话框,询问是否为对话框资源创建一个新类。 • 单击[OK]按钮,将弹出如图4.13所示的New Class对话框。在Name框中输入类 • 名CFirstDlg。Base class和Dialog ID内容是由系统自动设置的,一般无需修改。 • 从Base class框的内容可以看出,用户对话框类是从基类CDialog派生而来的。 • 单击[OK]按钮,一个基于对话框资源模板的对话框类CFirstDlg就创建好了。此 • 时,出现MFC ClassWizard(MFC类向导)对话框。 图4.12 “Adding a Class”对话框 图4.13 “New Class”对话框
4.1.6 添加对话框代码 • 在MFC ClassWizard对话框,查看“Class name”列表中是否选择了CFirstDlg,若 • 不是,则在IDs列表中选择CFirstDlg。 • 在Messages框中找到并选定WM_INITDIALOG消息,如图4.14。 图4.14 “MFC ClassWizard”对话框
4.1.6 添加对话框代码 • 在Member functions列表框中选择刚添加的OnInitDialog函数,单击[Edit Code]按钮(或 • 直接在函数名双击鼠标),将自动出现该函数代码编辑窗口,在此函数中添加下列代码: • BOOL CFirstDlg::OnInitDialog() • { • CDialog::OnInitDialog(); • // TODO: Add extra initialization here • CStatic* pWnd = (CStatic*)GetDlgItem(IDC_STATIC_1); • pWnd->SetWindowText("这是我的第一个对话框!"); • return TRUE; // return TRUE unless you set the focus to a control • // EXCEPTION: OCX Property Pages should return FALSE • } • 代码中,CStatic是静态文本控件的MFC类,SetWindowText是CWnd的一个成员函数, • 用来设置窗口的文本内容,由于控件类是CWnd的子类(派生类),因此可以使用基类的 • SetWindowText来改变静态文本控件显示的内容。GetDlgItem也是CWnd类的一个成员 • 函数,用来获得对话框中控件(参数是控件的ID标识符,这里是IDC_STATIC_1)的窗口 • 指针。
4.1.7 在程序中调用对话框 • 在项目工作区窗口中选择ResourceView页面,双击资源“Menu”项中的 • IDR_MAINFRAME,则菜单编辑器窗口出现在主界面的右边,相应的Ex_SDI项目的菜单 • 资源被显示出来,在菜单的最右一项,Visual C++为用户留出了一个空位置,用来输入新 • 的菜单项,如图4.15所示。 菜单的空位置 图4.15 Ex_SDI菜单资源
4.1.7 在程序中调用对话框 • (2) 在菜单的空位置上双击鼠标左键,则出现它的属性对话框,在标题框中输入“测试 • (&T)”,结果如图4.16所示,其中符号&用来其后面的字符作为该菜单项的助记符,这样当 • 按住“Alt”键不放,再敲击该助记符键时,对应的菜单项就会被选中,或在菜单打开时,直 • 接按相应的助记符键,对应的菜单项也会被选中。 子菜单的空位置 保存可见按钮 图4.16 Ex_SDI菜单资源
4.1.7 在程序中调用对话框 • (3) 单击菜单属性对话框中的“保存可见”(Keep Visible)按钮,使此属性对话框一 • 直可见。单击“测试”菜单项下方的空位置,在属性对话框中,输入标题“对话框 • (&D)”,在ID框输入该菜单项的资源标识:ID_TEST_DLG,结果如图4.17所示, • 单击属性对话框右上角的关闭按钮。 • (4) 单击“测试”菜单项并按住鼠标左键不放,移动鼠标,将“测试”菜单项移到“查 • 看”和“帮助”菜单项之间,然后释放鼠标。结果如图4.18所示。 图4.17 修改菜单项属性 图4.18 菜单项“对话框”拖放后的位置
4.1.7 在程序中调用对话框 • (5) 按Ctrl+W快捷键,弹出MFC ClassWizard对话框。在Message Maps页面 • 中,从Class name列表中选择CMainFrame,在IDs列表中选择ID_TEST_DLG, • 然后在Messages框中选择COMMAND消息。 • (6) 单击[Add Function]按钮或双击COMMAND消息,出现Add Member Function • 对话框,输入成员函数的名称。系统默认的函数名为OnTestDlg,如图4.19所 • 示。该函数是对菜单项ID_TEST_DLG的映射,也就是说,当在应用程序运行 • 时,用户选择“测试”→“对话框”,则该函数OnTestDlg被调用,执行函数中的代 • 码。 图4.19 添加成员函数
4.1.7 在程序中调用对话框 • (7) 单击[OK]按钮,在ClassWizard的Member functions列表中将列出新增加的成 • 员函数。选择此函数,单击[Edit Code]按钮(或直接双击函数名),在此成员函数 • 中添加下列代码: • void CMainFrame::OnTestDlg() • { • CFirstDlg dlg; // 定义对话框类对象 • dlg.DoModal(); // 显示对话框 • } • 代码中,DoModal是CDialog基类成员函数,用来将对话框按模式方式来显示。 • (8) 在OnTestDlg函数的实现文件MainFrm.cpp的前面添加CFirstDlg类的包含语 • 句,即: • #include "Ex_SDI.h" • #include "MainFrm.h" • #include "FirstDlg.h"
图4.20 对话框的显示 4.1.7 在程序中调用对话框 • (9) 编译并运行。在应用程序菜单上,选择“测试”→“对话框”菜单项,将出现如图 • 4.20的对话框,这个对话框就是刚才添加的对话框。
4.1.8 使用无模式对话框 • 对话框有两种类型,一种是模式对话框,另一是无模式对话框。 • 1. 模式对话框 • 所谓“模式对话框”是指当对话框被弹出,用户必须在对话框中作出相应的操作, • 在退出对话框之前,对话框所在应用程序的其它操作不能继续执行。 • 一般情况下,模式对话框会有[OK](确定)和[Cancel](取消)按钮。单出[OK]按钮, • 系统认定用户在对话框中的选择或输入有效,对话框退出;单击[Cancel]按钮, • 对话框中的选择或输入无效,对话框退出,程序恢复原有状态。 • 模式对话框的应用范围较广,上面示例中的对话框和平常所见到的大多数对话框 • 都是模式对话框。 • 2. 无模式对话框 • 所谓“无模式对话框”是指当对话框被弹出后,一直保留在屏幕上,用户可继续在 • 对话框所在的应用程序中进行其它操作;当需要使用对话框时,只需象激活一般 • 窗口一样单击对话框所在的区域即可激活。
4.1.8 使用无模式对话框 • 下面在单文档应用程序Ex_SDI中创建并使用无模式对话框,其步骤如下: • (1) 在该项目中添加一个对话框资源,将其标识符设为IDD_DIALOG_SECOND, • 标题设为“无模式对话框”,对话框字体和大小设为“宋体,9号”。 • (2) 为IDD_DIALOG_SECOND对话框资源创建一个对话框类CSecondDlg。 • (3) 按Ctrl+W快捷键打开MFC ClassWizard,从“Class name”列表中选择 • CSecondDlg,在IDs列表中选择IDOK,它是对话框中[OK]按钮的标识符,然后 • 在Messages框中选择BN_CLICKED(单击按钮)消息,单击[Add Function]按钮或 • 双击BN_CLICKED消息,出现“Add Member Function”对话框以输入成员函数的 • 名称,保留系统默认的函数名为OnOK,如图4.21所示。该函数是对[OK]按钮单 • 击消息的映射,即当用户单击此对话框中的[OK]按钮时,OnOK函数被执行。 • (4) 修改CSecondDlg::OnOK函数中的代码。 • void CSecondDlg::OnOK() • { • DestroyWindow(); // 终止对话框显示 • delete this; // 删除对话框,释放内存空间 • } • 代码中,DestroyWindow是对话框基类CWnd的一个成员函数,用来终止窗口。
4.1.8 使用无模式对话框 • (5) 用MFC ClassWizard来添加[Cancel]按钮(标识符为IDCANCEL)的BN_CLICKED消 • 息映射,并修改其映射函数CSecondDlg::OnCancel的代码。 • void CSecondDlg::OnCancel() • { • DestroyWindow(); • delete this; • } • (6) 将项目工作区切换到ClassView(类视图)页面,展开CMainFrame类的所有成员, • 双击OnTestDlg就会在文档窗口中自动定位到该函数的实现代码处,将其修改成下列 • 代码: • void CMainFrame::OnTestDlg() • { • CSecondDlg *pDlg = new CSecondDlg; // 使用new来为对话框分配内存空间 • pDlg->Create( IDD_DIALOG_SECOND ); // 创建对话框 • pDlg->ShowWindow( SW_NORMAL ); // 显示对话框 • } • 代码中,Create函数可以用来以一个对话框资源来创建对话框,ShowWindow是 • CWnd一个成员函数,用来显示对话框,SW_NORMAL用来指定将窗口显示成一般常 • 用的状态。
4.1.8 使用无模式对话框 • (7) 在文件MainFrm.cpp的前面添加CSecondDlg类的包含语句,即: • #include "FirstDlg.h" • #include "SecondDlg.h" • (8) 编译并运行。在应用程序菜单上,多次选择“测试”→“对话框”菜单项,将会在 • 同一个位置中出现多个对话框,拖动这些对话框到适当位置,如图4.22所示。 图4.22 无模式对话框显示的结
4.2 控件的创建和使用方法 • 控件是在系统内部定义的能够完成特定功能的控制程序单元。在应用程序中使用 • 控件不仅简化了编程,还能完成常用的各种功能。为了更好地发挥控件作用,用 • 户还必须理解和掌握控件的属性、消息以及创建和使用的方法。 • 4.2.1 控件的创建方法 • 控件的创建方式有以下两种:一种是在对话框模板中用编辑器指定控件,也就是 • 说,将控件的父窗口指定为对话框,这样做的好处是明显的,因为当应用程序启 • 动该对话框时,Windows系统就会为对话框创建控件;而当对话框消失时,控件 • 也随之清除。另一种方式是将控件看作是任一窗口的子窗口,并通过调用相应的 • Create函数来创建。
4.2.1 控件的创建方法 • [例Ex_DlgCtrls] 使用控件的编程方式来创建一个按钮 • (1) 选择“文件”→“新建”菜单,在弹出的新建对话框的项目类型列表中选择MFC • AppWizard(exe)类型,在工程框中输入项目名Ex_DlgCtrls,结果如图4.23所示。 图4.23 MFC AppWizard的“新建”对话框
4.2.1 控件的创建方法 • (2) 单击[确定]按钮,在出现的“Step 1”对话框中选择“基本对话”应用程序类型, • 单击[完成]按钮,创建一个默认的基于对话框的应用程序项目。 • (3) 将项目工作区切换到ClassView页面,展开CEx_DlgCtrlsDlg类,右击 • CEx_DlgCtrlsDlg类名,弹出如图4.24所示的快捷菜单。 图4.24 弹出的快捷菜单
4.2.1 控件的创建方法 • 4) 从快捷菜单中选择Add Member Variable(添加成员变量),在出现的对话框中 • 定义一个CButton类对象m_btnWnd,通常以“m_”来作为变量的开头,表示“成 • 员”(member)的意思。如图4.25所示,单击[OK]按钮。 图4.25 添加成员变量
4.2.1 控件的创建方法 • (5) 在项目工作区窗口的ClassView页面中,双击OnInitDialog函数名,在该函数 • 中添加下列代码: • BOOL CEx_DlgCtrlsDlg::OnInitDialog() • { • CDialog::OnInitDialog(); • … • m_btnWnd.Create("你好", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, • CRect(20, 20, 120, 60), this, 201); // 创建 • CFont *font = this->GetFont(); // 获取对话框的字体 • m_btnWnd.SetFont(font); // 设置控件字体 • return TRUE; // return TRUE unless you set the focus to a control • } • 由于OnInitDialog函数在对话框初始化时被调用,因此将对话框中的一些初始化 • 代码都添加在此函数中。代码中,Create用来创建一个按钮控件,该函数第一个 • 参数用来指定该按钮的标题,第二个参数用来指定控件的风格,第三个参数用来 • 指定它在父窗口中的位置和大小,第四个参数用来指定父窗口指针,最后一个参 • 数是指定该控件的标识值。
图4.26 控件创建的结果 4.2.1 控件的创建方法 • (6) 编译并运行,结果如图4.26所示。
4.2.2 控件的消息及消息映射 • 当控件的状态发生改变时,控件就会向其父窗口发送消息,这个消息称为“通知 • 消息”。对于每个消息,系统都会用一个MSG结构来记录,MSG具有下列结构: • typedef struct tagMSG • { // msg • HWND hwnd; // 接收到消息的窗口句柄 • UINT message; // 消息 • WPARAM wParam; // 消息的附加信息,它的含义取决于message • LPARAM lParam; // 消息的附加信息,它的含义取决于message • DWORD time; // 消息传送时的时间 • POINT pt; // 消息传送时,光标所在的屏幕坐标 • } MSG; • 对于一般控件来说,其通知消息通常是一条WM_COMMAND消息,这条消息的 • wParam参数的低位字中含有控件标识符,wParam参数的高位字则为通知代 • 码,lParam参数则是指向控件的句柄。 • 而对于有些控件,其通知消息通常是一条WM_NOTIFY消息,这条消息的 • wParam参数是发送通知消息的控件的标识符,而lParam参数则是指向一个结构 • 指针。
4.2.2 控件的消息及消息映射 • 1. 映射控件消息 • 在MFC中,映射一个控件消息是非常简便的。例如下面的步骤是用来映射按钮命 • 令消息。打开Ex_DlgCtrls应用程序项目。将项目工作区窗口切换到ResourseView页面,双击Dialog资源下的标识IDD_EX_DLGCTRLS_DIALOG,打开该对话框资源模板。 • 删除“TODO: 在这里设置对话控制。”控件,添加一个按钮控件,保留其默认属 • 性。如图4.27所示。 图4.27 添加一个按钮
4.2.2 控件的消息及消息映射 • (4) 按快捷键Ctrl+W,打开MFC ClassWizard对话框,查看“Class name”列表中是否选择了 • CEx_DlgCtrlsDlg,在IDs列表中选择IDC_BUTTON1,这是添加按钮后,系统自动为此按 • 钮设置的默认标识符,然后在Messages框中选择BN_CLICKED消息。 • (5) 单击[Add Function]按钮或双击BN_CLICKED消息,出现“Add Member Function”对话 • 框,在这里可以输入成员函数的名称,系统默认的函数名为OnButton1。如图4.28所示。 图4.28 添加按钮消息映射函数
4.2.2 控件的消息及消息映射 • (6) 单击[OK]按钮,在MFC ClassWizard的“Member functions”列表中将列出新增 • 加的成员函数。选择此函数,单击[Edit Code]按钮(或直接在函数名双击鼠标), • 开发环境的文档窗口中将自动打开该函数所在的源代码文件,并定位到该函数的 • 实现代码处。在此成员函数中添加下列代码: • void CEx_DlgCtrlsDlg::OnButton1() • { • MessageBox("你按下了\"Button1\"按钮!"); • } • (7) 编译并运行,当单击[Button1]按钮时,就会执行OnButton1函数,弹出一个 • 消息对话框。 • 这就是按钮BN_CLICKED消息的映射过程,其他控件的消息也可以类似操作。
4.2.2 控件的消息及消息映射 • 2. 映射控件通用消息 • 上述过程是映射一个控件的某一个消息,事实上也可通过WM_COMMAND消息的映射 • 来处理一个或多个控件的通用消息,如下面的步骤: • 打开MFC ClassWizard对话框,在“Class name”列表中是否选择了CEx_DlgCtrlsDlg, • 在IDs列表中选择CEx_DlgCtrlsDlg,在Messages框中找到并双击OnCommand,这样 • OnCommand消息函数就添加好了,如图4.29所示。 图4.29 添加OnCommand函数重载
4.2.2 控件的消息及消息映射 • (2) 在OnCommand函数中添加下列代码: • BOOL CEx_DlgCtrlsDlg::OnCommand(WPARAM wParam, LPARAM lParam) • { • WORD nCode = HIWORD(wParam); // 控件的通知消息 • WORD nID = LOWORD(wParam); // 控件的ID值 • if ((nID == 201)&&(nCode == BN_CLICKED)) • MessageBox("你按下了\"你好\"按钮!"); • if ((nID == IDC_BUTTON1)&&(nCode == BN_CLICKED)) • MessageBox("这是在OnCommand处理的结果!"); • return CDialog::OnCommand(wParam, lParam); • } • 注意:第一条if语句中,201是前面用Create创建按钮时指定的标识值。 • (3) 编译并运行。当单击如前图4.27所示的[Button1]按钮时,就会弹出一个消息 • 对话框。
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • 使用MFC ClassWizard可以很容易地为一个控件定义关联变量并可设置其数据范 • 围。例如,下面的步骤是为CEx_DlgCtrlsDlg类的按钮控件IDC_BUTTON1添加 • 并使用其关联变量m_RelBtn。 • (1) 打开MFC ClassWizard,并切换到Member Variables页面,如图4.30所示。 图4.30 “Member Variables”页面
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • (2) 选定Class name为CEx_DlgCtrlsDlg,然后在Control IDs列表中,选定所要 • 关联的控件ID标识符IDC_BUTTON1,双击鼠标左键或单击[Add Variable]按 • 钮,弹出Add Member Variable对话框,在对话框设置变量的名称、类别和数据 • 类型,如图4.31所示。 图4.31 “Add Member Variable”对话框
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • (3) 在Member variable name框中填好与控件相关联的成员变量m_RelBtn,单击 • [OK]按钮,又回到MFC ClassWizard对话框的Member Variables页面中,在 • Control IDs列表中出现刚才添加的控件关联变量(或直接称之为“控件变量”)。 • (4) 单击[确定]按钮后,打开CEx_DlgCtrlsDlg类源文件,可以发现MFC • ClassWizard对上述操作作了以下三方面的修改。 • ●在Ex_DlgCtrlsDlg.h文件中,添加控件关联变量的声明,代码如下面的加粗部 • 分: • // Dialog Data • //{{AFX_DATA(CEx_DlgCtrlsDlg) • enum { IDD = IDD_EX_DLGCTRLS_DIALOG }; // 枚举类型 • CButton m_RelBtn; • CString m_strEdit; • //}}AFX_DATA
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • ●在Ex_DlgCtrlsDlg.cpp文件中的CEx_DlgCtrlsDlg构造函数实现代码处,添加了 • 控件变量的一些初始代码: • CEx_DlgCtrlsDlg::CEx_DlgCtrlsDlg(CWnd* pParent /*=NULL*/) • : CDialog(CEx_DlgCtrlsDlg::IDD, pParent) • { • //{{AFX_DATA_INIT(CEx_DlgCtrlsDlg) • m_strEdit = _T(""); • //}}AFX_DATA_INIT • … • }
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • ●在Ex_DlgCtrlsDlg.cpp文件中的DoDataExchange函数体内,添加了控件的 • DDX/DDV代码,它们都是一些以DDV_或DDX_开头的函数调用。 • void CEx_DlgCtrlsDlg::DoDataExchange(CDataExchange* pDX) • { • CDialog::DoDataExchange(pDX); // 调用此函数作为DDX的开始 • //{{AFX_DATA_MAP(CEx_DlgCtrlsDlg) • DDX_Control(pDX, IDC_BUTTON1, m_RelBtn); • DDX_Text(pDX, IDC_EDIT1, m_strEdit); // 将IDC_EDIT1与m_strEdit进行数据交换 • DDV_MaxChars(pDX, m_strEdit, 20); // 校验m_strEdit的最大字符个数不超过20 • //}}AFX_DATA_MAP • }
4.2.3 控件的数据交换(DDX)和数据校验(DDV) • (5) 当为一个控件定义一个关联的数据变量后,就可以使用CWnd::UpdateData函 • 数实现控件数据的输入和读取。例如,将CEx_DlgCtrlsDlg::OnButton1修改成下 • 列代码: • void CEx_DlgCtrlsDlg::OnButton1() • { • UpdateData(); // 默认参数值是TRUE • m_RelBtn.SetWindowText(m_strEdit); • } • 代码中,UpdateData函数只有一个为TRUE或FALSE的参数。当调用 • UpdateData(FALSE)时,数据由控件相关联的成员变量向控件传输,当调用 • UpdateData(TRUE)或不带参数的UpdateData时,数据从控件向相关联的成员变 • 量复制。
图4.33 使用控件的数据成员变量 4.2.3 控件的数据交换(DDX)和数据校验(DDV) • (6) 运行该程序,当在编辑框中输入“Hello”后,单击[Button1]按钮,OnButton1 • 函数中的UpdateData将编辑框内容保存到m_strEdit变量中,从而执行下一条语 • 句后按钮的名称就变成了编辑框控件中的内容“Hello”,其结果如图4.33所示