我想将编辑控件子类化为蒙版编辑的特定情况 - 接受五个用户输入字符,并在第一个和第三个字符后显示冒号。我可以想象两种基本方法。
我可以将编辑控件存储的文本作为我想要显示的文本。在这种情况下,我需要将文本设置为L" ::"首先,并覆盖检测用户输入的消息,以便我可以将其复制到该字符串中的正确插槽中。但是,我不知道如何确定它们是哪些消息。我假设WM_KEYDOWN是一个,但是如果有其他人,并且我没有全部想到它们,那么触发我错过的消息的输入将错误地推迟到编辑控件的默认处理。
或者,我可以让编辑控件存储的文本是用户输入的文本 - 没有冒号。在这种情况下,我需要覆盖控件的显示方式,这样我就可以生成一个包含基于存储文本的冒号的字符串,并在绘制控件时绘制它。我认为这意味着要替换WM_PAINT处理。问题在于它似乎需要重新定义所有关于控件如何看待自己,当文本是我想要改变的唯一部分时。我不相信我能完美地做到这一点,我当然不会这样做。
我该如何处理?
编辑:我已尝试覆盖WM_PAINT,如下所示:
INT_PTR CALLBACK MaskedEditProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
if (message == WM_PAINT)
{
WCHAR userInput[6];
Edit_GetText(hwndDlg, userInput, 6);
WCHAR displayString[]{L" : : "};
int userInputLength{ Edit_GetTextLength(hwndDlg) };
switch (userInputLength)
{
case 5:
displayString[6] = userInput[4];
case 4:
displayString[5] = userInput[3];
case 3:
displayString[3] = userInput[2];
case 2:
displayString[2] = userInput[1];
case 1:
displayString[0] = userInput[0];
}
Edit_SetText(hwndDlg, displayString);
DefSubclassProc(hwndDlg, message, wParam, lParam);
Edit_SetText(hwndDlg, userInput);
return TRUE;
}
return DefSubclassProc(hwndDlg, message, wParam, lParam);
}
这似乎基本上有效,除了某些原因导致显示的文字闪烁。
编辑2:我将控件的文本设置为L" 0:00:00"从其父窗口,并给它以下窗口过程:
INT_PTR CALLBACK MaskedEditProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam,
UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (message)
{
case WM_CUT:
return 0;
case WM_PASTE:
return 0;
case WM_KEYDOWN:
if (wParam == VK_DELETE)
{
WORD caretPosition{ LOWORD(SendMessage(hwndDlg,EM_GETSEL,0,0)) };
switch (caretPosition)
{
case 7:
return 0;
case 1:
case 4:
SendMessage(hwndDlg, EM_SETSEL, caretPosition + 1, caretPosition + 2);
break;
default:
SendMessage(hwndDlg, EM_SETSEL, caretPosition, caretPosition + 1);
}
return DefSubclassProc(hwndDlg, WM_CHAR, '0', 0);
}
case WM_CHAR:
if (wParam == '\b')
{
WORD caretPosition{ LOWORD(SendMessage(hwndDlg,EM_GETSEL,0,0)) };
switch (caretPosition)
{
case 0:
return 0;
case 2:
case 5:
SendMessage(hwndDlg, EM_SETSEL, caretPosition - 2, caretPosition - 1);
break;
default:
SendMessage(hwndDlg, EM_SETSEL, caretPosition - 1, caretPosition);
}
return DefSubclassProc(hwndDlg, WM_CHAR, '0', 0);
}
else if (iswdigit(wParam))
{
WORD caretPosition{ LOWORD(SendMessage(hwndDlg,EM_GETSEL,0,0)) };
switch (caretPosition)
{
case 1:
case 4:
SendMessage(hwndDlg, EM_SETSEL, caretPosition + 1, caretPosition + 2);
break;
default:
SendMessage(hwndDlg, EM_SETSEL, caretPosition, caretPosition + 1);
}
}
}
return DefSubclassProc(hwndDlg, message, wParam, lParam);
}
这似乎按预期工作,虽然我的退格键一直被打破,所以我还没有测试过那部分。控制也设置为不接受非数字输入,所以我不认为我不会处理这些事实应该打破任何事情。
答案 0 :(得分:0)
我建议您只处理WM_CHAR(以及可能与您的屏蔽相关的自定义消息)。单独保留箭头键,让编辑控件处理它们,并在WM_CHAR处理程序中查询插入符号放置。在您的WM_CHAR中,当展示位置通常会到达冒号时,会发送一个跳过下一个字符位置的EM_SETSEL。