说说DoDataExchange(CDataExchange* pDX)
DoDataExchange(CDataExchange* pDX) 是MFC CWnd的一个重要的函数。
在此函数中可以利用一系列的DDX_xxxx(..)函数实现UI与data的数据交互,以及用DDV_xxx(...)来实现数据验证。如:
// simple text operations
void
AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, BYTE& value);// special control types
void
AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value);// number of characters
void
AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars);....
这些DDV可能并不能满足我们的需要。但可以利用CDataExchange类型的参数pDX,在DoDataExchange中实现自己的数据验证。利用 pDX->m_bSaveAndValidate判断是UpdateData(TRUE)还是UpdateData(FALSE)。如果验证失败触发pDX->Fail()即可。
// CDataExchange - for data exchange and validation
class
CDataExchange{
// Attributes
public
:BOOL m_bSaveAndValidate; // TRUE => save and validate data
// Operations (for implementors of DDX and DDV procs)
CWnd* m_pDlgWnd; // container usually a dialog
HWND PrepareCtrl(int nIDC); HWND PrepareEditCtrl(int nIDC); void Fail(); // will throw exception
CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);
COleControlSite* PrepareOleCtrl(int nIDC); // for OLE controls in dialog
// Implementation
UINT m_idLastControl; // last control used (for validation)
BOOL m_bEditLastControl; // last control was an edit item
};
值得注意的是PrepareXXX函数。其作用是当数据验证失败后,焦点能够恢复到失败的控件之上。自定义的数据验证函数可以有如下结构:
template< class T>
void DDV_MyValidate(CDataExchange* pDX, UINT nCtrlID, T& data...)
{
pDX->PrepareCtrl(nCtrlID);
if(pDX->m_bSaveAndValidate)
{
bool bValid = .....;
if( !bValid)
pDX->Fail();
else
data = ...; // get data from UI
}
else
{
// set data to contorl
}
}