//===============类申明===============================
class CDataExchange
{
// Attributes
public:
BOOL m_bSaveAndValidate; // TRUE => save and validate data 读写方向标志
CWnd* m_pDlgWnd; // container usually a dialog 对话框对象
// Operations (for implementors of DDX and DDV procs)
HWND PrepareCtrl(int nIDC); //取得控件窗口句柄
HWND PrepareEditCtrl(int nIDC); //内部调用PrepareCtrl()
void Fail(); // will throw exception
CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate);
#ifndef _AFX_NO_OCC_SUPPORT
COleControlSite* PrepareOleCtrl(int nIDC); // for OLE controls in dialog
#endif
// Implementation
UINT m_idLastControl; // last control used (for validation)
BOOL m_bEditLastControl; // last control was an edit item
};
//===============CPP实现===============================
CDataExchange::CDataExchange(CWnd* pDlgWnd, BOOL bSaveAndValidate)
{
ASSERT_VALID(pDlgWnd);
m_bSaveAndValidate = bSaveAndValidate;
m_pDlgWnd = pDlgWnd;
m_idLastControl = 0;
}
HWND CDataExchange::PrepareEditCtrl(int nIDC)
{
HWND hWndCtrl = PrepareCtrl(nIDC);
m_bEditLastControl = TRUE;
return hWndCtrl;
}
HWND CDataExchange::PrepareCtrl(int nIDC)
{
ASSERT(nIDC != 0);
ASSERT(nIDC != -1); // not allowed
HWND hWndCtrl;
COleControlSite* pSite = NULL;
m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
if (hWndCtrl == NULL)
{
// Could be a windowless OCX
pSite = m_pDlgWnd->GetOleControlSite(nIDC);
if (pSite == NULL)
{
TRACE(traceAppMsg, 0, "Error: no data exchange control with ID 0x%04X.\n", nIDC);
ASSERT(FALSE);
AfxThrowNotSupportedException();
}
}
m_idLastControl = nIDC;
m_bEditLastControl = FALSE; // not an edit item by default
return hWndCtrl;
}
void CDataExchange::Fail()
{
if (!m_bSaveAndValidate)
{
TRACE(traceAppMsg, 0, "Warning: CDataExchange::Fail called when not validating.\n");
// throw the exception anyway
}
else if (m_idLastControl != NULL)
{
// restore focus and selection to offending field
HWND hWndLastControl;
m_pDlgWnd->GetDlgItem(m_idLastControl, &hWndLastControl);
if (hWndLastControl != NULL)
{
::SetFocus(hWndLastControl);
if (m_bEditLastControl) // select edit item
::SendMessage(hWndLastControl, EM_SETSEL, 0, -1);
}
}
else
{
TRACE(traceAppMsg, 0, "Error: fail validation with no control to restore focus to.\n");
// do nothing more
}
AfxThrowUserException();
}
//===============调用===============================
BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
{
CDataExchange dx(this, bSaveAndValidate);
DoDataExchange(&dx);
return bOK;
}
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMFCTest2Dlg)
DDX_Text(pDX, IDC_ENTER, m_Enter);
DDX_Control(pDX, IDOK, m_OK);
DDV_MinMaxInt(pDX, m_edit2, 1, 10);
//}}AFX_DATA_MAP
}
void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value)
{
//根据nIDC取得对话框控件
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
//从控件取得数据赋给Value
if (pDX->m_bSaveAndValidate)
{
int nLen = ::GetWindowTextLength(hWndCtrl);
::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
value.ReleaseBuffer();
}
//将值赋给控件
else
{
AfxSetWindowText(hWndCtrl, value);
}
}
void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)
{
//只子类化一次
if (rControl.m_hWnd == NULL) // not subclassed yet
{
HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
rControl.SubclassWindow(hWndCtrl);
}
}
void AFXAPI DDV_MinMaxInt(CDataExchange* pDX, int value, int minVal, int maxVal)
{
ASSERT(minVal <= maxVal);
if (value < minVal || value > maxVal)
_AfxFailMinMaxWithFormat(pDX, minVal, maxVal, _T("%I64d"),
AFX_IDP_PARSE_INT_RANGE);
}