再在图7.33所示的快捷菜单中选择Add Member Function选项,弹出如图7.33所示的Add Member Function对话框,增加Creat()函数。为Creat()函数添加代码如下: return Cdialog::Create(Cmymodeless::IDD, m_parent);
其中Cmymodeless::IDD为在mymodeless.h中定义的IDD_MODELESS,m_parent为调用该无模式对话框的父窗口,在构造函数中已对其进行了初始化。
为无模式对话框的按钮添加代码。从“查看”菜单选“建立类向导”,出现MFC Class Wizard对话框,选择Member Maps标签,确认Project列表框中的内容为mydlg,Class name列表框中的内容为Cmymodeless。然后在Object IDs列表框中选IDOK选项,在Messages列表框中选择BN_CLCKED消息,如图7.36所示.单击Add Function按钮,为WM_INITDIALOG消息增加消息响应函数OnOk(),单击Edit Code按钮,在函数中添加如下代码:
{CEdit *m_edit=( CEdit *)GetDlgItem(IDC_EDIT1); CString str=”您正在是使用无模式对话框!”; m_edit->SetWindowText(str);}
利用同样的方法为Cancel按钮添加BN_CLICKED消息的消息响应函数OnCancel(),函数代码如下:
DestroyWindow();
在模式对话框中,通过单击OK或Cancel按钮来关闭对话框,Cdialog类提供两个默认的处理函数OnOk()和OnCancel(),在其中调用Cdialog类的EndDialog函数关闭对话框。而当关闭或删除无模式对话框时,需要调用DestroyWindow()函数,所以在OnOk()和OnCancel()函数中将调用Cdialog类默认的函数OnOk()和OnCancel()的代码行注释掉。当单击OK按钮时,编辑框显示”您正在是使用无模式对话框!”,当单击Cancel按钮时,调用DestroyWindow()函数删除该无模式对话框。
在无模式对话框中收到的最后一个消息是WM_NCDESTROY,无模式对话框将调用CWnd类的默认处理函数PostNcDestroy来处理,在这个函数中将释放分配给Cmymodeless的内存。通过以上添加函数的方法,利用MFC Class Wizard对话框,为Cmymodeless类的PostNcDestroy消息添加PostNcDestroy()函数,其函数代码如下:
delete this;
(2)对无模式对话框的调用
按照无模式对话框中增加变量的方法,为CMydlgView类增加如下变量: public:
Cmymodeless *mymodeless; BOOL m_modeless;
其中Cmymodeless *mymodeless;用于存放新创建的无模式对话框的指针,BOOL m_modeless; 用于存放无模式对话框是否正确创建的返回值。
按照无模式对话框添加菜单响应函数的方法,利用MFC Class Wizard对话框,为CMydlgView类的ID_MODELESS的COMMAND消息添加OnModeless()函数,其函数代码如下:
mymodeless=new Cmymodeless(this); m_modeless= mymodeless->Create();
CWnd *m_edit1= mymodeless->GetDlgItem(IDC_EDIT1); m_edit1->SetWindowText(”您正在是使用无模式对话框!”);
通过调用new创建无模式对话框,为其分配内存,并利用mymodeless对象的成员函数Create()创建对话框资源。然后通过GetDlgItem()和SetWindowText()函数初始化无模式
对话框。
当焦点转移到父窗口时,无模式对话框的编辑框中显示“您已经离开无模式对话框!”,为实现这个功能,需在CMydlgView类中添加“WM_SETFOCUS”的消息响应函数OnSetFocus(),其函数代码如下:
if(m_modeless)
{ CWnd *m_edit1= m_modeless->GetDlgItem(IDC_EDIT1); m_edit1->SetWindowText(”您已经离开无模式对话框!”); }
为了成功调用无模式对话框,还需要在中添加类的头文件mymodeless.h #include “mymodeless.h”
编译并执行程序,单击“对话框”菜单项的“无模式对话框”子菜单,弹出“无模式对话框” 对话框窗口,在窗口中单击OK按钮时,编辑框中显示”您正在是使用无模式对话框!”,而将焦点切换到父窗口时,编辑框中显示“您已经离开无模式对话框!”。至此,已完成了mydlg 应用程序的设计。
7.3 理论总结
7.3.1 对话框的设计
模式对话框和无模式对话框的设计思想基本一致,通过对话框资源管理器设计对话框资源,设计对话框资源的方法如下:
(1)创建对话框资源,并添加各种所需的控件。
(2)创建对话框的派生类,并将其与已创建的对话框资源相连。
(3)在创建的派生类中添加所需的数据成员变量、数据交换和数据校验函数。 (4)为对话框及其中的函数添加所需的响应函数。 7.3.2 模式对话框的调用 1.显示对话框
要显示对话框,首先要调用两个CDialog公有构造函数中的任何一个来构造对话框对象,然后调用对话框对象的成员函数Domodal()装载对话框资源、显示对话框并管理与对话框的交互作用,直到单击OK或Cancel按钮。 2.初始化对话框
创建对话框后,可以调用对话框对象的成员函数OnInitDialog()来初始化对话框,模式对话框在调用DoModal()函数时,调用OnInitDialog()函数。 3.处理对话框消息
对话框也是Winsows窗口,对话框的建立、用呼对对话框中各种控件的操作和对话框的结束都将产生消息,对话框必须适当的处理这些消息。 4.关闭对话框
当在对话框中单击OK或Cancel按钮时,可以关闭对话框,在OK或Cancel按钮的默认处理函数中,将调用CDialog类的成员函数EndDialog()来关闭窗口,程序员可以不重设成员函数OnOK()和OnCancel()。 5.加入头文件
在实现对话框的操作时,应将新产生的对话框派生类所对应的.h头文件加入到调用对话框的源文件中。
7.3.3 无模式对话框的调用
无模式对话框和模式对话框的使用方法差不多,只是在对话框的定义、创建以及消息处理上略有差别。 1.显示对话框
无模式对话框的显示和模式对话框的显示有所不同,无模式对话框利用了Create()函数来显示,而不是使用Domodal()来装载对话框资源。
对于无模式对话框首先要定义一个对话框的指针,再通过调用new为其分配内存,最后调用Create()函数来装载对话框资源并显示对话框。
Cmymodeless *mymodeless;
m_modeless=new Cmymodeless(this); m_modeless= m_modeless->Create(); 2.初始化对话框
创建对话框后,可以调用对话框对象的成员函数OnInitDialog()来初始化对话框,无模式对话框在调用Create()函数时,调用OnInitDialog()函数。 3.处理对话框消息
无模式对话框对于消息的处理与模式对话框一样。 4.关闭对话框
模式对话框通过调用CDialog类的成员函数EndDialog()来关闭窗口,而无模式对话框通过调用Create()函数装载,必须调用DetroyWindow()函数来删除相应的窗口。所以在无模式对话框中必须重设OnOK()和OnCancel()函数,当单击OK或Cancel按钮退出对话框时,需在OnOK()和OnCancel()函数中调用DetroyWindow()函数。
对于DetroyWindow()函数的调用只是删除相应的对话框,而并不释放分配给对话框的内存。程序员可以利用窗口的最后一个消息WN_NCDESTROY来释内存,在WN_NCDESTROY的消息响应函数PostNcDestroy中调用delete释放为 放中当单击OK或Cancel按钮时,可以关闭对话框,在OK或Cancel按钮的默认处理函数中,将无模式对话框分配的内存。如应用程序中代码:
delete this; 5.加入头文件
在实现对话框的操作时,应将新产生的对话框派生类所对应的.h头文件加入到调用对话框的源文件中。
7.3.4 对话框数据交换和校验
对话框的一个主要任务是采集用户的输入信息,将输入信息传递给应用程序。用户输入的信息是否正确,也是十分重要的问题。例如:输入了“5月45日”,就是一个明显的错误。如何在对话框中简单的查出这种错误?可以利用MFC所提供的DDX和DDV来解决数据交换与检查的问题。所谓DDX是指把对话框类中的成员变量与对话框中的控件产生关联,当对话框结束时,控件的内容会自动传递到这些成员变量上。所谓DDV是指允许程序员设定对话框的内容类型及数据(数值)范围。
MFC的DDX和DDV的工作流程是:首先在对话框类中定义一些与相对应的成员变量,然后再重载成员函数CWnd∷DoDataExchange(),在这个函数中插入DDX和DDV函数。CWnd∷UpdateData()
DoDataExchange()函数会被CWnd∷UpdateData()函数调用,在CDialog∷OnInitDialog()函数中默认调用CWnd∷UpdateData()函数来初始化对话框控件,当用户单击Ok按钮时,也在CDialog∷OnOk()函数中默认调用CWnd∷UpdateData()函数将控件的值传递给成员变量。UpdateData()函数的原型为:
BOOL Up dateData(BOOL bSaveAndValidate = TRUE); 如果bSaveAndValidate值为TRUE,则获取并验证对话框数据。图7.37为DoDataExchange()信息交换流程。
DDX()函数一般有三个参数:第一个参数是指向CdataExchange对象的指针,第二个参
数是控件资源ID,第三个参数是成员变量。
163页是DoDataExchange()函数重载的例子。
7.3.5 信息框
信息框可以用来与用户进行简单的沟通,在信息框中可以输入标题、信息框中间的文字信息、图标符号以及信息框带有的按钮等。图7.38为一个标准的信息框。要产生信息框,需要用CWnd类的成员函数MessageBox(),其函数原型如下:
int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption=NULL,UINT nType=MB_OK);
其中LPCTSTR lpszText为信息框中要显示的文本, LPCTSTR lpszCaption为信息框的标题,UINT nType为信息框的样式,包含其所含有的按钮及其信息文本旁出现的图案,它可以由表7.1所表示的常数组成。MessageBox()函数的返回值为信息框上的哪一个按钮被按下。
7.3.6 通用对话框类
通用对话框是Windows预定的对话框,可以通过对通用对话框的调用,执行各种标准的操作。每个通用对话框都是从CCommonDialog类派生的,而CCommonDialog类又是从CDialog类派生的。表7.2说明各通用对话框的名称和作用。
CDialog类是所有对话框类的基类。它定义了一个构造函数和一个Create()成员函数来创建对话框。CDialog类中有许多成员函数,其中最重要的有4个: 1) CDialog::DoModal();用于激活模式对话框。 2) CDialog::OnlnitDialog();用于响应WM_INITDIALOD消息。 3) CDialog::OnOK();单击确定按钮时,调用该函数。 4) CDialog::OnCancel();单击取消按钮时,将自动终止模式对话框。 1. CFontDialog类
CFontDialog类封装了Windows标准的“字体”对话框,使用户可以从系统安装的字体列表中选择要用的字体,在编程中按照如下步骤使用该对话框: (1)构造CFontDialog类对象。
(2)通过对象的数据成员m_cf初始化对话框中各控件的值或状态。 (3)使用成员函数DoModal()调用对话框。
(4)应用程序通过CFontDialog类的成员函数获得各种信息。 其常用的成员函数如表7.3. 2. CFileDialog类
CFileDialog类封装了Windows标准的“打开”和“另存为”对话框,在编程中按照如下步骤使用该对话框:
(1)构造CFileDialog类对象。
(2)通过对象的数据成员m_ofn初始化对话框中各控件的值或状态。 (3)使用成员函数DoModal()调用对话框。
(4)应用程序通过CFileDialog类的成员函数获得各种信息。 其常用的成员函数如表7.4 3. CColorDialog类
CColorDialog类封装了Windows标准的“颜色”对话框,在编程中按照如下步骤使用该对话框:
(1)构造CColorDialog类对象。
(2)通过对象的数据成员m_cc初始化对话框中各控件的值或状态。 (3)使用成员函数DoModal()调用对话框。
(4)应用程序通过CColorDialog类的成员函数获得各种信息。