为了账号安全,请及时绑定邮箱和手机立即绑定

高手能不能帮我彻底剖析下这个函数 和 UpDateData函数 我比较笨 最好能详细和通俗点

高手能不能帮我彻底剖析下这个函数 和 UpDateData函数 我比较笨 最好能详细和通俗点

C++
互换的青春 2022-12-21 19:15:26
我对这个函数不是很了解 我明白是负责控件数据和内部某个变量的双向交换的函数 但是我实在不懂他的机理 似乎很神秘 而且是在UpDateData函数中调用的 程序员一般不怎么调用 就更神秘了 小弟谢谢高手了
查看完整描述

2 回答

?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

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

对话框的数据交换和验证机制(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); 
}

 


查看完整回答
反对 回复 2022-12-25
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

UpdateData函数内部以this和UpdateData的参数为参数,构造了一个CDataExchange变量,以类变量的形式保存传入构造的参数。
然后调用DoDataExchange,传入上面的变量。
由于DoDataExchange是虚函数,这就回到了你的类的DoDataExchange中了。
DoDataExchange里面的宏很简单,简单看看就明白了。

查看完整回答
反对 回复 2022-12-25
  • 2 回答
  • 0 关注
  • 82 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信