UpdateData(FALSE)-将变量的值显示到控件上
新建一个Win32 Application,选择A Simple Win32 Application,修改stdafx.h 中的windwos.h为afxwin.h,工程属性设置使用MFC静态库
编写如下测试代码
// DDX.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 DoDataExchange (CDataExchange* pDX); virtual BOOL OnInitDialog (); virtual void OnOK(); protected: CButton m_wndOK; CString m_strEdit; }; void CMyDlg::DoDataExchange (CDataExchange* pDX) { //完成控件与变量的绑定 DDX_Control (pDX, IDOK, m_wndOK); DDX_Text (pDX, IDC_EDIT1, m_strEdit); } BOOL CMyDlg::OnInitDialog () { if (!CDialog::OnInitDialog()) return FALSE; // 初始化控件 // 方式一:通过GetDlgItem操作控件 CWnd *pWnd = GetDlgItem (IDCANCEL); pWnd->EnableWindow (FALSE); m_wndOK.MoveWindow (0, 0, 100, 100); m_wndOK.SetWindowText ("DDXOK"); // 方式二:通过DDX操作控件 m_strEdit = "Hello you"; UpdateData (FALSE); return TRUE; } void CMyDlg::OnOK () { // 接收控件的值到关联的变量 UpdateData (TRUE); AfxMessageBox (m_strEdit); CDialog::OnOK(); } class CMyWinApp : public CWinApp { public: virtual BOOL InitInstance (); }; CMyWinApp theApp; BOOL CMyWinApp::InitInstance () { CMyDlg dlg; m_pMainWnd = &dlg; dlg.DoModal (); return TRUE; }
DDX的实现原理
1 控件类型的绑定
DDX_Control (pDX, IDOK, m_wndOK);跟进:
void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl) {// nIDC: IDCOK , rControl: m_wndOK ................................... // 通过控件ID得到控件句柄 HWND hWndCtrl = pDX->PrepareCtrl(nIDC); if (!rControl.SubclassWindow(hWndCtrl)) { .......................................... } }
DDX_Control-->SubclassWindow
BOOL CWnd::SubclassWindow(HWND hWnd) {// this == m_wndOK, hWnd == 控件句柄 // 将m_wndOK控件变量与OK按钮句柄绑定 if (!Attach(hWnd)) return FALSE; ............................................... }
DDX_Control-->SubclassWindow-->Attach跟进:
BOOL CWnd::Attach(HWND hWndNew) {//this == m_wndOK, hWndNew == 控件句柄 ...................................... CHandleMap* pMap = afxMapHWND(TRUE); // create map if not exist ASSERT(pMap != NULL); // 建立映射关系 pMap->SetPermanent(m_hWnd = hWndNew, this); ........................................ }
DDX_Control-->SubclassWindow-->Attach-->SetPermanent
void CHandleMap::SetPermanent(HANDLE h, CObject* permOb) { ....................................... // 以控件句柄为键,以变量句柄为值建立映射关系 m_permanentMap[(LPVOID)h] = permOb; ......................................... }
总结流程如下:
DDX_Control(pDX,IDOK,m_wndOK); { //通过控件ID得到控件句柄 HWND hWndCtrl = pDX->PrepareCtrl(nIDC); //将控件句柄与变量绑定 rControl.SubclassWindow(hWndCtrl); { Attach(hWnd); { pMap->SetPermanent(m_hWnd = hWndNew, this); { //以句柄为健,以变量地址为值建立映射关系 m_permanentMap[(LPVOID)h] = permOb; } } } }
2 值类型的绑定
UpdateData (FALSE);跟进:
BOOL CWnd::UpdateData(BOOL bSaveAndValidate) {// this == &dlg, bSaveAndValidate == FALSE ............................................. CDataExchange dx(this, bSaveAndValidate); .......................................... // 虚函数,会调用我们重写的函数 DoDataExchange(&dx); ........................................ }
UpdateData-->DoDataExchange-->CMyDlg::DoDataExchange-->DDX_Text
void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value) {// pDX中保存了&dlg和FALSE, nIDC == IDOK, value == m_strEdit // 通过控件ID拿到编辑框控件句柄 HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC); if (pDX->m_bSaveAndValidate) {// UpdateData (TRUE) int nLen = ::GetWindowTextLength(hWndCtrl); // 获取控件文本 ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1); value.ReleaseBuffer(); } else {// UpdateData (FALSE) // 设置控件文本 AfxSetWindowText(hWndCtrl, value); } }
UpdateData(FALSE); { CDataExchange dx(this, bSaveAndValidate); DoDataExchange(&dx); { DDX_Text(pDX,IDC_EDIT1,m_strEdit); { //通过控件ID得到控件句柄 HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC); if (pDX->m_bSaveAndValidate) { ::GetWindowText(hWndCtrl,...); value.ReleaseBuffer(); } else { //将变量的值设置到控件的窗口上 AfxSetWindowText(hWndCtrl, value); } } } }