【C++ Win32】キーボ―ド入力のすべて
サンプルプログラム
#include <windows.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "keyboard"; // ウィンドウクラス BOOL bStart = FALSE, bSeikai = TRUE; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,LPSTR lpsCmdLine, int nCmdShow){ MSG msg; BOOL bRet; if (!InitApp(hCurInst))return FALSE; if (!InitInstance(hCurInst, nCmdShow))return FALSE; while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { break; }else { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int)msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst){ WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = NULL; wc.hCursor = (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = NULL; return (RegisterClassEx(&wc)); } BOOL InitInstance(HINSTANCE hInst, int nCmdShow){ HWND hWnd; hWnd = CreateWindow(szClassName,"KeyBoard", WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,240,180,NULL,NULL, hInst, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ HDC hdc; PAINTSTRUCT ps; MMTIME mm; char tcRe[32]; char *str = "Please Press some key..."; char *str2 = "--> A key was pressed!!"; switch (msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 0, 0, str, (int)strlen(str)); EndPaint(hWnd, &ps); break; case WM_CHAR: switch(wp){ case VK_ESCAPE: PostQuitMessage(0); return 0; case 'A': //SHIFT + Aキーが押された時に実行される hdc = GetDC(hWnd); SetTextColor(hdc, RGB(30, 30, 30)); //文字の色を設定 SetBkColor(hdc, RGB(255, 255, 0)); //文字の背景色を設定 TextOut(hdc, 10, 40, str2, lstrlen(str2)); ReleaseDC(hWnd, hdc); break; default: hdc = GetDC(hWnd); wsprintf(tcRe, "%d", (int)wp); SetTextColor(hdc, RGB(200, 200, 200)); //文字の色を設定 SetBkColor(hdc, RGB(0, 0, 0)); //文字の背景色を設定 TextOut(hdc, 10, 80, tcRe, lstrlen(tcRe)); ReleaseDC(hWnd, hdc); } break; case WM_KEYUP: //何らかのキーが押されたときに発生するイベント break; case WM_KEYDOWN: switch (wp) { // エスケープキーの場合 case VK_ESCAPE: // ウィンドウの閉じるメッセージ送信 MessageBox(hWnd, "エスケープキーが押されたよ", "あああああ", MB_OK); PostQuitMessage(0); return 0; } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }
実行結果
こんな感じです。
Shift+Aを押すと、「--> A key was pressed!!」と表示されます。
EscapeキーでWindowを終了します
解説
キーボードに関する処理は、↑のプログラムでは二つの方法があります。
- WndProc() 関数を使う
- GetKeyState()関数などによって、特定のキーが押されたかどうかを判定する
WndProc()を使って処理する方法
キーボードが押されたときに発生するメッセ―ジは以下のようなものがあります
メッセージ | 説明 |
WM_CHAR | 文字が入力されたときに発生する |
WM_KEYDOWN | 一般キーが押された |
WM_KEYUP | 一般キーが話された |
WM_SYSKEYDOWN | システムキーが押された |
WM_SYSKEYUP | システムキーが離された |
「システムキー」とは Alt と F10キーで、「一般キー」はシステムキー以外のキーです。
それぞれのメッセージにおいて、wParamには仮想キーコードが格納されています。
仮想キーコードにはこのサイトにまとめられています。
【Win32】仮想キーコード 一覧表 | 初心者のWindowsプログラミング日記
WM_CHARとWM_KEYUP(WM_KEYDOWN)の違い
- WM_CHAR→一文字入力されたときに送られる。その時にUnicodeで入力された文字が送られてくる
- WM_KEYUP(WM_KEYDOWN)→キーボードのいずれかのキーが押されたときに送られる。
- 通常、WM_KEYDOWN→WM_CHAR→WM_KEYUPの順にメッセージが送られる
例えば、ユーザーが「A」を入力する間、
- Shiftキーを押す → WM_KEYDOWNメッセージ(Shiftを押したよ)
- 「a」キーを押す → WM_KEYDOWNメッセージ(aを押したよ)→ WM_CHARメッセージ(Unicode文字「A」が入力されたよ)
- 「a」キーを離す → WM_KEYUPメッセージ(aを離したよ)
- Shiftキーを離す→ WM_KEYUPメッセージ(Shiftを離したよ)
という一連のメッセージのやり取りがあります。
WM_CHARメッセージ
WM_CHARメッセージは文字が入力されると発生します。wParamにはその文字のUnicodeが入っています
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){ HDC hdc; switch (msg) { case WM_CHAR: switch (wp) { case 0x08: // backspace. case 0x09: // tab. case 0x0A: // linefeed. case 0x0D: // carriage return. case 0x1B: // escape. case 0x20: // space. break; // Next, handle displayable characters by appending them to our string. default: hdc = GetDC(hWnd); SetTextColor(hdc, RGB(0, 0, 0)); SetBkColor(hdc, RGB(255, 255, 255)); TextOutW(hdc, 0,0, &(wchar_t)wp, 1); ReleaseDC(hWnd, hdc); break; } (以下省略)
上のプログラムは押されたキーボードの文字を表示するプログラムです。aキーを押すと「a」と表示され、Shift+aキーだと「A」と表示されます。
特定の文字が入力されたのかどうかを調べるには、以下の様に行います
(WndProc関数内) switch (msg) { case WM_CHAR: if (wp == 'A') { //Aが入力された(Shift+Aが押された)時にここが実行される }
WM_KEYDOWN(UP)メッセージ
一般キー(Altキー、F10キー以外)が押された時、キーボードフォーカスのあるウィンドウに送られます。
【Win32】仮想キーコード 一覧表 | 初心者のWindowsプログラミング日記
wParamには仮想キーコード(↓1つ下の節参照)が入っているため、下のように書くことができます
switch(msg){ case WM_KEYDOWN: switch(WPARAM){ case VK_ENTER: // エンターキーが押されたときの処理 break; case 0x41: //Aキーが押されたときの処理 break; } }
特定のキーが押されたかをチェック
GetKeyState()関数を使うことで、特定のキーが現在押されているかを調べることができます。
SHORT GetKeyState(int nVirtKey);
引数のnVirtKeyには、押されているかを調べる仮想キーコードを入力します
返り値は、そのキーが押されている時は負の数、押されていない時は0以上です
仮想キーコードは下のようなものがあります
仮想キーコード | 説明 | |
VK_RETURN | エンター | |
VK_SHIFT | シフト | |
VK_CONTROL | コントロール | |
VK_MENU | Alt | |
VK_PAUSE | Pause | |
VK_CAPITAL | Caps Lock | |
VK_ESCAPE | Esc | |
VK_SPACE | スペースキー | |
VK_PRIOR | Pg UP | |
VK_NEXT | Pg Down | |
VK_END | End | |
VK_HOME | Home | |
VK_LEFT | 左方向キー | |
VK_UP | 上方向キー | |
VK_RIGHT | 右方向キー | |
VK_DOWN | 下方向キー | |
VK_INSERT | Insert | |
VK_DELETE | Delete | |
VK_HELP | ヘルプ | |
VK_LWIN | 左Windowsキー | |
VK_RWIN | 右Windowsキー |
そして、通常のキーはasciiのキーコードをもとにしているようです。
- A~Z:0x41~0x5A
- 数字0~9:0x60~0x59
- ファンクションキー(F1~F24)は「VK_F○○」の形になります(例:F2キー→「VK_F2」)
使用例:
if (GetKeyState(VK_CONTROL) < 0) { // Ctrlキーが押されている }else { // Ctrlキーが押されていない }