Introduction
Ever been bothered by message boxes popping up after entering a value in an edit field, telling you that the value is out of range? Or ever got annoyed by a masked edit field while trying to correct a character in the middle of the formatted string? Maybe this approach will give you the solution you where looking for.
The CAutoEdit
class is derived from the normal CEdit
class.
With the method SetValidChar
, you can define which characters may be entered by the user, e.g. numeric characters only, or numeric characters, decimal point and sign, or the characters valid for representing a hexadecimal string. The method SetMaxChar
lets you define the maximal number of characters expected in this field. Is this number reached, the focus is automatically set to the next field, allowing efficient data capturing. The next method SetExitChar
lets you define one additional character which will be used to leave this field, just as pressing the TAB would. This is handy where you want to use the decimal point to skip to the next field etc.
Now the real invention is the error handling: CAutoEdit
is using a validation interface class CEditValidate
with a virtual function validate
. This class can be attached to the CAutoEdit
with the method SetValidationHandler
. Whenever the CAutoEdit
loses the focus, the validation
method of the attached validation interface class is called. Here the contents of the field are validated, formatted and if necessary an error message set. If an error message is generated, two things will happen:
- The focus stays in the erroneous field and the contents will be selected.
- The error message is displayed in a little window just above the faulty field. The class
CInfoWnd
is used for this.
This behavior allows the user to fix the problem without having to get rid of a message box first and trying to remember the message. The message is right there and will only disappear after the field has been corrected. The user will not be able to select any other field before the problem is corrected with the exception of the cancel button.
There are some other methods to define the behavior of the signs, null padding etc., which I will not describe in detail, they are simple to use and easy to understand.
In order to use this class in you own project, you have to include the files autoedit.h, autoedit.cpp, infowmd.h and infownd.cpp. In your dialog, change your CEdit
fields to CAutoEdit
and add the initialization in the OnInitDialog
:
BOOL CTestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_Edit1.SetMaxChars(2);
m_Edit1.SetValidChar(_T("0123456789"));
m_dayValidate = new CDayValidate;
m_Edit1.SetValidationHandler(m_dayValidate);
m_Edit1.SetDefaultValue(_T("01"));
m_Edit1.SetText();
m_Edit2.SetMaxChars(2);
m_Edit2.SetValidChar(_T("0123456789"));
m_monthValidate = new CMonthValidate;
m_Edit2.SetValidationHandler(m_monthValidate);
m_Edit2.SetDefaultValue(_T("01"));
m_Edit2.SetText();
m_Edit3.SetMaxChars(4);
m_Edit3.SetValidChar(_T("0123456789"));
m_yearValidate = new CYearValidate;
m_Edit3.SetValidationHandler(m_yearValidate);
m_Edit3.SetDefaultValue(_T("2000"));
m_Edit3.SetText();
m_Edit4.SetMaxChars(8);
m_Edit4.SetValidChar(_T("10"));
m_binValidate = new CBinValidate;
m_Edit4.SetValidationHandler(m_binValidate);
return TRUE;
}
Of course there are many possible improvements to this class, feel free to use and enhance it, just don't forget to share it here :-)
Problems
There are a few problems worth mentioning, maybe someone finds a (simple?) solution: For one, when a InfoWnd
displays a message and the dialog is moved, the InfoWnd
does not follow the dialog. The other problem is that pressing the 'Enter' key closes the dialog, even if there is still a invalid value in one of the CAutoEdit
fields.
Note: There is one thing to know: You can not have the cancel button immediately following a CAutoEdit
field in the TAB order, otherwise the validation will not work. The reason is that the cancel button is passed to the OnKillFocus
method as the next control. This is used to determine if the user has cancelled the dialog and I can not determine if the user pressed the button or the focus is just passed there because it is the next control in line.