高分 谁能和我说说MFC中函数DoDataExchange 的来龙去脉
我对这个函数不是很了解我明白是负责控件数据和内部某个变量的双向交换的函数但是我实在不懂他的机理似乎很神秘而且是在UpDateData函数中调用的程序员一般不怎么调用就更神...
我对这个函数不是很了解 我明白是负责控件数据和内部某个变量的双向交换的函数 但是我实在不懂他的机理 似乎很神秘 而且是在UpDateData函数中调用的 程序员一般不怎么调用 就更神秘了
高手能不能帮我彻底剖析下这个函数 和 UpDateData函数 我比较笨 最好能详细和通俗点 我一定会追加分数的
小弟谢谢高手了 展开
高手能不能帮我彻底剖析下这个函数 和 UpDateData函数 我比较笨 最好能详细和通俗点 我一定会追加分数的
小弟谢谢高手了 展开
展开全部
对于这个函数,MSDN是这样描述的:Called by the framework to exchange and validate dialog data.大意是框架调用此函数来改写与确认对话框数据。
反正我没明白这句话的意思。
到是看了下DoDataExchange函数里的DDX型函数,似乎明白了DoDataExchange函数的作用。最近看书的效果很明显哇。
按我的理解,DoDataExchange函数其实是一项数据动态绑定技术。比如你在写动态按扭过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的。你要添加新的变量就要用到DoDataExchange函数。
所以你要在对话框的构造函数里面初始化一个变量,再用DoDataExchange函数将它绑定到你的动态按扭中,比如:DDX_Check(pDX, IDC_CHECK1, m_Lesson1);这就是将m_Lesson1(这是一个外部变量,其定义在对话框的构造函数里)绑定到IDC_CHECK1中。
看下DDX_Check函数原型:void AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value);可以看到m_Lesson并不是真的添加到IDC_CHECK1控件里了,注意这是int& value,只是一个值引用而已。差不多的意思就是这个变量被框架传递给控件了。控件只负责使用此变量 ,而不负责改写此变量。-.-
哈哈,写到这里,我也终于明白MSDN那句话的意思了,原来DoDataExchange函数是被框架与控件用来交流数据的。而里面的DDX函数才是动态绑定技术。
值得注意的一点是:MSDN后面附加了一句 Never call this function directly. It is called by the UpdateData member function. Call UpdateData to initialize a dialog box’s controls or retrieve data from a dialog box.就是说此函数永远不被直接调用,它只是呼叫UpdateData函数时才会被调用。(因为每更新一次,它都需要重新绑定一次。是这样子吗?)
总之,这个函数对理解MFC框架是很有用的。对于写控件也是很有用的。
good good study,day day up.....
UpdataData函数内部调用了DoDataExchange。该函数只有一个布尔型参数,它决定了数据传送的方向。调用UpdateData(TRUE)将数据从对话框的控件中传送到对应的数据成员中,调用UpdateData(FALSE)则将数据从数据成员中传送给对应的控件。
UpdateData(false)是将变量的值传到控件.
UpdateData(TRUE)是从控件中取值到关联的变量
反正我没明白这句话的意思。
到是看了下DoDataExchange函数里的DDX型函数,似乎明白了DoDataExchange函数的作用。最近看书的效果很明显哇。
按我的理解,DoDataExchange函数其实是一项数据动态绑定技术。比如你在写动态按扭过程中须对按钮添加变量时,怎么添加?控件类已经写好了,其变量是已经固定的。你要添加新的变量就要用到DoDataExchange函数。
所以你要在对话框的构造函数里面初始化一个变量,再用DoDataExchange函数将它绑定到你的动态按扭中,比如:DDX_Check(pDX, IDC_CHECK1, m_Lesson1);这就是将m_Lesson1(这是一个外部变量,其定义在对话框的构造函数里)绑定到IDC_CHECK1中。
看下DDX_Check函数原型:void AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value);可以看到m_Lesson并不是真的添加到IDC_CHECK1控件里了,注意这是int& value,只是一个值引用而已。差不多的意思就是这个变量被框架传递给控件了。控件只负责使用此变量 ,而不负责改写此变量。-.-
哈哈,写到这里,我也终于明白MSDN那句话的意思了,原来DoDataExchange函数是被框架与控件用来交流数据的。而里面的DDX函数才是动态绑定技术。
值得注意的一点是:MSDN后面附加了一句 Never call this function directly. It is called by the UpdateData member function. Call UpdateData to initialize a dialog box’s controls or retrieve data from a dialog box.就是说此函数永远不被直接调用,它只是呼叫UpdateData函数时才会被调用。(因为每更新一次,它都需要重新绑定一次。是这样子吗?)
总之,这个函数对理解MFC框架是很有用的。对于写控件也是很有用的。
good good study,day day up.....
UpdataData函数内部调用了DoDataExchange。该函数只有一个布尔型参数,它决定了数据传送的方向。调用UpdateData(TRUE)将数据从对话框的控件中传送到对应的数据成员中,调用UpdateData(FALSE)则将数据从数据成员中传送给对应的控件。
UpdateData(false)是将变量的值传到控件.
UpdateData(TRUE)是从控件中取值到关联的变量
展开全部
关于对话框数据交换及验证
对话框的数据交换和验证机制(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);
}
对话框的数据交换和验证机制(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);
}
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
DoDataExchange 是将变量和空间绑定了,
比如DDX_Control(pDX, IDC_SLIDER1, m_fmzl);
这就将IDC_SLIDER1 这个空间和m_fmzl 这个变量一一对应了
一般都是通过ClassWizard添加的,代码自动生成
你什么时候用的时候,只需要UpDateData(true)就将控件的值传给了变量
UpDateData(false)就将变量的值传给了控件
比如DDX_Control(pDX, IDC_SLIDER1, m_fmzl);
这就将IDC_SLIDER1 这个空间和m_fmzl 这个变量一一对应了
一般都是通过ClassWizard添加的,代码自动生成
你什么时候用的时候,只需要UpDateData(true)就将控件的值传给了变量
UpDateData(false)就将变量的值传给了控件
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
UpdateData函数内部以this和UpdateData的参数为参数,构造了一个CDataExchange变量,以类变量的形式保存传入构造的参数。
然后调用DoDataExchange,传入上面的变量。
由于DoDataExchange是虚函数,这就回到了你的类的DoDataExchange中了。
DoDataExchange里面的宏很简单,简单看看就明白了。
然后调用DoDataExchange,传入上面的变量。
由于DoDataExchange是虚函数,这就回到了你的类的DoDataExchange中了。
DoDataExchange里面的宏很简单,简单看看就明白了。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询