MFC的对话框
1 相关类
CDialog类-父类是CWnd,本质上也是一个窗口。是对话框类的顶层父类。
CCommonDialog类-父类是CDialog类。称为通用对话框。MFC提供了6个通用对话框类,都是CCommonDialog类的子类,
包括:
文件对话框、颜色对话框、字体对话框、查找替换对话框、打印对话框和打印设置对话框。
CPropertyPage-父类是CDialog类,属性页对话框。
2 分类
模式对话框和非模式对话框
3 使用MFC的类创建基于模式对话框的应用程序
3.1 插入对话框资源,双击对话框资源创建对话框类,这样就完成了对话框类和对话框资源的关联
3.2 创建和显示调用: CDialog::DoModal()
3.3 如果需要在对话框关闭时做一些善后处理,可以重写虚函数
CDialog::OnOK()/OnCancel()
4 使用MFC的类创建基于非模式对话框的应用程序
4.1 插入对话框资源,并与对话框类关联
4.2 创建和显示与一般框架窗口类似
4.3 必须重写以下下函数,否则程序并没有退出
重写OnOK和OnCancel函数,在函数中,调用DestroyWindow()函数
// 如果需要做资源回收等善后处理工作可以
重写PostNcDestroy()函数,在函数中,delete this;
编写测试程序:
新建一个Win32 Application,选择A Simple Win32 Application, 修改stdafx.h中的Windows.h为afxwin.h, 删除默认的主函数
编写如下测试代码:
// Dlg.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
class CMyDlg : public CDialog
{
public:
// 通过调用父类的构造函数来关联对话框资源
CMyDlg():CDialog (IDD_DIALOG1){}
//重写虚函数做关闭时的善后处理
virtual void OnOK ();
virtual void OnCancel ();
virtual void PostNcDestroy ();
};
/****************************
用户点击了默认的"OK"按钮
******************************/
void CMyDlg::OnOK ()
{
DestroyWindow ();
}
/*************************************
用户点击了默认的"Cancel"或关闭按钮
**************************************/
void CMyDlg::OnCancel ()
{
DestroyWindow ();
}
/**************************************
程序将要退出最后发出的消息
***************************************/
void CMyDlg::PostNcDestroy ()
{
delete this;
}
class CMyWinApp : public CWinApp
{
public:
virtual BOOL InitInstance ();
};
CMyWinApp theApp;
BOOL CMyWinApp::InitInstance ()
{
// 创建和显示模式对话框
/*
CMyDlg dlg;
m_pMainWnd = &dlg;
dlg.DoModal ();
*/
// 创建和显示非模式对话框
CMyDlg *pDlg = new CMyDlg;
pDlg->Create (IDD_DIALOG1);
m_pMainWnd = pDlg;
pDlg->ShowWindow (SW_SHOW);
pDlg->UpdateWindow ();
return TRUE;
}
而在MFC中创建对话框: 新建一个对话框资源后双击该对话框选择创建一个类,MFC自动会把我们创建的对话框资源和对话框类关联起来了,我们只需要定义一个我们生成的对话框类对象使用即可。
这里创建一个当文档应用程序,通过点击菜单项分别创建模式和非模式对话框,菜单响应函数如下:
// 包含对话框资源关联的类头文件
#include "DlgModal.h"
#include "DlgModaless.h"
/***********************************
创建并显示模式对话框
*********************************/
void CMainFrame::OnModal()
{
CDlgModal dlg;
if (IDOK == dlg.DoModal ())
MessageBox ("执行相关操作");
else
MessageBox ("取消操作");
}
/**************************************
创建并显示非模式对话框
***************************************/
void CMainFrame::OnModaless()
{
CDlgModaless *pDlg = new CDlgModaless;
pDlg->Create (IDD_DIALOG_NOMODAL);
pDlg->ShowWindow (SW_SHOW);
pDlg->UpdateWindow ();
}
MFC中同样需要为非模式对话框添加处理OnOK、OnCancel、PostNcDestroy虚函数
注意:添加OnOK,OnCancel可以通过双击对话框资源的对应按钮来实现,PostNcDestroy通过右键天机虚函数实现
函数如下:
void CDlgModaless::OnOK()
{
// TODO: Add extra validation here
CDialog::OnOK();
DestroyWindow ();
}
void CDlgModaless::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
DestroyWindow ();
}
void CDlgModaless::PostNcDestroy()
{
// TODO: Add your specialized code here and/or call the base class
CDialog::PostNcDestroy();
delete this;
}
跟之前记得把MFC库改为静态库
void CMainFrame::OnModal()
{
CDlgModal dlg;
dlg.DoModal ();
}
跟进:
OnModal-->DoModal
int CDialog::DoModal()
{
.........................................................
// 超找对话并加载框资源
HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource);
if (hDialogTemplate != NULL)// 由于一个对话框类可以有多个对话框窗口,这里锁定是为了多线程的操作
lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);
if (hWndParent != NULL && ::IsWindowEnabled(hWndParent))
{// 如果父窗口当前是可用的,那么设置为不可用
::EnableWindow(hWndParent, FALSE);
bEnableParent = TRUE;
}
......................................
// create modeless dialog, 创建和显示非模式对话框
if (CreateDlgIndirect(lpDialogTemplate,CWnd::FromHandle(hWndParent), hInst))
........................................................
// 进入对话框的消息循环
VERIFY(RunModalLoop(dwFlags) == m_nModalResult);
// hide the window before enabling the parent, etc.
// 点击OK、Cancel按钮后跳出上面的消息循环来到这里,隐藏对话框窗口
if (m_hWnd != NULL)
SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
.......................................................
if (bEnableParent)
::EnableWindow(hWndParent, TRUE);// 启用父窗口
if (hWndParent != NULL && ::GetActiveWindow() == m_hWnd)
::SetActiveWindow(hWndParent); // 设置父窗口为活动
// destroy modal window
// 销毁对话框,这里可以看到是MFC帮我们调用了这两个函数
DestroyWindow();
..................................................
// unlock/free resources as necessary
if (m_lpszTemplateName != NULL || m_hDialogTemplate != NULL)
UnlockResource(hDialogTemplate);// 解锁
if (m_lpszTemplateName != NULL)
FreeResource(hDialogTemplate);// 释放对话框资源
return m_nModalResult;//返回用户点击的按钮对应的数值值
}
DoModal()函数的执行过程
1 查找和加载对话框资源
2 将父窗口设置为不可用状态
3 创建和显示对话框
4 进入对话框的消息循环
5 点击OK/Cancel/关闭按钮时,跳出循环,隐藏对话框窗口
6 将父窗口设置为可用的和活动的状态
7 销毁对话框窗口
8 释放对话框资源
9 函数执行结束,得到DoModal函数的返回值