CreateAcceleratorTable
アクセラレーターもメニュー同様にリソースファイルに定義するのが一般的ですが、 やはりリソースを使わずに作成することができます。 リソースからロードするときはLoadAcceleratorを使いますが、 リソースを使わない場合はCreateAcceleratorTableを使います。
CreateAcceleratorTableの宣言はこのようになっています。
要するにACCEL構造体の配列へのポインタとその要素の数を渡せば作ってくれるようです。 LoadMenuIndirect関数に比べれば楽に作れますね。
HACCEL CreateAcceleratorTable( LPACCEL lpaccl, // pointer to structure array with accelerator data int cEntries // number of structures in the array );
ACCEL構造体は以下のとおりです。
fVirtには同時にAltキーやCtrlキーを押す必要があるとかを示すフラグで、 以下の値を組み合わせます。
typedef struct tagACCEL { // accl BYTE fVirt; WORD key; WORD cmd; } ACCEL;
FNOINVERTは英語ヘルプを読んだのですが意味がよくわかりませんでした...(実験もしてない) (意味がわかる方がいらっしゃいましたら教えてください)。
FALT Altキー FCONTROL Ctrlキー FNOINVERT 他のアクセラレーターと衝突したときにこっちが優先される(?) FSHIFT Shiftキー FVIRTKEY 仮想キーでkeyを定義
keyにはアクセラレーターに割り当てるキーを代入します。 fVirtにFVIRTKEYが含まれていないとF1などが使えないと思うので気をつけてください。
cmdにはWM_COMMANDメッセージのWPARAMのLOWORDに格納される数値で、 メニューアイテムのIDを入れておきます。
以下サンプルです。LoadMenuIndirectのコードを流用しています。
#include<windows.h> #define IDM_OPEN 0x0101 #define IDM_SAVE 0x0102 #define IDM_QUIT 0x0103 #define IDM_FSCREEN 0x0201 LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_COMMAND: switch(LOWORD(wParam)) { case IDM_OPEN: MessageBox(hwnd, "Open", "Test", MB_OK); break; case IDM_SAVE: MessageBox(hwnd, "Save", "Test", MB_OK); break; case IDM_QUIT: MessageBox(hwnd, "終了", "Test", MB_OK); break; case IDM_FSCREEN: MessageBox(hwnd, "全画面表示", "Test", MB_OK); break; } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); } int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { HWND hwnd; HMENU hmenu; HACCEL haccel; WNDCLASS wc; MSG msg; // メニュー const WORD menu_template[] = { //// MENUITEMTEMPLATEHEADER //// 0, // versionNumber version number; must be zero 0, // offset offset first MENUITEMTEMPLATE structure //// MENUITEMTEMPLATE //// MF_POPUP, 0x30d5, 0x30a1, 0x30a4, 0x30eb, '(', '&', 'F', ')', 0, // ファイル 0 , IDM_OPEN , '&', 'O', 'p', 'e', 'n', '\t', 'C', 't', 'r', 'l', '+', 'O', 0, // Open 0 , IDM_SAVE , '&', 'S', 'a', 'v', 'e', '\t', 'C', 't', 'r', 'l', '+', 'S', 0, // Save MF_SEPARATOR, 0 , 0, // セパレータ MF_HILITE , IDM_QUIT , 0x7d42, 0x4e86, '(', '&', 'Q', ')', 0, // 終了 MF_POPUP | MF_HILITE, 0x8868, 0x793a, '(', '&', 'V', ')', 0, // 表示 MF_HILITE , IDM_FSCREEN, 0x5168, 0x753b, 0x9762, 0x8868, 0x793a, 0, // 全画面表示 }; hmenu = LoadMenuIndirect(menu_template); // アクセラレーター ACCEL accel_table[] = { {FVIRTKEY | FNOINVERT | FCONTROL , 'O', IDM_OPEN}, {FVIRTKEY | FNOINVERT | FCONTROL , 'S', IDM_SAVE}, }; haccel = CreateAcceleratorTable(&accel_table[0], sizeof(accel_table)/sizeof(ACCEL)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hThisInstance; wc.hIcon = LoadIcon(NULL, IDI_WINLOGO ); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "Sample"; RegisterClass (&wc); hwnd = CreateWindow (wc.lpszClassName, "サンプル - CreateAcceleratorTable", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 320, 200, NULL, hmenu, hThisInstance, NULL ); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while( GetMessage(&msg, NULL, 0, 0) > 0 ) { if( !TranslateAccelerator(hwnd, haccel, &msg) ) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; }