第193章 スレッド特異的ホットキー


今回は、スレッド特異的ホットキーについて解説します。 特別なことはありません。

グローバルホットキーは、そのキーの組み合わせが押されれば ホットキーを設定してあるウィンドウがアクティブになりました。 自分では特に、あるメッセージを処理するというようなことは不要でした。 また、押されたホットキーの種類はわかりませんでした。

これに対してスレッド特異的ホットキーとは、そのキーの組み合わせが 押されると自分のスレッドにWM_HOTKEYがきます。 このメッセージを受け取ったら自分のやりたいことをします。

前回使ったホットキー・コントロールを利用してユーザーに スレッド内ホットキーを決定してもらいます。



スレッド特異的ホットキーを設定するにはRegisterHotKey関数を使います。

BOOL RegisterHotKey( HWND hWnd, // 通知を受けるウィンドウハンドル int id, // ホットキーのID UINT fsModifiers, // 修飾キー UINT vk // 仮想キーコード );

hWndは、ホットキーが押されていることを通知されるウィンドウを 指定します。このウィンドウにWM_HOTKEYが届きます。

idは0x0000から0xBFFFの範囲で指定します。同一アプリケーション内では 一意でなくてはいけません。dll内で定義されるホットキーの場合は 0xC000から0xFFFFの範囲で指定します。

fsModifiersは修飾キーでMOD_ALT(ALTキー)、MOD_CONTROL(Ctrlキー)、 MOD_SHIFT(SHIFTキー)の組み合わせを指定します。

成功すると0以外、失敗すると0が返されます。

WM_HOTKEY idHotKey = (int) wParam; fuModifiers = (UINT) LOWORD(lParam); uVirtKey = (UINT) HIWORD(lParam);

idHotKeyはホットキーのIDです。

fuModifiersは修飾キーでMOD_ALT, MOD_CONTROL, MOD_SHIFT, MOD_WIN(ウィンドウキー)の組み合わせです。

uVirtKeyは仮想キーコードです。

では、プログラムを見てみることにします。

// hotkey02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END END POPUP "オプション(&O)" BEGIN MENUITEM "ホットキー設定(&H)", IDM_HOT END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDLG DIALOG DISCARDABLE 0, 0, 154, 49 STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "ホットキー設定" FONT 9, "MS Pゴシック" BEGIN CONTROL "HotKey1",IDC_HOTKEY1,"msctls_hotkey32",WS_BORDER | WS_TABSTOP,7,7,138,15 DEFPUSHBUTTON "OK",IDOK,8,28,50,14 PUSHBUTTON "キャンセル",IDCANCEL,94,28,50,14 PUSHBUTTON "取消",IDC_DEL,62,28,27,14 END

普通のメニューと、ダイアログボックスのリソース・スクリプトです。

// hotkey02.cpp #ifndef STRICT #define STRICT #endif #define ID_HOTKEY 1 #include <windows.h> #include <commctrl.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDlgProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "hotkey02"; //ウィンドウクラス HINSTANCE hInst;

ホットキーのIDをdefineしていることに注意して下さい。 また、commctrl.hをインクルードしているのはホットキー・コントロール を使うためでホットキーそのものとは関係ありません。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 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 = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるホットキー", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ 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 wp, LPARAM lp) { int id; INITCOMMONCONTROLSEX ic; switch (msg) { case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_HOTKEY_CLASS; InitCommonControlsEx(&ic); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_HOT: DialogBox(hInst, "MYDLG", hWnd, (DLGPROC)MyDlgProc); break; } break; case WM_HOTKEY: MessageBox(hWnd, "ホットキーが押されました!", "HOTKEY!", MB_OK); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEのところで、コモンコントロールを初期化しています。

メニューから「ホットキー設定」(IDM_HOT)が選択されたら ダイアログボックスを呼び出します。

ホットキーが押されたら(WM_HOTKEY)「ホットキーが押されました!」と メッセージボックスが出ます。

LRESULT CALLBACK MyDlgProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp) { static HWND hHot, hParent; static WORD wHotKey; UINT uMod = 0; static UINT uModifiers, uVirtual; switch (msg) { case WM_INITDIALOG: hHot = GetDlgItem(hDlg, IDC_HOTKEY1); hParent = GetParent(hDlg); SendMessage(hHot, HKM_SETHOTKEY, (WPARAM)wHotKey, 0); return TRUE; case WM_COMMAND: switch (LOWORD(wp)) { case IDOK: wHotKey = (WORD)SendMessage(hHot, HKM_GETHOTKEY, 0, 0); uModifiers = (UINT)HIBYTE(wHotKey); uVirtual = (UINT)LOBYTE(wHotKey); if (uModifiers & HOTKEYF_ALT) uMod = MOD_ALT; if (uModifiers & HOTKEYF_CONTROL) uMod |= MOD_CONTROL; if (uModifiers & HOTKEYF_SHIFT) uMod |= MOD_SHIFT; if (RegisterHotKey(hParent, ID_HOTKEY, uMod, uVirtual) == 0) MessageBox(hDlg, "Error", "OK", MB_OK); EndDialog(hDlg, IDOK); return TRUE; case IDC_DEL: wHotKey = 0; SendMessage(hHot, HKM_SETHOTKEY, 0, 0); UnregisterHotKey(hParent, ID_HOTKEY); return TRUE; case IDCANCEL: EndDialog(hDlg, IDCANCEL); return TRUE; } return FALSE; } return FALSE; }

メッセージボックスのプロシージャです。

WM_INITDIALOGメッセージが来たら、ホットキーコントロールと 親ウィンドウのハンドルをスタティック変数に保存しておきます。 そして、ホットキー・コントロールにwHotKeyを表示させます。

OKボタンが押されたら、ホットキー・コントロールからホットキーを 取得します。そして、RegisterHotKey関数でホットキーを設定しますが、 WM_SETHOTKEYの時使うHOTKEYF_***とは異なる点に注意して下さい。 ここでは、RegisterHotKey関数の3番目の引数をuModとしています。 uModを設定する為にちょっとめんどうなことをしています。 uModifiersにHOTKEYF_***が含まれるかどうかを調べて もし含まれればuModにMOD_***を加えていきます。 uMod自体はローカル変数でよいのですが、最初に0にしておかないと おかしな結果になります。

「取消」ボタンが押された時はUnregisterHotKey関数でホットキーを 無効にします。

BOOL UnregisterHotKey( HWND hWnd, int id );

hWndはホットキーが関連付けられているウィンドウのハンドルです。

idはホットキーのIDです。

今回は1つのホットキーだけを設定しましたが複数のホットキーを 設定することもできます。ホットキーのIDで区別すればよいですね。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 12/Apr/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。