2017-01-24 2 views
0

Кто-нибудь нашел способ вернуть значение в поле редактирования, если он не прошел проверку? Если значение недействительно, оно преследует пользователя с помощью ящиков сообщений, пока они не исправят его.MFC Dialog Data Validation, возвращающий данные при сбое

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_. В приложении, в котором я работал, использовался пользовательский элемент управления (MCReal, полученный из CEdit), который будет принимать только десятичные значения между допустимым диапазоном, определенным в элементе управления. Когда пользователь вводит не десятичное значение или значение вне диапазона, код выдает собственное сообщение и возвращает значение, введенное в поле диалога.

Это было выполнено путем создания настраиваемого элемента управления и специального обработчика проверки. Вот что процедура 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) до его изменения, чтобы вернуть значение.

Эта структура не была написана специально, чтобы вернуть неправильные значения полей диалога. Он обеспечивает гораздо больше, чем это, поскольку класс управления предоставляет некоторые дополнительные возможности. Однако наличие элемента управления, определенного в пользовательском классе, позволило мне выполнить выборочную проверку.

Смежные вопросы