To reduce the chances of error even further, I lock out an characters that are not actually valid. So for my floating-point control, I disallow all characters except the digits, plus and minus signs, decimal point, and the letters 'e' and 'E'. And backspace. Don't forget backspace!
A common piece of advice that appears is to "put this in the PreTranslateMessage handler of your dialog". This doesn't make any sense to me; it violates any number of issues of abstraction and object orientation. It makes a lot more sense to me to put this in the control that wants to filter the characters. To do this, I write a handler like the one shown below, which appears in my subclassed dialog. This gets created when I add a WM_CHAR handler using ClassWizard, and all I do is fill in the code shown.
void CFloatingEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { switch(nChar) { /* validate */ case _T('+'): case _T('-'): case _T('.'): case _T('E'): case _T('e'): case _T('0'): case _T('1'): case _T('2'): case _T('3'): case _T('4'): case _T('5'): case _T('6'): case _T('7'): case _T('8'): case _T('9'): case _T('\b'): break; default: MessageBeep(0); return; } /* validate */ CEdit::OnChar(nChar, nRepCnt, nFlags); }
All this does is accept the characters shown, and call the superclass handler, or simply issue a beep and return, thus discarding the character.
Summary
This article summarizes a set of techniques I use extensively in the applications I build. I've not seen this set of ideas documented elsewhere, so this seemed a good topic for an essay.
Comments