@DavidHeffernan WM_KILLFOCUSのやり方でフィールドを検証する方法は他にもありますか?
私は提案をすることができます。 EN_CHANGEハンドラでエディットコントロールの入力を検証することができます。ドキュメントから:
編集コントロールでテキストが変更されている可能性がある操作をユーザーが実行したときに送信されます。
ユーザーが何か入力するたびに、データを検証するのに適したこの通知が表示されます。
データが無効の場合は、を無効にします。次のボタンはEnableWindowを使用し、何とかエラーを示します。
EM_SHOWBALLOONTIPを使用すると、ツールチップにエラーメッセージが表示されたり、エディットコントロールの背景色を赤色に変更することができます。
以下は、私の要点を示す小さな例です。もちろん、より良いエラーチェックを追加する必要がありますが、主なアイデアがあります:
#include <windows.h>
#include <CommCtrl.h>
#define IDC_BTN_NEXT 1000
#define IDC_BOX1 2000
#define IDC_BOX2 3000
// enable Visual Styles
#pragma comment(linker, "/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
language='*'\"")
// link with Common Controls library
#pragma comment(lib, "comctl32.lib")
void onBtnNext()
{
MessageBeep(0);
}
void onKillFocus(HWND box)
{
//==================== these are needed to disable Next button
HWND hwnd = ::GetParent(box);
if (NULL == hwnd) // critical error
return; // TODO: add error handling
HWND btnNext = ::GetDlgItem(hwnd, IDC_BTN_NEXT);
if (NULL == btnNext) // critical error
return; // TODO: add error handling
//==============================================================
int len = ::GetWindowTextLength(box);
if (0 == len) // it is ok, empty text, just return
return;
// if possible, use std::wstring here, I assumed you can't...
wchar_t *txt = new wchar_t[len +1];
if (0 == ::GetWindowText(box, txt, len + 1)) // critical error, according to documentation
{
// TODO: add error handling
delete[] txt;
return;
}
//====== simple validation for illustration only, treat uppercase letter as error
int isTextValid = ::isupper(txt[0]);
for (int i = 1; 0 == isTextValid && i < (len + 1); isTextValid = ::isupper(txt[++i]));
delete[] txt;
//==============================================
if (isTextValid)
{
EDITBALLOONTIP ebt;
ebt.cbStruct = sizeof(EDITBALLOONTIP);
ebt.pszText = L" Tooltip text";
ebt.pszTitle = L" Tooltip title";
ebt.ttiIcon = TTI_ERROR_LARGE;
if (!::SendMessage(box, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt))
{
//TODO: tooltip won't show, handle error
}
EnableWindow(btnNext, FALSE); // disable Next button
return; // our work is successfully done
}
if (!::SendMessage(box, EM_HIDEBALLOONTIP, 0, 0))
{
//TODO: tooltip won't hide, handle error
}
EnableWindow(btnNext, TRUE); // enable Next button
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
HWND hwndBox1 = CreateWindowEx(0, WC_EDIT, L"",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
20, 20, 250, 20, hwnd, (HMENU)IDC_BOX1,
((LPCREATESTRUCT)lParam)->hInstance, 0);
if (NULL == hwndBox1) // add better error handling, this is for illustration only
return -1;
HWND hwndBox2 = CreateWindowEx(0, WC_EDIT, L"",
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
20, 50, 250, 20, hwnd, (HMENU)IDC_BOX2,
((LPCREATESTRUCT)lParam)->hInstance, 0);
if (NULL == hwndBox2) // add better error handling, this is for illustration only
return -1;
HWND hwndBtnNext = CreateWindowEx(0, WC_BUTTON, L"Next",
WS_CHILD | WS_VISIBLE | BS_CENTER | BS_DEFPUSHBUTTON,
20, 80, 50, 25, hwnd, (HMENU)IDC_BTN_NEXT,
((LPCREATESTRUCT)lParam)->hInstance, 0);
if (NULL == hwndBtnNext) // add better error handling, this is for illustration only
return -1;
}
return 0L;
case WM_COMMAND:
{
switch (HIWORD(wParam))
{
case BN_CLICKED:
{
if (LOWORD(wParam) != IDC_BTN_NEXT)
break;
onBtnNext();
}
break;
case EN_CHANGE:
{
if (LOWORD(wParam) != IDC_BOX1 && (LOWORD(wParam) != IDC_BOX2))
break;
onKillFocus((HWND)lParam);
}
break;
default:
break;
}
}
break;
case WM_CLOSE:
::DestroyWindow(hwnd);
return 0L;
case WM_DESTROY:
{
::PostQuitMessage(0);
}
return 0L;
default:
return ::DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"Main_Window";
wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
return 0;
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_STANDARD_CLASSES;
InitCommonControlsEx(&iccex);
hwnd = CreateWindowEx(0, L"Main_Window", L"Test",
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION,
50, 50, 305, 160, NULL, NULL, hInstance, 0);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
'WM_KILLFOCUS'で検証するのは面倒です。もし私があなただったら、私はこの問題に対する別の解決策を見つけるでしょう。 –
@DavidHeffernan WM_KILLFOCUSのやり方でフィールドを検証する他の方法について知っていますか?これがチームが悲しいことにしたがっている方法です! https://blogs.msdn.microsoft.com/oldnewthing/20040419-00/?p=39753では、それが悪い方法だと説明しています。彼らはすべて私が2004年に抱えていた問題を経験しました! –
チームにその記事を表示します。次に彼らがどれほど毅然としているかを見てください –