DoDataExchange函数的来龙去脉

关于对话框数据交换及验证 

对话框的数据交换和验证机制(DDX、DDV)可以使对话框上控件与对象数据成员间协调工作。 

包括控件窗口与控件对象间的连接,控件窗口与对话框数据成员间的连接,以及数据成员的合法性验证等等。 

在 virtual void DoDataExchange(CDataExchange* pDX);中记录了这些关系: 
例如: 

DDX_Control(pDX, IDC_BUTTON1, m_btn); //CButton对象到控件窗口IDC_BUTTON1的关联 
DDX_Text(pDX, IDC_EDIT1, m_int); //整型数据到编辑窗口的关联 
DDV_MinMaxInt(pDX, m_int, 0, 40); //整型数据的范围验证 

必要时,可以自己编写验证函数实现特定内容检验。 

相关的成员函数: 

CDialog::OnInitDialog(); 
CWnd::DoDataExchange(); 
CDialog::DoDataExchange(); 

1 .控件关联 

DDX_Control实现控件窗口和C++控件对象的关联。 
由于对话框是以模板的方式建立的,故控件窗口都是事先建立好的。 
C++控件对象用SubClassWindow的方法附着在控件窗口上,管理窗口的行为。 
内部流程分析: 

①OnInitDialog 时调用基类CDialog::OnInitDialog(); 

BOOL CDialog::OnInitDialog() 
{ 
..... 
// 执行UpdateData(),参数为FALSE,表示初始化 
if (!UpdateData(FALSE)) 
{ 
.... 
} 
..... 
} 

②UpdateData() 

BOOL CWnd::UpdateData(BOOL bSaveAndValidate) 
{ 
.... 

//调用虚函数DoDataExchange 
CDataExchange dx(this, bSaveAndValidate); 
.... 
TRY 
{ 
DoDataExchange(&dx); 
bOK = TRUE; // it worked 
} 
..... 
} 

③DoDataExchange 
void C????Dlg::DoDataExchange(CDataExchange* pDX) 
{ 
.... 
//对象到窗口的关联。 
DDX_Control(pDX, IDC_BUTTON1, m_btn); 
.... 
} 

④DDX_Control void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl) 
{ 
if (rControl.m_hWnd == NULL) //若还未关联 
{ 
//窗口句柄 
HWND hWndCtrl = pDX->PrepareCtrl(nIDC); 
// SubclassWindow 实现关联。 
if (!rControl.SubclassWindow(hWndCtrl)) 
{ 
.... 
} 
.... 
} 
} 

至此,控件对象与对话框上的子窗口关联上了,可以通过对控件对象的操作来管理该子窗口。 

2 .数据关联 

大致流程与前相似。在对话框OnOK()时将调用Update(TRUE),参数TRUE表示读出及校验数据。 

另可根据需要,随时调用Update(TRUE)完成窗口内容到成员数据的校验及转换。 

流程分析(以编辑框到整数的关联为例) 

①DoDataExchange 

void C???Dlg::DoDataExchange(CDataExchange* pDX) 
{ 
.... 
DDX_Text(pDX, IDC_EDIT1, m_int); 
.... 
} 

②DDX_Text 

void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, int& value) 
{ 

if (pDX->m_bSaveAndValidate) //读取及校验 
_Afx_DDX_TextWithFormat(pDX, nIDC, _T("%d"), AFX_IDP_PARSE_INT, &value); 
else //初始化 
_Afx_DDX_TextWithFormat(pDX, nIDC, _T("%d"), AFX_IDP_PARSE_INT, value); 
} 

③_Afx_DDX_TextWithFormat 

在对话框初始化时,m_bSaveAndValidate参数为FALSE; 

在进行数据读取时,m_bSaveAndValidate参数为TRUE; 

AFX_STATIC void AFX_CDECL _Afx_DDX_TextWithFormat(CDataExchange* pDX, int nIDC, 
LPCTSTR lpszFormat, UINT nIDPrompt, ...) 
// only supports windows output formats - no floating point 
{ 
.... 
//窗口句柄 
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC); 
TCHAR szT[32]; 
if (pDX->m_bSaveAndValidate) 
{ 
//读取 
// the following works for %d, %u, %ld, %lu 
::GetWindowText(hWndCtrl, szT, _countof(szT)); 
if (!_AfxSimpleScanf(szT, lpszFormat, pData)) 
{ 
AfxMessageBox(nIDPrompt); 
pDX->Fail(); // throws exception 
} 
} 
else //对话框初始化时,以成员数据内容初始窗口内容。 
{ 

//初始化窗口内容。 
wvsprintf(szT, lpszFormat, pData); 
AfxSetWindowText(hWndCtrl, szT); 
} 
.... 
} 

3. 数据验证 

流程分析(以整数数值范围验证为例) 

void C????Dlg::DoDataExchange(CDataExchange* pDX) 
{ 
.... 
DDV_MinMaxInt(pDX, m_int, 0, 40); 
.... 
} 
void AFXAPI DDV_MinMaxInt(CDataExchange* pDX, int value, int minVal, int maxVal) 
{ 
ASSERT(minVal <= maxVal); 

//验证 
if (value < minVal || value > maxVal) 
//报错返回 
_AfxFailMinMaxWithFormat(pDX, (long)minVal, (long)maxVal, _T("%ld"), 
AFX_IDP_PARSE_INT_RANGE); 
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值