2017-01-24 81 views
0

有沒有人找到一種方法來恢復編輯框上的值,如果驗證失敗?如果該值無效,則會用消息框騷擾用戶,直到他們修復爲止。MFC對話框數據驗證恢復失敗時的數據

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

如果失敗,UpdateData將返回FALSE,因此您可以修復它。調用UpdateData之前,您可以親自驗證控制值。將控件映射到CEdit。您還可以使用PreTranslateMessage並抑制按鍵強制用戶只輸入某些值。 –

回答

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; 
    } 

(注:我已經更換了代碼,不屬於你的問題與「...」)

恢復字段值的工作發生在InvalidRealField()。該代碼顯示一條彈出消息,並使用該字段的先前值(保存在實際的MCReal控件類中)更改之前恢復該值。

此框架並非專門用於恢復不正確的對話框字段值。它提供的遠不止這些,因爲控制類提供了一些額外的功能。但是,如果讓自定義類中定義的控件允許我提供自定義驗證。