1 / 19

Dialog Field Validation

Dialog Field Validation. Using MFC Data Exchange and Validation Code David J. Kruglinski. Summary. What is field validation? Existing MFC validation support The “Validator Class” solution The CValidDialog class Using CValidDialog in a sample app Cross-validation Technical details

kelvin
Download Presentation

Dialog Field Validation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Dialog Field Validation Using MFC Data Exchange and Validation Code David J. Kruglinski

  2. Summary • What is field validation? • Existing MFC validation support • The “Validator Class” solution • The CValidDialog class • Using CValidDialog in a sample app • Cross-validation • Technical details • The CValidForm class for form-view apps

  3. The Field Validation Problem • More people are using Windows for data entry applications. • Users expect immediate feedback after they make an error in a field. • Windows dialog box prodedure not optimized to support field validation. • Field validation not easy with SDK or MFC.

  4. What is Field Validation? • When the user tries to leave a control (in a dialog box) that contains text (edit control, combobox).... • A function validates the data just entered. • Allows user to leave if data is OK. • Displays message box if data not OK. • Returns user to the same field.

  5. What is Field Validation? • All fields are validated on OK button. • No validation on Escape button. • User is allowed to leave a control when moving to another application.

  6. Existing MFC Validation Support • Validation of all fields on OK button • Derived dialog class has data members corresponding to controls • Generated DDX/DDV code called from OnOK virtual function • Validation is “too late” • No immediate feedback to user • Does allow cross-validation • Full support from ClassWizard

  7. Existing MFC Validation Support • Control subclassing for keystroke validation • CWnd::SubclassDlgItem traps control’s messages before standard WndProc • A derived control class can map messages • Example: A derived CEdit class can accept only numeric keystrokes

  8. The “Validator Class” Solution • Standard base class CValidDialog • CValidDialog base class is MFC’s CDialog. • Your dialog classes should be derived from CValidDialog instead of CDialog. • You override one virtual function, ValidateDlgItem. • #include “valid.h” • Add VALID.CPP to your project.

  9. Sample Application A modal dialog displayed from the main menu

  10. Writing Validation Code • Standard MFC DDX/DDV code • Generated by ClassWizard void CAboutDlg::DoDataExchange(CDataExchange* pDX) { //{{AFX_DATA_MAP(CAboutDlg) DDX_Text(pDX, IDC_EDIT1, m_nEdit1); DDV_MinMaxInt(pDX, m_nEdit1, 0, 10); DDX_Text(pDX, IDC_EDIT2, m_nEdit2); DDV_MinMaxInt(pDX, m_nEdit2, 20, 30); DDX_Text(pDX, IDC_EDIT3, m_strEdit3); DDV_MaxChars(pDX, m_strEdit3, 5); //}}AFX_DATA_MAP }

  11. Writing Validation Code • The ValidateDlgItem function void CAboutDlg::ValidateDlgItem(CDataExchange* pDX, UINT uID) { switch (uID) { case IDC_EDIT1: DDX_Text(pDX, IDC_EDIT1, m_nEdit1); DDV_MinMaxInt(pDX, m_nEdit1, 0, 10); break; case IDC_EDIT2: DDX_Text(pDX, IDC_EDIT2, m_nEdit2); DDV_MinMaxInt(pDX, m_nEdit2, 20, 30); break; case IDC_EDIT3: DDX_Text(pDX, IDC_EDIT3, m_strEdit3); DDV_MaxChars(pDX, m_strEdit3, 5); default: break; } }

  12. Writing Validation Code • Cross-validation • Independent of field validation • Executed on OK button • Code added to end of DoDataExchange • after //}}AFX_DATA_MAP if(pDX->m_bSaveAndValidate) { if(m_nEdit1 + m_nEdit2 < 30) { AfxMessageBox("Sum of Edit1 and Edit2 must be >= 30"); pDX->Fail(); } }

  13. How CValidDialog Works • Traps KILLFOCUS message as user tries to leave control • Controls send “notification” WM_COMMAND messages to their parent dialog window • Edit control sends EN_KILLFOCUS • Calls virtual ValidDlgItem to validate data • MFC exception processing returns user to the field if there is an error

  14. How CValidDialog Works -- Complications • Can’t call CWnd::SetFocus while a KILLFOCUS operation is in progress • Post user-defined message WM_VALIDATE • Handler sets focus back after KILLFOCUS completes • Must recognize the KILLFOCUS that results from the SetFocus call • Use a flag data member, m_bValidateOn

  15. How CValidDialog Works -- Complications • Must regognize a KILLFOCUS when user switches to another app • Can call CWnd::GetParent to test if new parent is our same dialog window • Similar logic for modeless dialogs

  16. MFC Command ProcessingControl Notifications • MFC first processes WM_COMMAND messages with a function CWnd::OnCommand( wParam, lParam) • Both parameters are 32 bits (Win32) • wParam LOWORD = control child window ID • wParam HIWORD = notification code • lParam = control window HWND • Base class handler dispatches command through message map

  17. CValidDialog::OnCommand BOOL CValidDialog::OnCommand(WPARAM wParam, LPARAM lParam) { if(m_bValidationOn) { // might be a killfocus UINT notificationCode = (UINT) HIWORD( wParam ); if((notificationCode == EN_KILLFOCUS) || (notificationCode == LBN_KILLFOCUS) || (notificationCode == CBN_KILLFOCUS) ) { CWnd* pFocus = CWnd::GetFocus(); // if we're changing focus to another control in same dialog if( pFocus && (pFocus->GetParent() == this) ){ if(pFocus->GetDlgCtrlID() != IDCANCEL) { // and focus not in Cancel button // validate AFTER drawing finished PostMessage(WM_VALIDATE, wParam); } } } } return CDialog::OnCommand(wParam, lParam); // pass it on }

  18. CValidDialog::OnValidate • Handler for WM_VALIDATE message ON_MESSAGE(WM_VALIDATE, OnValidate) LONG CValidDialog::OnValidate(UINT wParam, LONG lParam) { TRACE("Entering CValidDialog::OnValidate\n"); CDataExchange dx(this, TRUE); m_bValidationOn = FALSE; // temporarily off UINT controlID = (UINT) LOWORD( wParam ); TRY { ValidateDlgItem(&dx, controlID); } CATCH(CUserException, pUE) { // fall through -- user already alerted via message box } END_CATCH m_bValidationOn = TRUE; return 0; // goes no further }

  19. CFormView Considerations • Same as dialog except use CValidForm derived from MFC CFormView • CValidForm is the new base class for your form views • ValidateDlgItem, OnCommand, OnValidate are the same • Could use multiple inheritance to save code duplication

More Related