对话框是Windows应用程序中重要的用户接口,对话框实际上也是一个窗口,可以接收消息,绘制图案、移动窗口等。我们可以把对话框看做是一个大容器,能够在上面放置各种各样的标准空间和扩展控件。
对话框种类
对话框有两种类型:模态(Modal)对话框和非模态(Modaless)对话框。
- 模态对话框
- 非模态窗口
对话框的创建&显示
如果想在程序中创建自己的对话框,可以通过插入一个对话框资源来完成。在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成的。例如,对话框资源对应的类就是CDialog,该类派生于CWnd类,是窗口相关的类。CWnd类中的m_hWnd指示了与其所关联的窗口。
对话框资源添加步骤:
资源视图->添加->添加资源->选择“Dialog”->点击“新建”,效果如图1所示。在对话框上面默认有两个按钮:“确定”和“取消”,对应ID号是ID_OK和ID_CANCAL.
添加与资源相关的类:
资源编辑器->鼠标右键->添加类,效果如图2所示:
图1 对口框资源
图2 绑定对对话框资源的类
模态对话框创建
创建模态对话框需要调用CDialog类中的成员函数DoModal,该函数的功能是创建并显示一个模态对话框,其返回值作为Endialog的参数,其功能是关闭模态对话框。通常我们根据该DoModal返回值来判断用户单击的是哪一个按钮,从而确定用户行为。
DoModal的函数声明如下:
virtual int DoModal();由于DoMal函数具有阻塞性,函数执行会停止在DoMal所在的行,所以此时对话框的对象可以是临时的。代码如下:
//模态窗口创建 CTestDlg dlg; //窗口关闭,DoModal程序执行完成,否则程序一直阻塞在DoModal函数。 dlg.DoModal(); //窗口关闭,程序执行到该语句
非模态对话框创建
如果要创建非模态窗口,则需要利用CDialog类的Create成员函数,该函数相关声明如下:
BOOL Create(LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL); BOOL Create(UNIT nIDTemplate, CWnd* pParentWnd = NULL); 返回值: 如果对话框创建和初始化成功,则返回非零值,否则为0。 参数: lpszTemplateName 包含一个对话框模板资源的空终止字符串。 pParentWnd 指向含有对话框的父窗口对象的指针。如果为NULL,对话框对象的父窗口设置为应用的主窗口。 nIDTemplate 包含对话框模板资源的ID数。 说明: 调用Create,使用资源中对话框模板来创建非模态对话框。可将调用置于构造程序内部或者在构造程序启动之后调用。具体代码下:
//非模态窗口创建 if (GetDlg() != NULL) { if (NULL == GetDlg()->m_hWnd) { GetDlg()->Create(IDD_DIALOG_EXPORT, this);//GetDlg返回CDialog对象指针 GetDlg()->ShowWindow(SW_SHOW); } }
三个重要函数说明
我们创建的默认对话框中包含了两个按钮“确认”和“取消”,它们所对应的功能都是一样的,就是关闭对话框。对于模态对话框而言,此时对话框对象被销毁了,所对应的窗口也被释放,而对于非模态对口框来说,对话框对象并未被消息销毁,只是被隐藏起来了。下面说明这两个按钮所对应的函数以及窗口创建初始化函数OnInitDialog。
virtual void OnCancel();说明:
当用户在模态对话框或非模态对话框内单击Cancel按钮或按ESC键时,窗体调用这个成员函数。
对于模态窗口:
调用EndDialog来简单中止模态对话框,并使DoModal返回IDCANCEL,该模态窗口被销毁,不需要重写改函数。
对于非模态窗口:
需要重写OnCancel成员函数,并调用DestoryWindow函数来销毁窗口。不能再调用基类的OnCancel函数,否则那将会调用EndDialog,使对话框虽然存在但不可视。
virtual void OnOK();说明:
当用户按OK按钮(ID是IDOK)时调用。对于模态窗口可以销毁窗口,而非模态窗口则需要重写该函数,具体使用和OnCancel类似。
virtual BOOL OnInitDialog();说明:
调用这个成员函数是对WM_INITDIALOG消息作出的反应。这条消息是在对话框即将显示之前,在Create,CreateIndirect或DoModal调用期间发出的。我们可以利用重写该函数完成数据的初始化。
案例
根据以上知识介绍,可以完成对话框的创建和显示,这里以创建非模态窗口为例,我们在菜单栏中创建Test菜单,并在视类中完成消息的响应,对口框窗口所对应的类是CTestDlg,具体代码如下:
对话框消息消息响应函数:
//对话框创建,显示之前响应 BOOL CTestDlg::OnInitDialog() { CDialog::OnInitDialog(); // TODO: 在此添加额外的初始化 //主要用于用户数据初始化 AfxMessageBox("OnInitDialog"); return TRUE; } //确定按钮响应函数 void CTestDlg::OnOK() { // TODO: 在此添加专用代码和/或调用基类 AfxMessageBox("OnOK"); DestroyWindow(); //CDialog::OnOK(); } //取消按钮响应函数 void CTestDlg::OnCancel() { // TODO: 在此添加专用代码和/或调用基类 AfxMessageBox("OnCancel"); DestroyWindow(); //CDialog::OnCancel(); }视类中的相关函数:
//创建对话框类 CTestDlg* CDialogView::GetDlg() { if (m_dlg == NULL) { m_dlg = new CTestDlg; } return m_dlg; } //Test菜单消息响应函数 void CDialogView::OnTest() { //非模态窗口创建 if (GetDlg() != NULL) { if (NULL == GetDlg()->m_hWnd) { GetDlg()->Create(IDD_DIALOG_EXPORT, this); GetDlg()->ShowWindow(SW_SHOW); } } }
运行结果: