我将编辑控件子类化为仅接受数字。
此外,在子类化过程中,我解析剪贴板数据以删除禁用的字符。
我已经达到了预期的行为,或者至少我认为,但唯一的问题是我也可以在编辑控件中输入点。
我不知道我的代码有什么问题,所以我在这里发帖,希望别人可以帮助我。
剪贴板解析返回正确的数据,但是WM_CHAR给我带来了麻烦。
请帮助,我无法弄清楚我的代码有什么问题。
谢谢。
以下是子类化过程的代码:
LRESULT CALLBACK MyEditProc ( HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam,
UINT_PTR uIdSubclass,
DWORD_PTR dwRefData )
{
switch (message)
{
case WM_PASTE:
{
if ( OpenClipboard( NULL ) )
{
HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
wchar_t *pchData =
(wchar_t*)GlobalLock(hClipboardData);
GlobalUnlock(hClipboardData);
CloseClipboard();
int i = 0, j = 0;
wchar_t *temp = new wchar_t[51]; // parsed string
memset( temp, '\0', sizeof(temp) );
// integer numbers are parsed here
while( ( i < (int)wcslen(pchData) )
&& ( j < 10 ) ) // I just need first 10
{
if( isdigit( pchData[i] ) )
temp[j++] = pchData[i];
i++;
}
temp[j] = '\0';
// replace selection with parsed text
SendMessage( hwnd, EM_REPLACESEL,
(WPARAM)TRUE, (LPARAM)temp );
// set caret at the end of the text
SendMessage( hwnd, EM_SETSEL, j, j );
delete[] temp;
}
}
return TRUE;
break;
case WM_CHAR:
{
if( ! ( isdigit(wParam)
|| wParam == VK_RETURN
|| wParam == VK_DELETE
|| wParam == VK_BACK )
// this check bellow is needed
// so I can catch WM_PASTE !
&& ( ! ( GetKeyState( VK_CONTROL ) & 0x8000 ) ) )
{
return 0;
}
}
break;
}
return DefSubclassProc( hwnd, message, wParam, lParam);
}
我已经将WM_CREATE的控件子类化为:
SetWindowSubclass( hEdit, MyEditProc, 0, 0);
由于我没有传递任何内容作为上述程序的第4个参数,我觉得不需要调用RemoveWindowSubclass
。
由于Passant先生指出我的解决方案中的错误,我已将其删除,以免混淆阅读此帖的人寻找类似问题的解决方案。
答案 0 :(得分:1)
核心错误是您正在测试WM_CHAR消息处理程序中的虚拟密钥代码。这是不正确的,虚拟键码仅用于WM_KEYDOWN / UP消息。 WM_CHAR获取翻译的击键,由活动键盘布局和键盘状态选择的字符。消息循环中的TranslateMessage()调用可以完成该任务。使用GetKeyState()同样是错误的,这已经由TranslateMessage()完成。
你幸运的是VK_RETURN和VK_BACK,这些虚拟键码与翻译的控制码(0x0d和0x08)具有相同的代码。运气用VK_DELETE运行,它的代码为0x2e,与'.'
字符相同。
正确的代码应该类似于:
case WM_CHAR:
{
if (wParam >= ' ' && !isdigit(wParam) {
return 0;
}
}
break;