我想创建一个编辑控件,用户只能在其中输入浮点数,但我也希望能够在此编辑中复制/粘贴/剪切文本。因此,我使用以下窗口过程对编辑控件进行了子类化:
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);
}
}
这有效,除了复制/粘贴/剪切操作被阻止的事实。当我尝试这样做时,什么也没有发生。
这让我很困惑,因为微软说这些操作是由WM_COPY
、WM_PASTE
和WM_CUT
消息处理的,我什至没有覆盖它们。但我测试发现,当我在编辑中输入Ctrl+C、Ctrl+V和时Ctrl+X,它会触发一条WM_CHAR
带有键码VK_CANCEL
、VK_IME_ON
和的消息VK_FINAL
(可能分别是,我不记得了)。这很奇怪,因为这些键听起来都不像代表这些输入,而且互联网上没有任何人说它们代表这些输入。
如果我添加这些关键代码被传递DefSubclassProc()
而不是被拒绝的条件,它可以解决问题。但是我很犹豫是否接受这个修复并继续前进,因为我无法解释它为什么会起作用,而且我不知道它可能会引入什么错误,这是由这些关键代码的实际含义引起的。
那么,为什么覆盖WM_CHAR
使复制/粘贴/剪切不再起作用?为什么这些看似与这些输入无关的关键代码会与它们相关联?以及如何以一种不那么老套的方式允许复制/粘贴/剪切?