当前位置:C++技术网 > 资讯 > UpdateData函数运行机制及源代码详解

UpdateData函数运行机制及源代码详解

更新时间:2016-02-21 22:21:49浏览次数:1+次

采用GetDlgItem方法可以获得对话框的子控件窗口。获得控件窗口后,就可以用CWnd的各种方法进行操作,譬如SetWindowText等等。这种方式可以实现在对话框成员与控件窗口之家进行数据交换。这种方法比较繁琐,因此MFC为我们提供了一个更简单地方法,就是CWnd::UpdateData方法。它接受一个BOOL参数指示数据传递的方向。如果传入的参数为TRUE,则将根据控件设置对话框成员;否则根据数据成员设置对话框控件。

CWnd::UpdateData方法还有一个额外的好处就是支持数据验证,其实也就是断言(assert)在这里就不说这个方面了。我们看看UpdateData的实现细节:

BOOL CWnd::UpdateData(BOOL bSaveAndValidate) { ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal? CDataExchange dx(this, bSaveAndValidate); // prevent control notifications from being dispatched during UpdateData _AFX_THREAD_STATE* pThreadState = AfxGetThreadState(); HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow; ASSERT(hWndOldLockout != m_hWnd); // must not recurse pThreadState->m_hLockoutNotifyWindow = m_hWnd; BOOL bOK = FALSE; // assume failure TRY { DoDataExchange(&dx); bOK = TRUE; // it worked } CATCH(CUserException, e) { // validation failed - user already alerted, fall through ASSERT(!bOK); // Note: DELETE_EXCEPTION_(e) not required } AND_CATCH_ALL(e) { // validation failed due to OOM or other resource failure e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE); ASSERT(!bOK); DELETE_EXCEPTION(e); } END_CATCH_ALL pThreadState->m_hLockoutNotifyWindow = hWndOldLockout; return bOK; }

从实现代码可以看出,数据交换与验证主要用到数据交换对象CDataExchange,并以该对象为参数调用DoDataExchange。也就是说呢,我们调用UpdateData函数其实是调用DoDateDataExchange函数。CDataExchange对象的m_nSaveAndValidate指示数据交换方向。m_pDlgWnd表示进行数据交换与验证的目标对话框。那么接下来我们看看DoDataExchange函数:

_AFXWIN_INLINE void CWnd::DoDataExchange(CDataExchange*) { } // default does nothing

看到这里,你也就应该懂了,DoDataExchange函数又是调用了DDX_Text函数,那么,我们右键查看头文件,就能看到一系列的DDX_XXX函数了:

接下来我们看看DDX_Text函数的源代码:

void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value) { HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC); if (pDX->m_bSaveAndValidate) { int nLen = ::GetWindowTextLength(hWndCtrl); ::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1); value.ReleaseBuffer(); } else { AfxSetWindowText(hWndCtrl, value); } }

这代码实现可谓是一目了然。因此,看到这里,我们应该秒懂了,我们用UpdateData函数来实现数据交换,其实就是DDX_XXX函数来帮我们做的,而代码实现则是非常简单。