第14单元对话框 第14单元对话框 教学目标 介绍对话框的概念和用法 学习要求 理解对话框、对话框模板和控件的概念,以及数据交换和验证机制,可编写使用对话框 的程序。 授课內容 对话框是一种特殊的窗口,主要功能是输岀信息和接收用户的输入。对话框与控件是密 不可分的,在每个对话框内一般都有一些控件,对话框依靠这些控件与用户进行交流信息 本单元主要介绍对话框,控件在第15单元中介绍 141对话框(Daog) 对话框( Dialog)实际上也是一个窗口。在MFC中,对话框的功能被封装在 CDialog 类中, CDialog类是CWnd类的派生类 对话框分为模态对话框和非模态对话框两种。模态对话框垄断了用户的输入,当一个模 态对话框打开时,用户只能与该对 话框进行交互,而其它用户界面对 是寻 1201 回团酬 象收不到用户的输入信息(如键盘口1nbng ]1201.cpt 和鼠标消息)。平时我们所遇到的量01 1201.ds 大部分对话框都是模态对话框,例国1201adb 如通过 File/Open命令打开的文件 打开@ 搜索对话框就是模态对话框(图文件型①匾 14-1)。非模态对话框类似普通的 窗口,并不垄断用户的输入。在非 图14-1文件搜索对话框 模式对话框打开时,用户随时可用 鼠标点击等手段激活其他窗口对象,操纵完毕后再回到本对话框。非模式对话框的典型例子 是 Microsoft word中的搜索对话框,打开搜索对话框后,用户仍可与其它窗口对象进行交互, 可以一边搜索,一边修改文章,非常方便
第 14 单元 对话框 275 第 14 单元 对话框 教学目标 介绍对话框的概念和用法。 学习要求 理解对话框、对话框模板和控件的概念,以及数据交换和验证机制,可编写使用对话框 的程序。 授课内容 对话框是一种特殊的窗口,主要功能是输出信息和接收用户的输入。对话框与控件是密 不可分的,在每个对话框内一般都有一些控件,对话框依靠这些控件与用户进行交流信息。 本单元主要介绍对话框,控件在第 15 单元中介绍。 14.1 对话框(Dialog) 对话框(Dialog)实际上也是一个窗口。在 MFC 中,对话框的功能被封装在 CDialog 类中,CDialog 类是 CWnd 类的派生类。 对话框分为模态对话框和非模态对话框两种。模态对话框垄断了用户的输入,当一个模 态对话框打开时,用户只能与该对 话框进行交互,而其它用户界面对 象收不到用户的输入信息(如键盘 和鼠标消息)。平时我们所遇到的 大部分对话框都是模态对话框,例 如通过 File/Open 命令打开的文件 搜索对话框就是模态对话框(图 14-1)。非模态对话框类似普通的 窗口,并不垄断用户的输入。在非 模式对话框打开时,用户随时可用 鼠标点击等手段激活其他窗口对象,操纵完毕后再回到本对话框。非模式对话框的典型例子 是 Microsoft Word 中的搜索对话框,打开搜索对话框后,用户仍可与其它窗口对象进行交互, 可以一边搜索,一边修改文章,非常方便。 图 14-1 文件搜索对话框
第14单元对话框 本节介绍模态对话框,非模态对话框将在145节介绍。 在程序中使用模态对话框有两个步骤: 1.在视图类或框架窗口类的消息响应函数(如鼠标消息或菜单选项的命令消息响应函 数)中说明一个对话框类的对象(变量) 2.调用 CDialog: DoModal()成员函数 DoModal()函数负责对模态话框的创建和撤销。在创建对话框时, DoModal()函数 的任务包括载入对话框模板资源、调用 OnInitDialog()函数初始化对话框和将对话框显示 在屏幕上。完成对话框的创建后, DoModal()函数启动一个消息循环,以响应用户的输入 由于该消息循环截获了几乎所有的输入消息,使主消息循环收不到对对话框的输入,致使用 户只能与模态对话框进行交互,而其它用户界面对象收不到输入信息。 如果用户在对话框内点击了标识符为IDOK的按钮(通常该按钮的标题是“确定”或 OK”),或者按了回车键,则 CDialog:: OnOK()函数会被调用。OnOK()函数首先调 用 UpdateData()函数将数据从控件传给对话框成员变量,然后调用 CDialog: Enddialog() 函数关闭对话框。关闭对话框后, DoModal()函数会返回值IDOK。 如果用户点击了标识符为 IDCANCEL的按钮(通常其标题为“取消”或“ Cancel”) 或按了ESC键,则会导致对 CDialog: On Cancel()函数的调用。该函数只调用 CDialog: Enddialog()函数关闭对话框。关闭对话框后, Do Modal()函数会返回 IDCANCELO 在应用程序中,可根据 DoModal()函数的返回值是IDOK还是 IDCANCEL来判断用 户是确定还是取消了对对话框的操作 从MFC编程的角度来看,一个对话框由两部分组成: 1.对话框模板资源:对话框模板用于指定对话框的形状、所用控件及其分布, Developer Studio根据对话框模板来创建对话框对象 2.对话框类:对话框类用来实现对话框的功能。由于各应用程序中的对话框具体功能 不同,因此一般要从 CDialog类中派生一个新类,以便添加特定的数据成员和成员函数。 相应地,对话框的设计也包括对话框模板的设计和对话框类的设计两个主要方面。具体 来说,应有以下步骤: 1.向项目中添加对话框模板资源; 2.编辑对话框模板资源,加入所需的控件 3.从 CDialog类派生对话框类,加入与各控件对应的数据成员 4.在框架窗口类或视图类的菜单选项、鼠标事件或其他消息响应函数中添加对话框对 象的应用代码。 向项目中添加对话框模板资源和编辑对话框模板资源的方法在14.7中介绍,下面主要 说明对话框类的设计方法,这包括以下几项工作: 1.从 CDialog类派生一个对话框类,并通过对话框模板资源的ID建立它们之间的对应 关系 2.为对话框类添加与各控件相对应的成员变量
第 14 单元 对话框 276 本节介绍模态对话框,非模态对话框将在 14.5 节介绍。 在程序中使用模态对话框有两个步骤: 1.在视图类或框架窗口类的消息响应函数(如鼠标消息或菜单选项的命令消息响应函 数)中说明一个对话框类的对象(变量); 2.调用 CDialog::DoModal()成员函数。 DoModal()函数负责对模态话框的创建和撤销。在创建对话框时,DoModal()函数 的任务包括载入对话框模板资源、调用 OnInitDialog()函数初始化对话框和将对话框显示 在屏幕上。完成对话框的创建后,DoModal()函数启动一个消息循环,以响应用户的输入。 由于该消息循环截获了几乎所有的输入消息,使主消息循环收不到对对话框的输入,致使用 户只能与模态对话框进行交互,而其它用户界面对象收不到输入信息。 如果用户在对话框内点击了标识符为 IDOK 的按钮(通常该按钮的标题是“确定”或 “OK”),或者按了回车键,则 CDialog::OnOK()函数会被调用。OnOK()函数首先调 用 UpdateData()函数将数据从控件传给对话框成员变量,然后调用 CDialog::EndDialog() 函数关闭对话框。关闭对话框后,DoModal()函数会返回值 IDOK。 如果用户点击了标识符为 IDCANCEL 的按钮(通常其标题为“取消”或“Cancel”), 或按了 ESC 键, 则会导 致对 CDialog::OnCancel( )函数 的调 用。该 函数 只调用 CDialog::EndDialog()函数关闭对话框。关闭对话框后,DoModal()函数会返回 IDCANCEL。 在应用程序中,可根据 DoModal()函数的返回值是 IDOK 还是 IDCANCEL 来判断用 户是确定还是取消了对对话框的操作。 从 MFC 编程的角度来看,一个对话框由两部分组成: 1.对话框模板资源:对话框模板用于指定对话框的形状、所用控件及其分布,Developer Studio 根据对话框模板来创建对话框对象。 2.对话框类:对话框类用来实现对话框的功能。由于各应用程序中的对话框具体功能 不同,因此一般要从 CDialog 类中派生一个新类,以便添加特定的数据成员和成员函数。 相应地,对话框的设计也包括对话框模板的设计和对话框类的设计两个主要方面。具体 来说,应有以下步骤: 1.向项目中添加对话框模板资源; 2.编辑对话框模板资源,加入所需的控件; 3.从 CDialog 类派生对话框类,加入与各控件对应的数据成员; 4.在框架窗口类或视图类的菜单选项、鼠标事件或其他消息响应函数中添加对话框对 象的应用代码。 向项目中添加对话框模板资源和编辑对话框模板资源的方法在 14.7 中介绍,下面主要 说明对话框类的设计方法,这包括以下几项工作: 1.从 CDialog 类派生一个对话框类,并通过对话框模板资源的 ID 建立它们之间的对应 关系; 2.为对话框类添加与各控件相对应的成员变量;
第14单元对话框 3.为对话框进行初始化工作; 4.增加对控件通知消息的处理 例141为例9-1的吹泡泡程序加一版权( About)对话框 说明: Windows应用程序大都有一版权对话框,提供软件的版本号、出品商和版 权说明等信息。版权对國 区 话框可以通过主菜单上「MM习● 的“关于.”菜单选项 的③回日萬2·g,国曾%四 d msEX: Fol 调出,也可以通过鼠标 E IDD DIALOGI 右键调出。本例采用后 吹泡泡程序 Version10 一种方法。 Copyright 2000 首先建立Win32 四安交通大学计机教学实验中心 Application空项目,为 项目建立C++ Source ral Styles I Extended Styles I esource Caption:计算机数芋买验中心 文件(建立后关闭) F Visible F Group Disabled「 Tab stop 并将项目设置为使用 MFC 向项目中添加一个 图14-2编辑吹泡泡程序的版权对话框 对话框模板资源(通过 菜单选项 Insert/ Resource.),将其 Caption改为“关于吹泡泡程序”。然后利用对话框编 辑器添加3个静态文本控件( Static Text)说明版本信息并删除“ Cancel”按钮,见图14-2 然后修改例9-1的程序,加入以下内容: 程序 1.在程序首部加上文件包含命令 # include“ resource.h 2.在框架窗口类之前加入从 CDialog类派生的对话框类: /对话框类 class CAboutDlg: public CDialog CAboutDlgo enum [IDD= IDD DIALOG1] inline CAboutDlg: CAboutDlg(: CDialog(CAboutDlg:: IDD) 3.在框架窗口类中添加响应鼠标右键消息的代码,包括消息响应函数说明、消息响应 宏和消息响应函数定义。鼠标右键消息响应函数为
第 14 单元 对话框 277 3.为对话框进行初始化工作; 4.增加对控件通知消息的处理。 [例 14-1] 为例 9-1 的吹泡泡程序加一版权(About)对话框。 说 明:Windows 应用程序大都有一版权对话框,提供软件的版本号、出品商和版 权说明等信息。版权对 话框可以通过主菜单上 的“关于… ”菜单选项 调出,也可以通过鼠标 右键调出。本例采用后 一种方法。 首先建立 Win32 Application 空项目,为 项目建立 C++ Source File 和 Resource Script 文件(建立后关闭), 并将项目设 置为使用 MFC。 向项目中添加一个 对话框模板资源(通过 菜单选项 Insert/Resource…),将其 Caption 改为“关于吹泡泡程序”。然后利用对话框编 辑器添加 3 个静态文本控件(Static Text)说明版本信息并删除“Cancel”按钮,见图 14-2。 然后修改例 9-1 的程序,加入以下内容: 程 序: 1.在程序首部加上文件包含命令 #include “resource.h” 2.在框架窗口类之前加入从 CDialog 类派生的对话框类: // 对话框类 class CAboutDlg: public CDialog { public: CAboutDlg(); enum {IDD = IDD_DIALOG1}; }; inline CAboutDlg::CAboutDlg():CDialog(CAboutDlg::IDD){} 3.在框架窗口类中添加响应鼠标右键消息的代码,包括消息响应函数说明、消息响应 宏和消息响应函数定义。鼠标右键消息响应函数为: 图 14-2 编辑吹泡泡程序的版权对话框
第14单元对话框 void CMyWnd: OnRBut tonDown (UINT nFlags, CPoint point) CAboutDig dl dlg DoModal O 输入输出:除可用鼠标左键生成泡泡外,按下鼠标右键会弹出一版权对话框 分析:该对话框仅提供了固定的版本信息,没有实现用户与应用程序间的数据交流 所以结构比较简单。 CAboutDIg类重载了构造函数并调用了基类 CDialog的构造函数来实现 对话框模板资源和对话框类之间的关联。注意其中的枚举类型定义,其实质是将具体的对话 框模板资源的标识符在对话框类内映射为统一的标识符IDD 在框架窗口类的 OnR Button Down()成员函数中,声明了一个 CAboutDIg类的对象 并通过其 DoModal()成员函数调用该对话框。这是典型的模态对话框调用方法,除非用 户按下对话框上的OK按钮、 Cancel()按钮或窗口右上角的关闭按钮退出对话框,用户的 所有输入信息均被该对话框截留(无论该信息对对话框是否有用) 实际上,可以使用 Class wizard直接从对话框模板资源生成对应的对话框类代码,无需 手工编程。这方面的内容请参看148:“使用 ClassWizard建立对话框类”。 142控件 要使对话框真正具有与用户对话的能力,还必须使用控件。所谓控件,就是一个现成的 程序组件,可以独立运行以完成一定的功能。 Windows提供了大量控件,控件的使用不仅方 便了 Windows编程,还使 Windows程序具有相当统一的外观和风格。 控件多与对话框一起使用。所有的控件都是CWnd类派生出来的后代类对象,因此它 们均有和CWnd类似的属性。每个控件均有一个标识符(ID),在程序中可以通过这个标识 符对相应的控件进行操作 使用 Visual c++编程时可用的控件很多,在本单元中,仅介绍其中的两个:静态文本控 件和编辑控件,目的是介绍对话框中的数据交换机制。第15单元集中介绍其他控件。 静态文本控件是最简单的控件,其用途是在对话框上显示一段文字。在例14-1中,就 是使用静态文本控件来显示软件的版本信息的。由于静态文本控件的文字和属性均在编辑对 话框模板资源时确定,程序运行中一般无法改变,所以在编程时无需考虑静态文本控件 编辑控件是最有用的控件,其功能十分全面,本身就是一个小型的文本编辑器。编辑控 件的作用是接受用户输入的字符串信息。 以上控件作为资源的编辑方法可参看147:“对话框模板资源的编辑”。 143对话框的初始化 对话框的初始化工作一般在构造函数和 OnInitDialog()函数中完成。在构造函数中的 初始化工作主要是针对对话框的数据成员进行的
第 14 单元 对话框 278 void CMyWnd::OnRButtonDown(UINT nFlags, CPoint point) { CAboutDlg dlg; dlg.DoModal(); } 输入输出:除可用鼠标左键生成泡泡外,按下鼠标右键会弹出一版权对话框。 分 析:该对话框仅提供了固定的版本信息,没有实现用户与应用程序间的数据交流, 所以结构比较简单。CAboutDlg 类重载了构造函数并调用了基类 CDialog 的构造函数来实现 对话框模板资源和对话框类之间的关联。注意其中的枚举类型定义,其实质是将具体的对话 框模板资源的标识符在对话框类内映射为统一的标识符 IDD。 在框架窗口类的 OnRButtonDown()成员函数中,声明了一个 CAboutDlg 类的对象, 并通过其 DoModal()成员函数调用该对话框。这是典型的模态对话框调用方法,除非用 户按下对话框上的 OK 按钮、Cancel()按钮或窗口右上角的关闭按钮退出对话框,用户的 所有输入信息均被该对话框截留(无论该信息对对话框是否有用)。 实际上,可以使用 ClassWizard 直接从对话框模板资源生成对应的对话框类代码,无需 手工编程。这方面的内容请参看 14.8:“使用 ClassWizard 建立对话框类”。 14.2 控件 要使对话框真正具有与用户对话的能力,还必须使用控件。所谓控件,就是一个现成的 程序组件,可以独立运行以完成一定的功能。Windows 提供了大量控件,控件的使用不仅方 便了 Windows 编程,还使 Windows 程序具有相当统一的外观和风格。 控件多与对话框一起使用。所有的控件都是 CWnd 类派生出来的后代类对象,因此它 们均有和 CWnd 类似的属性。每个控件均有一个标识符(ID),在程序中可以通过这个标识 符对相应的控件进行操作。 使用 Visual C++编程时可用的控件很多,在本单元中,仅介绍其中的两个:静态文本控 件和编辑控件,目的是介绍对话框中的数据交换机制。第 15 单元集中介绍其他控件。 静态文本控件是最简单的控件,其用途是在对话框上显示一段文字。在例 14-1 中,就 是使用静态文本控件来显示软件的版本信息的。由于静态文本控件的文字和属性均在编辑对 话框模板资源时确定,程序运行中一般无法改变,所以在编程时无需考虑静态文本控件。 编辑控件是最有用的控件,其功能十分全面,本身就是一个小型的文本编辑器。编辑控 件的作用是接受用户输入的字符串信息。 以上控件作为资源的编辑方法可参看 14.7:“对话框模板资源的编辑”。 14.3 对话框的初始化 对话框的初始化工作一般在构造函数和 OnInitDialog()函数中完成。在构造函数中的 初始化工作主要是针对对话框的数据成员进行的
第14单元对话框 在对话框创建时,会收到 WM INITDIALOG消息,对话框对该消息的处理函数是 OnInitDialog()。调用 OnInitdialog()函数时,对话框已初步创建,对话框的窗口句柄也 已有效,但对话框还未被显示出来。因此,可以在 OnlnitDialog()函数中做一些影响对话 框外观的初始化工作。 OnInitDialog()对对话框类的作用与 On create)函数对 MAin Frame 类的作用类似。 144对话框的数据交换和数据检验机制 在程序中,通过控件与用户的数据交流是分两步完成的。首先,要在对话框类中加入与 控件对应的数据成员,通过数据交换(DDX)确定其与控件的数据交换关系。例如对于编 辑控件,可在对话框类中声明一个 CString类的数据成员,并通过DDX将其与编辑控件联 系起来。这样,打开对话框时,编辑控件窗口显示的就是该数据成员原来的值,如果用户对 编辑控件的内容进行了编辑修改,则在退出对话框后,该数据成员的值也相应地变为编辑后 的内容。 在视图类(或框架窗口类)中调用对话框时,还可通过对话框的数据成员来处理用户的 输入数据。具体说来,在调用对话框类的 DoModal()函数打开对话框之前,可以通过设 置对话框数据成员的值,使其成为控件窗口的显示信息:在退出对话框后,又可将对话框数 据成员所反映的用户输入数据应用到程序的其他部分。也正因为如此,对话框类的数据成员 通常被说明为 public的,以便在上述情况下直接处理。 MFC提供了 DAtaeXchange类来实现对话框类与控件之间的数据交换(DDX),该类 还提供了数据检验机制(DDV)。所谓数据检验,即对用户输入数据的范围进行检査,如 果不符合要求则拒绝接受。这样可以将用户输入数据限制在一预先确定的范围内。数据交换 和检验机制不仅适用于编辑框控件,还适用于检査框、单选按钮、列表框和组合框等控件。 数据交换和检验机制通过 CDialog: DoDataExchange()函数来完成,其原型为 virtual void DoData Exchange( CDataExchange* pDX ) 其中参数pDX为指向 DAtaeXchange类对象的指针,框架使用该对象建立数据交换内 容。该函数由程序控件直接调用,可重载以加入数据交换函数实现对话框数据成员与控件的 联系。数据交换函数很多,这里先介绍与编辑控件有关的数据交换函数 void DDX Text( CDataExchange* pDX, int nlDC, int& value ) void DDX Text( CDataExchange* pDX, int nlDC, long& value yoid DDX Text( CDataExchange* pDX, int nlDC, CString& value ) void DDX Text( CDataExchange* pDX, int nlDC, float& value void DDX Text( CDataExchange* pDX, int nlDC, double& value ) 其中参数pDX是指向 DAtaeXchange对象的指针;参数nDC是对话框对象中的编辑控件 的标识符:而参数 value是对话框中的数据成员的引用。注意该参数的类型不仅可以是 CString,而且可以是各种数值类型。因此,编辑控件不仅可以用来输入文字数据,也可以 用来输入数值数据
第 14 单元 对话框 279 在对话框创建时,会收到 WM_INITDIALOG 消息,对话框对该消息的处理函数是 OnInitDialog()。调用 OnInitDialog()函数时,对话框已初步创建,对话框的窗口句柄也 已有效,但对话框还未被显示出来。因此,可以在 OnInitDialog()函数中做一些影响对话 框外观的初始化工作。OnInitDialog()对对话框类的作用与 OnCreate()函数对 CMainFrame 类的作用类似。 14.4 对话框的数据交换和数据检验机制 在程序中,通过控件与用户的数据交流是分两步完成的。首先,要在对话框类中加入与 控件对应的数据成员,通过数据交换(DDX)确定其与控件的数据交换关系。例如对于编 辑控件,可在对话框类中声明一个 CString 类的数据成员,并通过 DDX 将其与编辑控件联 系起来。这样,打开对话框时,编辑控件窗口显示的就是该数据成员原来的值,如果用户对 编辑控件的内容进行了编辑修改,则在退出对话框后,该数据成员的值也相应地变为编辑后 的内容。 在视图类(或框架窗口类)中调用对话框时,还可通过对话框的数据成员来处理用户的 输入数据。具体说来,在调用对话框类的 DoModal()函数打开对话框之前,可以通过设 置对话框数据成员的值,使其成为控件窗口的显示信息;在退出对话框后,又可将对话框数 据成员所反映的用户输入数据应用到程序的其他部分。也正因为如此,对话框类的数据成员 通常被说明为 public 的,以便在上述情况下直接处理。 MFC 提供了 CDataExchange 类来实现对话框类与控件之间的数据交换(DDX),该类 还提供了数据检验机制(DDV)。所谓数据检验,即对用户输入数据的范围进行检查,如 果不符合要求则拒绝接受。这样可以将用户输入数据限制在一预先确定的范围内。数据交换 和检验机制不仅适用于编辑框控件,还适用于检查框、单选按钮、列表框和组合框等控件。 数据交换和检验机制通过 CDialog::DoDataExchange()函数来完成,其原型为: virtual void DoDataExchange ( CDataExchange* pDX ); 其中参数 pDX 为指向 CDataExchange 类对象的指针,框架使用该对象建立数据交换内 容。该函数由程序控件直接调用,可重载以加入数据交换函数实现对话框数据成员与控件的 联系。数据交换函数很多,这里先介绍与编辑控件有关的数据交换函数: void DDX_Text ( CDataExchange* pDX, int nIDC, int& value ); void DDX_Text ( CDataExchange* pDX, int nIDC, long& value ); void DDX_Text ( CDataExchange* pDX, int nIDC, CString& value ); void DDX_Text ( CDataExchange* pDX, int nIDC, float& value ); void DDX_Text ( CDataExchange* pDX, int nIDC, double& value ); 其中参数 pDX 是指向 CDataExchange 对象的指针;参数 nIDC 是对话框对象中的编辑控件 的标识符;而参数 value 是对话框中的数据成员的引用。注意该参数的类型不仅可以是 CString,而且可以是各种数值类型。因此,编辑控件不仅可以用来输入文字数据,也可以 用来输入数值数据
第14单元对话框 下面介绍常用的数据检验函数: void DDV Max Chars( CData Exchange* pDX, CString const& value, int nChars ) void DDV Min Byte( CDataExchange* pDX, BYTE value, BYTE min Val BYTE max val void DDV Min Date Time( CDataExchange* pDX, CTime& revAlue, const CTime* refMin Range, const CTime" refMaxRange ) void DD Min MaxD Word( CData Exchange* pDX, DWORD const& value DWORD min Val, DWORD max Val void DDV Min Double( CDataExchange* pDX, double const& value, double min Val, double max val void DDV Min Float( CDataExchange* pDX, float value, float min Val float max Val ) void DDV MinMaxlnt( CDataExchange* pDX, int value, int min Val, int max Val ) void DDV MinMaxLong( CDataExchange* pDX, long value, long min Val, : Val void DDV MinMaxMonth( CDataExchange'* pDX, CTime& revalue, const CTime* refMinRange, const CTime* refMax Range void DDV MinMaxUnsigned( CData Exchange* pDX, unsigned value unsigned min Val, unsigned max Val ) void DDV Min MaxSlider( CDataExchange* pDX, DWORD value, DWORD min Val DWORD max Val 其中参数pDX和 value的含义与DDx函数相同,最后一个(或两个)参数是数据范围。参 数 n Chars是字符串的最大字符数,而参数mnVa和 marVa分别为数值类数据的下限和上 例142签名留念簿程序。该程序模仿签名簿,用户使用鼠标左键点击窗口客户区后 会弹出一个对话框,输入姓名后可在鼠标点击位置显示出该签名。签名的颜色、字体大小和 方向随机确定。 说明:项目建立及添加对话框模板资源的方法同例14-1。修改对话框模板的ID为 IDD NAMEDLG, Caption为“签名对话框”,并添加一个静态文本控件( Caption改为“签 名”)和一个编辑控件(ID改为 IDC EDITNAME) 程序: ∥/ Example14-2:签名留念簿程序 #include include resource. h" /对话框类 class CNameDlg: public CDialog public
第 14 单元 对话框 280 下面介绍常用的数据检验函数: void DDV_MaxChars ( CDataExchange* pDX, CString const& value, int nChars ); void DDV_MinMaxByte ( CDataExchange* pDX, BYTE value, BYTE minVal, BYTE maxVal ); void DDV_MinMaxDateTime ( CDataExchange* pDX, CTime& refValue, const CTime* refMinRange, const CTime* refMaxRange ); void DDV_MinMaxDWord( CDataExchange* pDX, DWORD const& value, DWORD minVal, DWORD maxVal ); void DDV_MinMaxDouble ( CDataExchange* pDX, double const& value, double minVal, double maxVal ); void DDV_MinMaxFloat ( CDataExchange* pDX, float value, float minVal, float maxVal ); void DDV_MinMaxInt ( CDataExchange* pDX, int value, int minVal, int maxVal ); void DDV_MinMaxLong ( CDataExchange* pDX, long value, long minVal, long maxVal ); void DDV_MinMaxMonth ( CDataExchange* pDX, CTime& refValue, const CTime* refMinRange, const CTime* refMaxRange ); void DDV_MinMaxUnsigned ( CDataExchange* pDX, unsigned value, unsigned minVal, unsigned maxVal ); void DDV_MinMaxSlider ( CDataExchange* pDX, DWORD value, DWORD minVal, DWORD maxVal ); 其中参数 pDX 和 value 的含义与 DDX 函数相同,最后一个(或两个)参数是数据范围。参 数 nChars 是字符串的最大字符数,而参数 minVal 和 maxVal 分别为数值类数据的下限和上 限。 [例 14-2] 签名留念簿程序。该程序模仿签名簿,用户使用鼠标左键点击窗口客户区后 会弹出一个对话框,输入姓名后可在鼠标点击位置显示出该签名。签名的颜色、字体大小和 方向随机确定。 说 明:项目建立及添加对话框模板资源的方法同例 14-1。修改对话框模板的 ID 为 IDD_NAMEDLG,Caption 为“签名对话框”,并添加一个静态文本控件(Caption 改为“签 名”)和一个编辑控件(ID 改为 IDC_EDITNAME)。 程 序: // Example 14-2:签名留念簿程序 #include #include "resource.h" // 对话框类 class CNameDlg: public CDialog { public:
第14单元对话框 CPoint m pointTopLeft String m strNameEdit publ )lgo enum [IDD= IDD NAMEDLG protected virtual void DoDataExchange(CDataExchange* pDX) virtual BOOL OnInitDialogo /对话框类的构造函数 CNameDlg: CNameDlg(: CDialog(CName Dlg:: IDD) m strName Edit T() /数据交换和数据检验 void CNameDlg: DoDataExchange(CDataExchange* pDX) CDialog:: DoDataExchange(pDX) DDX Text(pDX, IDC EDI TNAME, m strName Edit) DDV MaxChars (pDX, m strName Edit, 20) //初始化对话框 BOOL CNameDlg:: OnInitDialogo CDialog:: OnInitDialogo CRect rect GetWindowRect(&rect) rect CRect(m pointTopLeft, rect Size o) return TRUE //签名类 class SIgnal: public Cobject CString m sName /姓名 CPoint m pointsignal;∥/签名位置 int m nHeight /字体高 int //签名颜色
第 14 单元 对话框 281 CPoint m_pointTopLeft; CString m_strNameEdit; public: CNameDlg(); enum {IDD = IDD_NAMEDLG}; protected: virtual void DoDataExchange(CDataExchange* pDX); virtual BOOL OnInitDialog(); }; // 对话框类的构造函数 CNameDlg::CNameDlg():CDialog(CNameDlg::IDD) { m_strNameEdit = _T(""); } // 数据交换和数据检验 void CNameDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDITNAME, m_strNameEdit); DDV_MaxChars(pDX, m_strNameEdit, 20); } // 初始化对话框 BOOL CNameDlg::OnInitDialog() { CDialog::OnInitDialog(); CRect rect; GetWindowRect(&rect); rect = CRect(m_pointTopLeft, rect.Size()); MoveWindow(rect); return TRUE; } // 签名类 class CSignal: public CObject { CString m_sName; // 姓名 CPoint m_pointSignal; // 签名位置 int m_nHeight; // 字体高 int m_nColor; // 签名颜色
int m eScapement;//签名倾角 blie igna } void Setvalue(CString name, CPoint point, int height, int color //签名类成员函数 void CSignal: SetValue(CString name, CPoint point, int height, int color int escapement) name m m nHeight m cOlor color t = escapement /显示签名 void CSignal: ShowSignal(CDC *pDC) CFont **pOIdFont, font font. CreateFont(m nHeight, 0, m eScapement, 0, 400, FALSE, FALSE 0, OEM CHARSET, OUT DEFAULT PRECIS CLIP DEFAULT PRECIS, DEFAULT QUALITY, DEFAULT_ PITCH,"楷体"); pOldFont= pDC->SelectObject(&font) switch(m cOlor case DC->SetTextColor(rGb(0, 0, 0)) case 5,0,0) pDC->SetTextColor (RGB(0, 255, 0)) break
第 14 单元 对话框 282 int m_nEscapement; // 签名倾角 public: CSignal(){} void SetValue(CString name,CPoint point,int height,int color, int escapement); void ShowSignal(CDC *pDC); }; // 签名类成员函数 void CSignal::SetValue(CString name,CPoint point,int height,int color, int escapement) { m_sName = name; m_pointSignal = point; m_nHeight = height; m_nColor = color; m_nEscapement = escapement; } // 显示签名 void CSignal::ShowSignal(CDC *pDC) { CFont *pOldFont, font; font.CreateFont(m_nHeight, 0, m_nEscapement,0, 400, FALSE,FALSE, 0, OEM_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH, "楷体"); pOldFont = pDC->SelectObject(&font); switch(m_nColor) { case 0: pDC->SetTextColor(RGB(0, 0, 0)); break; case 1: pDC->SetTextColor(RGB(255, 0, 0)); break; case 2: pDC->SetTextColor(RGB(0, 255, 0)); break; case 3:
第14单元对话框 DC->SetTextColor (RGb(0, 0, 255)) break pDC->Text Out(m pointSignal. x, m pointsignal y, m sName pDC->SelectObject(poldFont //框架窗口类 #define maX name 250 class CMy Wnd: public CFrameWnd CSignal m signalList [MAX NAME int m n Count: publi CMyWnd (: m nCount(O)1 protected afx msg void OnLBut ton Down UINT nFlags, CPoint point afx msg void OnPaint O DECLARE MESSAGE MAPO /消息映射 BEGIN MESSAGE MAP(CMyWnd, CFrameWnd ON WM LBUTTONDOWN O ON WM PAINTO END MESSAGE MAPO /框架窗口类的成员函数 /鼠标右键消息响应函数 void CMy Wnd:: OnLBut Down UINT nFlags, CPoint point) if(m nCount MAX NAME) CNamedlg dig dl if(dlg DoModal(== IDOK) int color rand (%4 int escapement =(rand(%1200)-600 CString name = dlg. m strName Edit
第 14 单元 对话框 283 pDC->SetTextColor(RGB(0, 0, 255)); break; } pDC->TextOut(m_pointSignal.x, m_pointSignal.y, m_sName); pDC->SelectObject(pOldFont); } // 框架窗口类 #define MAX_NAME 250 class CMyWnd: public CFrameWnd { CSignal m_signalList[MAX_NAME]; int m_nCount; public: CMyWnd(): m_nCount(0){} protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnPaint(); DECLARE_MESSAGE_MAP() }; // 消息映射 BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd) ON_WM_LBUTTONDOWN() ON_WM_PAINT() END_MESSAGE_MAP() // 框架窗口类的成员函数 // 鼠标右键消息响应函数 void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { if(m_nCount < MAX_NAME) { CNameDlg dlg; dlg.m_pointTopLeft = point; if(dlg.DoModal() == IDOK) { int height = rand()%60+12; int color = rand()%4; int escapement = (rand()%1200)-600; CString name = dlg.m_strNameEdit;
第14单元对话框 signallist [m nCount]. SetValue (name, point, height ol m Invalidate /绘制框架窗口客户区函数 void CMyWnd: OnPaint o CPaintDC dc(this for(int i=0: iShowWindow(m nCmdShow) this->m pMainWnd pframe return TRUe //全局应用程序对象 CMy App Thisapp 输入输出:每当用户在窗口客户区按下鼠标左键后可弹出一对话框,要求输入一签名。 输入签名后退出对话框,在窗口相应位置显示该签名,字体大小、颜色和倾斜角是随机确定 的,见图14-3。 分析:对话框类 CNameDlg的声明方法与例14-1类似,但在其中加入了一个 CString 类的数据成员 m str Nameedit。该数据成员与编辑控件 IDC EDITNAME对应,实现这一对 应关系的代码在数据交换函数 DoData Exchange()中。该变量的初始化在对话框类的构造 函数中完成。在框架窗口类的鼠标左键消息响应函数 OnL Button Down()中,声明了一个
第 14 单元 对话框 284 m_signalList[m_nCount].SetValue(name,point,height, color,escapement); m_nCount++; Invalidate(); } } } // 绘制框架窗口客户区函数 void CMyWnd::OnPaint() { CPaintDC dc(this); for(int i=0; iCreate(0,_T("签字留念簿程序")); pFrame->ShowWindow(m_nCmdShow); this->m_pMainWnd = pFrame; return TRUE; } // 全局应用程序对象 CMyApp ThisApp; 输入输出:每当用户在窗口客户区按下鼠标左键后可弹出一对话框,要求输入一签名。 输入签名后退出对话框,在窗口相应位置显示该签名,字体大小、颜色和倾斜角是随机确定 的,见图 14-3。 分 析:对话框类 CNameDlg 的声明方法与例 14-1 类似,但在其中加入了一个 CString 类的数据成员 m_strNameEdit。该数据成员与编辑控件 IDC_EDITNAME 对应,实现这一对 应关系的代码在数据交换函数 DoDataExchange()中。该变量的初始化在对话框类的构造 函数中完成。在框架窗口类的鼠标左键消息响应函数 OnLButtonDown()中,声明了一个