I want to create an edit control where users can only type in floating point numbers, but I want to also be able to copy/paste/cut text in this edit. So I subclassed an edit control with the following window procedure:
LRESULT CALLBACK FloatTextboxWindowProc(HWND windowHandle, UINT msg, WPARAM wparam, LPARAM lparam, UINT_PTR subclassId, DWORD_PTR refData)
{
switch (msg)
{
case WM_CHAR:
// If the character isn't a digit or a dot, rejecting it.
if (!(('0' <= wparam && wparam <= '9') ||
wparam == '.' || wparam == VK_RETURN || wparam == VK_DELETE || wparam == VK_BACK))
{
return 0;
}
else if (wparam == '.') // If the digit is a dot, we want to check if there already is one.
{
TCHAR buffer[16];
SendMessage(windowHandle, WM_GETTEXT, 16, (LPARAM)buffer);
// _tcschr finds the first occurence of a character and returns NULL if it wasn't found. Rejecting this input if it found a dot.
if (_tcschr(buffer, TEXT('.')) != NULL)
{
return 0;
}
}
default:
return DefSubclassProc(windowHandle, msg, wparam, lparam);
}
}
This works, aside from the fact that copy/paste/cut operations are blocked. Nothing happens when I try to do them.
This is confusing to me, because Microsoft says these operations are handled by WM_COPY
, WM_PASTE
, and WM_CUT
messages, which I'm not even overriding. But I tested and found that when I type Ctrl+C, Ctrl+V, and Ctrl+X into the edit, it fires a WM_CHAR
message with the key codes VK_CANCEL
, VK_IME_ON
, and VK_FINAL
(may be respectively, I don't remember). Which is weird, because none of these keys sound like they represent these inputs, and nowhere on the Internet does anyone say they do.
If I add the condition that these key codes are passed on to DefSubclassProc()
instead of being rejected, it fixes the problem. But I'm hesitant to just take this fix and move on, because I can't explain why it works, and I don't know what bugs it might introduce, resulting from what these key codes actually mean.
So, why does overriding WM_CHAR
make copy/paste/cut no longer work? And why do these key codes, which seemingly have nothing to do with these inputs, get associated with them? And how might I allow copy/paste/cut in a less hacky way?