The ES_
NUMBER
edit control style limits typed input to digits, but what if you also want to accept negative numbers? How can we extend¹ ES_
NUMBER
to accept the minus sign?
The ES_
NUMBER
edit control style works by altering the behavior of the edit control when it receives a WM_
CHAR
. You can do that too!
Subclass the edit control and handle the WM_
CHAR
message by checking whether the character is a digit or a minus sign. If not, then beep and return. Otherwise, let the message through.
LRESULT CALLBACK SignedIntegerSubclassProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { switch (uMsg) { case WM_NCDESTROY: RemoveWindowSubclass(hwnd, SignedIntegerSubclassProc, uIdSubclass); break; case WM_CHAR: { wchar_t ch = (wchar_t)wParam; if (ch < L' ') break; // let control character through else if (ch == L'-') break; // let hyphen-minus through else if (ch == L'\x2212') break; // let Unicode minus sign through else if (IsUnicodeDigit(ch)) break; // let digit through MessageBeep(0); // otherwise invalid return 0; } } return DefSubclassProc(hwnd, uMsg, wParam, lParam); } BOOL EnforceSignedIntegerEdit(HWND hwnd) { return SetWindowSubclass(hwnd, SignedIntegerSubclassProc, 0, 0); }
If the user entered a character, then we let it through if it is one of the following:
- A control character, to permit Ctrl+A, Ctrl+C, Bksp, Tab, and so on.
- Unicode character U+002D HYPHEN-MINUS, which is what most people think of as a minus sign.
- Unicode character U+2212 MINUS SIGN, which is a true minus sign.
¹ As noted in the documentation, the ES_
NUMBER
edit control style doesn’t prevent the user from putting non-digits into the edit control by other means, like pasting with Ctrl+V. The exercise is to extend the existing behavior of the ES_
NUMBER
style, not to fix it to cover all the other scenarios. Our technique has the same defects as ES_
NUMBER
, but at least it’s the same defects.
0 comments