尽管MFC对于对话框数据交换和确认(DDX/DDV)来说大大简化了代码的编写,但是ClassWizard支持的标准确认规则DDV_xxx()函数对于实际应用程序而言太过于简单了,其缺点如下:
1、由于ClassWizard生成的确认代码完全是静态的。然而在在许多应用程序中,某些数据范围可能依赖于当前的上下文变动。例如:在销售管理应用中,最大折扣比例依赖于当前登录用户的权限。
2、单独一个DDV_xxx()函数着眼于单独一个控件从而判断其值是否正确。相反,许多实际中的确认规则必须依据一些控件值之间的关系来检查这些控件值之间的一致性。
对话框的数据交换和确认机制是由对话框类的成员函数DoDataExchange()函数来实现的。通常,当将对话框的控件和成员变量绑定时,ClassWizard自动生产函数中的代码,常常自己书写合适的代码来替换其默认行为。
下面的代码实现以下的确认规则:
如果选择正方形,则X和Y的值必须在100和300之间
如果选择圆形,则X和Y的值必须在0和100之间,且Y必须大于X。
void CDemoDlg::DoDataExchange(CDataExchange* pDX)
{
// 1 - 由ClassWizard生产的标准代码段
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDemoDlg)
DDX_Control(pDX, IDC_SHAPE, m_cmbShape);
DDX_Control(pDX, IDC_Y, m_edtY);
DDX_Control(pDX, IDC_X, m_edtX);
DDX_Text(pDX, IDC_X, m_nX);
DDX_Text(pDX, IDC_Y, m_nY);
DDX_CBIndex(pDX, IDC_SHAPE, m_nShape);
//}}AFX_DATA_MAP
// 2 -自己定制的确认规则
if( m_nShape == CDrawDoc::SQUARE )
{
// 3 - 确认"100 < X < 300"
pDX->PrepareEditCtrl( IDC_X );
DDV_MinMaxInt( pDX, m_nX, 100, 300 );
// 4 - 确认 "100 < Y < 300"
pDX->PrepareEditCtrl( IDC_Y );
DDV_MinMaxInt( pDX, m_nY, 100, 300 );
}
else
{
// 5 - 确认 "0 < X < 100"
pDX->PrepareEditCtrl( IDC_X );
DDV_MinMaxInt( pDX, m_nX, 0, 100 );
// 6 - 确认 "0 < Y < 100"
pDX->PrepareEditCtrl( IDC_Y );
DDV_MinMaxInt( pDX, m_nY, 0, 100 );
// 7 - 确认 "Y >= X" (定制确认)
pDX->PrepareEditCtrl( IDC_Y );
if( pDX->m_bSaveAndValidate && m_nY < m_nX )
{
// 8 - 为用户显示错误信息
CString prompt;
prompt.Format( "Error: Y (%d) should be greater than X (%d).", m_nY, m_nX );
AfxMessageBox( prompt, MB_ICONEXCLAMATION );
prompt.Empty(); // exception prep
// 9 - 确认失败
pDX->Fail(); // note: throws a CUserException
}
}
}
解释:
1、在确认一个控件之前,是调用pDX->PrePareEditCtrl()还是调用pDX->PrePareCtrl()依赖于该控件是否为一个编辑控件。这是必须的,因为只有这样,才能在确认失败的情况下焦点能回到正确的控件上。
CDataExchange::PrepareEditCtrl
HWND PrepareEditCtrl(int nIDC);
throw(CNotSupportedException);
返回值:为DDX或DDV预备的编辑控件HWND。
参数:
nIDC | 为DDX或DDV预备的控件ID。 |
2、当写一个定制块时,开始一般要检查pDX->m_bSaveAndValidate的值,当且仅当该变量的值设置为True时才执行确认代码。当m_bSaveAndValidate为FALSE时,调用DoDataExchange()函数将值从C++对话框的数据成员拷贝到Windows对话框的控件内。