首页 > 代码库 > MFC对话框
MFC对话框
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函数的返回值