Introduction
Ever since computers were invented, data validation has been an important concern. When it comes to a user interface, the fastest way to validate data is whilst it is being input. Strange, then, that there is no standard Windows edit control that tackles this problem for any kind of data.
This validating edit control aims to provide the ultimate Framework for data validation, no matter how complex the data you are attempting to input is.
Design Decisions
- Validation must be clean and reliable
- The control should be usable exactly like
CEdit
- Only a handful of visual effects will be included as standard
- 'WM_KILLFOCUS is the wrong time to do field validation'
- Auto-formatting should be easy to add from a derived class
FilterEdit
must stay as simple as possible and not get too bloated!
Intercepted Windows Messages
The following Windows messages are trapped for validation purposes:
EM_REPLACESEL
WM_CLEAR
WM_CHAR
WM_CUT
WM_KEYDOWN
WM_KEYUP
WM_KILLFOCUS
WM_PASTE
WM_SETFOCUS
WM_SETTEXT
... and these are trapped to perform the visual effects:
Windows Message Overrides for Validation
CBaseEdit::OnChar
WM_CHAR
is the Windows message that every validating edit control ever written for Windows must have trapped. This is where a single character can be checked to see if the control will accept it or not.
CBaseEdit::OnKeyDown
WM_KEYDOWN
is where the Delete key, Ctrl-X, Ctrl-C and Ctrl-V are trapped.
CBaseEdit::OnKillFocus
Again, WM_KILLFOCUS
is a very popular message to trap. However, rather than trying to set the focus back to the control in the event that the input is incomplete, we just flag the error and allow the focus to switch normally.
CBaseEdit::OnSetFocus
WM_SETFOCUS
is trapped simply so that we can set any colours we need to and display a tooltip if required.
CBaseEdit::WindowProc
This is where the rest of the Windows messages we are interested in are processed.
How to Derive Your Own Custom Control
Here are the four obvious things you might want to do:
- Override
SemanticCheck
See the CUIntRangeEdit
example to see how this works.
- Trap
WM_CHAR
yourself
By trapping characters yourself, you can automatically format input and perform semantic validation as the user types. Refer to the CDateTimeEdit
example to see how this works.
- Trap
WM_KILLFOCUS
yourself
You may want to perform extra formatting when the user leaves the control. Again, see the CDateTimeEdit
example. Don't forget to call CBaseEdit::OnKillFocus
if you do this!
- Override
SyntaxCheck
This is if you want to pre-process the string
before running the syntax checking. See CDateTimeEdit
for an example.
Example Controls Included in the ZIP
CCurrencyEdit
CDateTimeEdit
CFloatEdit
CIntEdit
CUIntEdit
CUIntRangeEdit
CSpin
Tooltip Support
You might want to explain the data format for your controls at runtime. For this reason, Balloon Help support is included. To include this support, you must call CreateToolTip
:
BOOL CEditTestDlg::OnInitDialog()
{
CDialog::OnInitDialog ();
...
m_DateEdit.CreateToolTip (this, _T("Tooltip text here"));
...
}
The C++ Standard Regular Expression Library
The boost::regex
library has been accepted into the C++ Standard Library. Due to its partial match support, the library is also ideal for this control. Get the Boost library here.
TO DO
- Add more demo controls
- Tutorial for deriving controls
Feedback
All feedback is most welcome!
Revision History
- 1.0.0.0 - 30th July, 2004
- 1.0.3.5 - 8th August, 2007
- BUG FIX: Now using
GetKeyState()
in CBaseEdit::OnKeyDown()
- 1.0.3.6 - 22nd August, 2007
- Now allows user to delete the entire contents of an edit control, regardless of the regex
- 1.0.3.7 - 14th January, 2008
- Changed
CDateEdit
- now CDateTimeEdit
- 1.0.3.8 - 25th February, 2008
- 1.0.3.9 - 13th June, 2008
- Added
bool CDateTimeEdit::GetTimeStamp (SQL_TIMESTAMP_STRUCT *pTS)
- Filter out Ctrl-X, Ctrl-C and Ctrl-V in
CBaseEdit::ValidateChar()
- 1.0.4.0 - 8th August, 2008
- Display tooltip right at the bottom of the edit control to avoid painting overwriting spin control border!
- 1.0.4.1 - 15th September, 2008
- Use system colours as defaults, support
boost::gregorian::date
- 1.0.4.2 - 15th October, 2008
- Dynamic calendar dialog and bitmap for
CDateTimeEdit
(no resource file entries required now)
- 1.0.4.3 - 7th November, 2008
- Fixed assertions in
CDateTimeEdit::WindowProc
- 1.0.4.4 - 5th December, 2008
- Added
boost
posix_time
support to CDateTimeEdit
- 1.0.4.5 - 9th January, 2009
- Allow
WM_SETTEXT
to set an empty string even if regex forbids it
- 1.0.4.6 - 1st May, 2009
- Interface change for Date/Time
Get
functions
- 1.0.4.7 - 7th September, 2009
- Bug fix to
CDateTimeEdit::SyntaxCheck
- 1.0.4.8 - 19th May, 2010
- Adds unsigned support to
FloatEdit
- 1.0.5.0 - 7th October, 2010
- This version extends
CFloatEdit
so that you can specify the number of digits for the whole part
- 1.0.5.1 - 25th October, 2010
- This version fixes a bug in
CDateTimeEdit::SetTime()
- 1.0.5.2 - 26th January, 2011
- This version adds an HHMM mode for times
- 1.0.5.3 - 17th February, 2011
- This version adds the
BS_DEFPUSHBUTTON
style to the calendar button in CDateTimeEdit
- 1.0.5.4 - 21st February, 2011
- Changed the date ordering for
get
/set
functions in CDateTimEdit
to bring it in line with COleDateTime
- 1.0.5.5 - 8th April, 2011
- This update fixes range checking in
CDateTimeEdit::SetTime()
- 1.0.5.6 - 12th September, 2011
- This version adds
SetMin()
and SetMax()
to CDateTimeEdit
and fixes some bugs
- 1.0.5.7 - 3rd October, 2011
- This version fixes a bug in
CDateTimeEdit::SemanticCheck()
- 1.0.5.8 - 4th September, 2022
- Introduced interface
SValidator
so that different types of validator can be used. SRegexValidator
and SGrammarValidator
are use by the demo controls.
- 1.0.5.9 - 6th September, 2022
- Made FilterEdit a DLL. Introduced
CRegexEdit
and renamed CBaseEdit
to CFilterEdit
.
- 1.0.6.0 - 21st January, 2023
- Updated to latest parsertl library.
- 1.0.6.1 - 15th February, 2024
- Updated to use lexertl17 and parsertl17