SAMPLE: Control-by-Control Validation in MFC
ID: Q114962
|
The information in this article applies to:
-
The Microsoft Foundation Classes (MFC), included with:
-
Microsoft Visual C++ for Windows, 16-bit edition, versions 1.0, 1.5
SUMMARY
The FCSVAL sample application was created to show how an application can do
control-by-control validation in a dialog box.
MORE INFORMATION
The following file is available for download from the Microsoft Software
Library:
FCSVAL.EXE
For more information about downloading files from the Microsoft Software
Library, please see the following article in the Microsoft Knowledge Base:
Q119591 How to Obtain Microsoft Support Files from Online Services
The application itself is just a modal dialog box displayed by the
CWinApp::InitInstance(). After displaying the dialog box, InitInstance()
simply quits the application.
The important part of the sample takes place in the dialog-box class
implementation: There are two edit controls. The first takes input of an
integer between 1 and 20. The second takes a character string as input with
length less than or equal to 5. When you Tab or mouse-click from control to
control within the displayed dialog box, the contents of the control that
is losing focus are validated.
The CFocusDlg Class
The application's functionality centers around the CFocusDlg class and its
implementation of four message handlers (discussed below). Normal data
exchange (DDX) and validation (DDV) using the routines provided by MFC take
place in OnInitialUpdate(), when the dialog box is first displayed, and
when the user chooses the OK button to accept the input. This is default
behavior provided by ClassWizard when member variables are connected to
dialog-box controls and can be examined in the dialog class
DoDataExchange() function.
Special Case 1
The first special case, for which this sample is written, involves
validating control contents when switching focus from one control to the
next. This is done by handling the EN_KILLFOCUS notification sent by the
edit control that is losing focus. The idea here is to check the
contents and, if they are not valid, to display the message box, inform
the user, and then set the focus back to the control from which it came.
Unfortunately, some difficulties arise when trying to set the focus (or
display the message boxes) within a killfocus message handler. At this
point, Windows is in an indeterminate state as it is moving focus from
one control to the other. This is a bad place to do the validation and
SetFocus() call.
The solution here is to post a user-defined message to the dialog box
(parent) and do the validation and SetFocus() there, thus waiting for a
safer time to do the work. (See "CFocusDlg::OnEditLostFocus()" in the
file FOCUSDLG.CPP and "WM_EDITLOSTFOCUS user-defined message" in the
file FOCUSDLG.H.)
Another thing you will notice about this function is that it uses
TRY/CATCH to do the validation. The provided DDX/DDV routines throw
CUserExceptions when failing to validate or load a control's data. You
should catch these and do the SetFocus() in the CATCH block.
Special Case 2
The second special case is when the user clicks the Cancel button while
there is still invalid data in one of the controls. In this situation,
the user (normally) does not want to know whether his or her input is
correct because he or she is quitting the application. You might
consider prompting the user to save and validate the input, but normally
"Cancel" means what it says. Focus is sent to the Cancel button before
the IDCANCEL notification is sent to the dialog box, causing
EN_KILLFOCUS to be generated by the control.
Because we want to control validation, we maintain a flag called
"m_bValidate". When the user clicks Cancel, the dialog box is notified
of the mouse-click by the child button through a WM_PARENTNOTIFY
message. If we handle this message, we can set the m_bValidate flag to
"FALSE", which prevents the validation from taking place in the
OnEditLostFocus() function. Notice the "if (m_bValidate)" right at the
beginning.
Special Case 3
The third special case is when the user inputs bad data and then decides
to bring another application to the foreground, possibly to do some
other work or check some other information before completing this dialog
box' form. The edit control generates a EN_KILLFOCUS when the
application loses activation but, again, you might not necessarily want
to validate. So, handle the WM_ACTIVATEAPP message and based on the
bActive flag that is passed as a parameter, set the "m_bValidate" flag
to disable validation. Upon reactivation, the same message gets handled
and this time the bActivate flag is TRUE, causing us to re-enable
validation.
Special Case 4
The fourth special case is when the user ends the Windows session either
through the Program Manager or the ExitWindows() function. In this case,
handle the WM_QUERYENDSESSION message. If the dialog-box controls pass
validation (coded like the OnOK() function), then return TRUE from this
handler to allow Windows to terminate. Otherwise, return FALSE so that
the user can input the correct data.
Additional query words:
kbinf killfocus queryendsession parentnotify
Keywords : kb16bitonly kbMFC KbUIDesign kbVC
Version : 1.00 1.50
Platform : WINDOWS
Issue type :
Last Reviewed: August 5, 1999