特殊キーは、WM_SYSKEYDOWNとWM_SYSKEYUPです。 では、サンプルのプログラムを見てみましょう。
いつもと、少し趣を変えてみました。 マクロを使うのでwindowsx.hもインクルードしてあります。// key02.cpp #include <windows.h> #include <windowsx.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); void OnClose(HWND); void OnDestroy(HWND); void OnKeyDown(HWND); void Cls_OnKey(HWND, UINT, BOOL, int, UINT); void Cls_OnSysKey(HWND, UINT, BOOL, int, UINT); void Cls_OnPaint(HWND); char szClassName[] = "key02"; //ウィンドウクラス char str[256];
これは、毎度おなじみのWinMainです。int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!hPrevInst) { if (!InitApp(hCurInst)) return FALSE; } if (!InitInstance(hCurInst, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }
ウィンドウクラスの登録もいつもと同じです。//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }
初期状態のウィンドウは少し小さめにしてみました。//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるキー入力", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 300, //幅 100, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }
//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { HANDLE_MSG(hwnd, WM_CLOSE, OnClose); HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy); HANDLE_MSG(hwnd, WM_KEYDOWN, Cls_OnKey); HANDLE_MSG(hwnd, WM_SYSKEYDOWN, Cls_OnSysKey); HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint); default: return (DefWindowProc(hwnd, msg, wParam, lParam)); } return 0L; }
という感じで使います。 そして、メッセージの種類によってこれを処理するための関数の 引数と戻り値が決められています。 たとえばWM_KEYDOWNではHANDLE_MSG(ウィンドウハンドル, メッセージ, このメッセージを処理する関数);
のように定義されています。 HANDLE_MSG(hwnd, WM_KEYDOWN, fn);としたら、これを処理する関数の 戻り値とか、引数は上のコメントで囲まれたCls_OnKeyと同じにしてやればよいのです。/* void Cls_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) */ #define HANDLE_WM_KEYDOWN(hwnd, wParam, lParam, fn) \ ((fn)((hwnd), (UINT)(wParam), TRUE, (int)(short)LOWORD(lParam), (UINT)HIWORD(lParam)), 0L)
いつもウィンドウプロシージャに書いていた処理も 関数にするとこんな風になります。void OnClose(HWND hwnd) { int id; id = MessageBox(hwnd, (LPCTSTR)"終了してもよいですか", (LPCTSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) DestroyWindow(hwnd); return; }
マクロにするかどうかは、全く趣味の問題です。(本当は16ビットから 32ビットに移行するとき重大な意味がありました。)void OnDestroy(HWND hwnd) { PostQuitMessage(0); return; }
この関数には、vkに仮想キーコードが入っています。16ビットの時は、VK_AとかVK_Bとかいう のがありましたが、32ビットではアスキーコードと同じということでなくなったみたいです。void Cls_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) { char *str_org = "押されたキーは「%c」です。"; char *str_org2 = "押されたキーは、「%s」です。"; if ((vk >= 0x41 && vk <=0x5A) || (vk >= 0x30 && vk <= 0x39)) { wsprintf((LPTSTR)str, (LPCTSTR)str_org, vk); }else { switch(vk) { case VK_TAB: wsprintf((LPSTR)str, (LPCTSTR)str_org2, "TAB"); break; case VK_SHIFT: wsprintf((LPSTR)str, (LPCTSTR)str_org2, "SHIFT"); break; case VK_ESCAPE: wsprintf((LPSTR)str, (LPCTSTR)str_org2, "ESC"); break; default: strcpy(str, "知らないキーです"); break; } } InvalidateRect(hwnd, NULL, TRUE); return; }
if ((vk >= 0x41 && vk <=0x5A) || (vk >= 0x30 && vk <= 0x39))それで、if文を使って分けて処理をしてみました。
ここで特殊キーの処理を自前でしてしまったので、本来の特殊キーの 働きはなくなってしまうことに注意してください。void Cls_OnSysKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) { if (vk == VK_F10) strcpy(str, "F10が押されました。"); if (vk == VK_MENU) strcpy(str, "ALT(GRPH)キーが押されました"); InvalidateRect(hwnd, NULL, TRUE); return; }
今回使ったようなマクロをメッセージ・クラッカーといいます。void Cls_OnPaint(HWND hWnd) { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 10, 10, (LPCTSTR)str, strlen(str)); EndPaint(hWnd, &ps); return; }
[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]
Update May/15/1997 By Y.Kumei