グローバルホットキーは、そのキーの組み合わせが押されれば ホットキーを設定してあるウィンドウがアクティブになりました。 自分では特に、あるメッセージを処理するというようなことは不要でした。 また、押されたホットキーの種類はわかりませんでした。
これに対してスレッド特異的ホットキーとは、そのキーの組み合わせが
押されると自分のスレッドにWM_HOTKEYがきます。
このメッセージを受け取ったら自分のやりたいことをします。
前回使ったホットキー・コントロールを利用してユーザーに
スレッド内ホットキーを決定してもらいます。
スレッド特異的ホットキーを設定するにはRegisterHotKey関数を使います。
hWndは、ホットキーが押されていることを通知されるウィンドウを 指定します。このウィンドウにWM_HOTKEYが届きます。BOOL RegisterHotKey( HWND hWnd, // 通知を受けるウィンドウハンドル int id, // ホットキーのID UINT fsModifiers, // 修飾キー UINT vk // 仮想キーコード );
idは0x0000から0xBFFFの範囲で指定します。同一アプリケーション内では 一意でなくてはいけません。dll内で定義されるホットキーの場合は 0xC000から0xFFFFの範囲で指定します。
fsModifiersは修飾キーでMOD_ALT(ALTキー)、MOD_CONTROL(Ctrlキー)、 MOD_SHIFT(SHIFTキー)の組み合わせを指定します。
成功すると0以外、失敗すると0が返されます。
idHotKeyはホットキーのIDです。WM_HOTKEY idHotKey = (int) wParam; fuModifiers = (UINT) LOWORD(lParam); uVirtKey = (UINT) HIWORD(lParam);
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
ホットキーのIDをdefineしていることに注意して下さい。 また、commctrl.hをインクルードしているのはホットキー・コントロール を使うためでホットキーそのものとは関係ありません。// 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;
いつもと同じです。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; }
WM_CREATEのところで、コモンコントロールを初期化しています。//ウィンドウプロシージャ 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; }
メニューから「ホットキー設定」(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関数でホットキーを 無効にします。
hWndはホットキーが関連付けられているウィンドウのハンドルです。BOOL UnregisterHotKey( HWND hWnd, int id );
idはホットキーのIDです。
今回は1つのホットキーだけを設定しましたが複数のホットキーを 設定することもできます。ホットキーのIDで区別すればよいですね。
Update 12/Apr/1999 By Y.Kumei