如果验证失败,有没有人找到一种方法来恢复编辑框上的值?如果该值无效,则会使用消息框骚扰用户,直到他们修复它为止。
void MyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_FOO, foo);
DDV_MinMaxFloat(pDX, foo, 0.001f, 300.0f);
}
答案 0 :(得分:4)
我能够通过编写自定义DDX_处理程序来完成此操作。我所使用的应用程序使用了一个自定义控件(从CEdit派生的MCReal),它只接受控件中定义的可接受范围之间的十进制值。当用户输入非十进制值或超出范围的值时,代码将弹出自定义消息并还原输入到对话框字段中的值。
这是通过创建自定义控件和自定义验证处理程序来完成的。这是DDX_例程的样子:
void AFXAPI_EXPORT DDX_ProcessEditReal(CDataExchange* pDX, int nIDC, MCReal& mcr)
{
// prepare edit control
HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
// does control exist yet?
if (!IsWindow(mcr.m_hWnd))
{
// subclass the control
if (!mcr.SubclassWindow(hWndCtrl))
{
ASSERT(false);
// possibly trying to subclass twice?
AfxThrowNotSupportedException();
}
return;
}
if (!ValidateMCRealCtrl (mcr, pDX->m_pDlgWnd, (pDX->m_bSaveAndValidate == TRUE)))
{
pDX->Fail ();
}
}
我使用标准的DDX_例程作为编写自定义版本的起点。真正的工作是在ValidateMCRealCtrl()
:
bool ValidateMCRealCtrl (MCReal &mcRealCtrl, CWnd *pParentWnd, bool bSaveAndValidate)
{
CString ctext;
double val = 0.0, r = 0.0;
double unit_factor = 0.0;
bool bDmsrg = false;
bool rc = false;
bool ret;
...
if (bSaveAndValidate) // Move from dialog to data
{
if (pParentWnd != nullptr && mcRealCtrl.CancelButtonClicked (pParentWnd))
{
return true;
}
if (!mcRealCtrl.IsWindowEnabled () || !mcRealCtrl.IsWindowVisible ())
{
return true;; // don't update if not enabled
}
mcRealCtrl.GetWindowText (ctext);
...
// base field validation.
ret = mcRealCtrl.Validate ();
if (!ret)
{
make_mcreal_str (r, ctext.GetBuffer (mcRealCtrl.maxlen), mcRealCtrl.maxlen, prec, mcRealCtrl.add_plus,
mcRealCtrl.m_strip_trailing == TRUE);
ctext.ReleaseBuffer ();
InvalidRealField (mcRealCtrl); // Bad value
return false; // Reset Focus
}
...
ctext.ReleaseBuffer ();
mcRealCtrl.SetWindowText (ctext);
}
else // Move from data to dialog
{
if (mcRealCtrl.angle) // If angle field...
{
val = mcRealCtrl.value * R2D; // Convert to degrees
}
else
{
val = mcRealCtrl.value; // Use data value
}
make_mcreal_str (val, ctext.GetBuffer (mcRealCtrl.maxlen), mcRealCtrl.maxlen, prec, mcRealCtrl.add_plus,
mcRealCtrl.m_strip_trailing == TRUE);
ctext.ReleaseBuffer ();
mcRealCtrl.SetWindowText (ctext);
mcRealCtrl.SetLimitText (mcRealCtrl.maxlen);
}
...
return true;
}
(注意:我已经用&#34替换了与您的问题无关的代码; ...")
恢复字段值的工作发生在InvalidRealField ()
。该代码显示弹出消息,并在更改之前使用字段的先前值(保存在实际MCReal控件类中)来还原值。
此框架并非专门用于还原不正确的对话框字段值。它提供了更多,因为控件类提供了一些额外的功能。但是,在自定义类中定义控件允许我提供自定义验证。