一、MFC对话框
1.对话框的分类
模式和非模式
2.相关类
CDialog类 - 父类CWnd类
CCommonDialog - 父类是CDialog类,称为通用对话框类,包括颜色对话框、文件对话框、字体对话框、
查找对话框、页面设置对话框、打印对话框。
CPropertyPage类 - 父类是CDialog类,称为属性页对话框。
3.CDialog类的使用类
3.1 创建基于模式对话框的应用程序
(1)添加对话框资源,与对话框类关联
(2)在应用程序类的InitInstance函数中创建和显示对话框窗口
CDialog::DoModal( )
(3)对话框的关闭
不要做任何处理,点击OK或关闭的时,会自动调用相关函数
CDialog::OnOk
CDialog::OnOk
3.2 创建基于非模式对话框的应用程序
(1)添加对话框资源,与对话框类关联
(2)窗口的创建和显示与一般的框架窗口类似
(3)处理对话框的关闭(销毁对话框)
重写CDialog::OnOk( )和CDialog::OnOk( )函数,在函数中调用DestroyWindow销毁对话框窗口
重写CWnd::PostNcDestroy( )函数,在函数中完成对象的自我销毁,delete this;
相关代码:

#include "stdafx.h" //2对话框类 class CMyDialog :public CDialog { public: CMyDialog() : CDialog(IDD_DIALOG1) { } virtual void OnOK(); virtual void OnCancel(); virtual void PostNcDestroy(); }; void CMyDialog::OnOK() { DestroyWindow(); } void CMyDialog::OnCancel() { DestroyWindow(); } void CMyDialog::PostNcDestroy() { delete this; } //1应用程序类 class CMyWinApp : public CWinApp { public: virtual BOOL InitInstance(); }; CMyWinApp theApp; BOOL CMyWinApp::InitInstance() { //模式对话框 //CMyDialog dlg; //m_pMainWnd = &dlg; //dlg.DoModal(); //非模式对话框 CMyDialog *pDlg = new CMyDialog; pDlg->Create(IDD_DIALOG1); m_pMainWnd = pDlg; pDlg->ShowWindow(SW_SHOW); pDlg->UpdateWindow(); return TRUE; }
运行结果:
在MFC应用程序中创建对话框,在框架类中添加代码
相关代码:

#include "DlgModel.h" #include "DlgModeless.h" void CMainFrame::OnDlgModel() { //创建和显示模式对话框 CDlgModel dlg; int nRet = dlg.DoModal(); if (1 == nRet) { AfxMessageBox(L"用户点击OK按钮"); } if (2 == nRet) { AfxMessageBox(L"用户点击Cancel按钮"); } } void CMainFrame::OnDlgModeless() { //创建和显示非模式对话框 CDlgModeless *pDlg = new CDlgModeless; pDlg->Create(IDD_DIALOG2); pDlg->ShowWindow(SW_SHOW); pDlg->UpdateWindow(); }
运行结果:
4. DoModal函数的执行过程
4.1 查找并加载资源
4.2 将父窗口设置为不可用状态
4.3 创建对话框,进入对话框的消息循环
4.4 点击OK、Cancel或者关闭按钮时,跳出循环,并且隐藏对话框窗口
4.5 将父窗口设置为可用和活动状态
4.6 销毁对话框窗口
4.7 释放对话框资源
4.8 返回
dlg.DoModal( )
{
//1 查找加载资源
HRSRC hResource = ::FindResource( hInst, m_lpszTemplateName, RT_DIALOG );
hDialogTemplate = LoadResource( hInst, hResource );
//2 将父窗口设置为不可用状态
HWND hWndParent = PreModal( );
::EnableWindow( hWndParent, FALSE );
//3 创建对话框,进入对话框的消息循环
CreateRunDlgIndirect( lpDialogTemplate, CWnd::FromHandle(hWndParent), hInst )
{
BOOL bRet = CreateDlgIndirect( lpDialogTemplate, pParentWnd, hInst )
{
RunModalLoop( dwFlags ) == m_nModalResult;
//4 点击OK、Cancel或者关闭按钮时,跳出循环,并且隐藏对话框窗口
SetWindowPos( NULL, 0, 0, 0, 0, SWP_HIDEWINDOW |
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
}
}
//5 将父窗口设置为可用和活动状态
::EnableWindow( hWndParent, TRUE );
::SetActiveWindow( hWndParent );
//6 销毁对话框窗口
DestroyWindow( );
//7 释放对话框资源
FreeResource( hDialogTemplate );
return m_nModalResult;
}
二、控件操作
1. 控件的初始化放到对话框的OnInitDialog( )函数中
2. 对话框数据交换技术DoDataExchange,DDX
2.1概念
将控件与对话框类的成员变量绑定,通过操作成员变量的方式间接的操作控件
2.2 使用步骤
(1)添加成员变量
(2)在CWnd::DoDataExchange( )函数中,将变量与控件绑定
DDX_Control( ) - 控件类型的绑定
DDX_Text( ) - 值类型的绑定,需要结合UpdateData使用
(3)UpdateData(BOOL)函数
FALSE - 将变量的值传递给控件
TRUE - 用户在控件中输入的值传递给变量
相关代码:

#include "stdafx.h" class CMyDialog : public CDialog { public: CMyDialog() : CDialog(IDD_DIALOG1) { } virtual BOOL OnInitDialog(); virtual void DoDataExchange(CDataExchange* pDX); virtual void OnOK(); protected: CButton m_btnOK;//与OK按钮绑定的成员变量 CString m_sText;//与文本框绑定的值类型的成员变量 }; void CMyDialog::OnOK() { UpdateData(TRUE);//将用户在控件中输入的值传递给变量 AfxMessageBox(m_sText); CDialog::OnOK(); } void CMyDialog::DoDataExchange(CDataExchange* pDX) { //变量m_btnOK与OK按钮绑定 DDX_Control(pDX, IDOK, m_btnOK); //值类型的绑定 DDX_Text(pDX, IDC_EDIT1, m_sText); } BOOL CMyDialog::OnInitDialog() { if (!CDialog::OnInitDialog()) return FALSE; //控件的初始化操作 CWnd *pWnd = GetDlgItem(IDCANCEL); pWnd->EnableWindow(FALSE); //使用DDX操作OK按钮 m_btnOK.MoveWindow(0, 0, 100, 100); m_btnOK.SetWindowTextW(L"DDXOK"); //值类型的操作 m_sText = "Hello World"; UpdateData(FALSE); return TRUE; } class CMyWinApp : public CWinApp { public: virtual BOOL InitInstance(); }; CMyWinApp theApp; BOOL CMyWinApp::InitInstance() { CMyDialog dlg; m_pMainWnd = &dlg; dlg.DoModal(); return TRUE; }
运行结果:
2.3 实现原理
(1)控件类型绑定
DDX_Control( pDX, IDOK, m_btnOK )
{
//1 根据控件ID获取控件句柄
pDX->PrepareCtrl( IDOK ); //给pDX中的成员m_pDlgWnd赋值
HWND hWndCtrl;
pDX->m_pDlgWnd->GetDlgItem( IDOK, &hWndCtrl );
//2 将控件句柄附加到对象中
m_btnOK.SubclassWindow( hWndCtrl )
{
Attach( hWndCtrl )
{
pMap->SetPermanent( m_hWnd = hWndCtrl , &m_btnOK )
{
//以控件句柄为键,以变量地址为值,建立映射关系
m_permanentMap[ m_hWnd ] = &m_btnOK; //★★★
}
}
}
}
(2)值类型的绑定
UpdateData( TRUE )
{
CDataExchange dx( this, TRUE ); //对话框信息及相关参数
DoDataExchange( &dx )
{
//回到我们自己写的代码
DDX_Text( pDX, IDC_EDIT1, m_sText )
{
//1 根据控件ID得到控件句柄
HWND hWndCtrl = pDX->PrepareEditCtrl( IDC_EDIT1 );
//2.1 将用户在控件的输入传递给变量
if ( pDX->m_bSaveAndValidate )
{
//获得文本框内容长度
int nLen = ::GetWindowTextLength( hWndCtrl );
//获取文本框的值
::GetWindowText( hWndCtrl, m_sText .GetBufferSetLength( nLen ), nLen + 1 );
}
//2.2 将变量的值显示到控件上
else
{
AfxSetWindowText( hWndCtrl, m_sText );
}
}
}
}