MFC对话框数据验证失败时还原数据

MFC Dialog Data Validation reverting data on failure

本文关键字:数据 还原 失败 验证 对话框 MFC      更新时间:2023-10-16

是否有人找到了在验证失败时恢复编辑框上的值的方法?如果该值无效,它会用消息框骚扰用户,直到他们修复为止

void MyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT_FOO, foo);
DDV_MinMaxFloat(pDX, foo, 0.001f, 300.0f);
}

我能够通过编写自定义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;
}

(注意:我已将与您的问题无关的代码替换为"…")

恢复字段值的工作发生在InvalidRealField ()中。该代码显示一条弹出消息,并使用字段的前一个值(保存在实际的MCReal控件类中)来恢复该值。

此框架不是专门为恢复不正确的对话框字段值而编写的。它提供的远不止这些,因为控制类提供了一些额外的功能。但是,在自定义类中定义控件允许我提供自定义验证。