MFC对话数据验证在故障时恢复数据

时间:2017-01-24 20:18:46

标签: c++ mfc

如果验证失败,有没有人找到一种方法来恢复编辑框上的值?如果该值无效,则会使用消息框骚扰用户,直到他们修复它为止。

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

1 个答案:

答案 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控件类中)来还原值。

此框架并非专门用于还原不正确的对话框字段值。它提供了更多,因为控件类提供了一些额外的功能。但是,在自定义类中定义控件允许我提供自定义验证。