アクセラレータ テーブル
アプリケーションでは、多くの場合、[ファイルを開く] コマンドの Ctrl + O などのキーボード ショートカットを定義します。 個々の WM_KEYDOWN メッセージを処理することでキーボード ショートカットを実装できますが、アクセラレータ テーブルは次の優れたソリューションを提供します。
- コーディングが少なくて済みます。
- すべてのショートカットを 1 つのデータ ファイルに統合します。
- 他の言語へのローカライズをサポートします。
- ショートカットとメニュー コマンドで同じアプリケーション ロジックを使用できるようにします。
アクセラレータ テーブルは、Ctrl + O などのキーボードの組み合わせをアプリケーション コマンドにマップするデータ リソースです。 アクセラレータ テーブルの使用方法を確認する前に、リソースの概要を簡単に説明する必要があります。 リソースは、アプリケーション バイナリ (EXE または DLL) に組み込まれているデータ BLOB です。 リソースには、メニュー、カーソル、アイコン、画像、テキスト文字列、カスタム アプリケーション データなど、アプリケーションで必要なデータが格納されます。 アプリケーションは、実行時にバイナリからリソース データを読み込みます。 バイナリにリソースを含めるには、次の操作を行います。
- リソース定義 (.rc) ファイルを作成します。 このファイルは、リソースの種類とその識別子を定義します。 リソース定義ファイルには、他のファイルへの参照を含めることができます。 たとえば、アイコン リソースは .rc ファイルで宣言されていますが、アイコン イメージは別のファイルに格納されます。
- Microsoft Windows リソース コンパイラ (RC) を使用して、リソース定義ファイルをコンパイルされたリソース (.res) ファイルにコンパイルします。 RC コンパイラは、Visual Studio と Windows SDK でも提供されます。
- コンパイルされたリソース ファイルをバイナリ ファイルにリンクします。
これらの手順は、コード ファイルのコンパイル/リンク プロセスとほぼ同じです。 Visual Studio には、リソースを簡単に作成および変更できる一連のリソース エディターが用意されています。 (これらのツールは、Visual Studio の Express エディションでは使用できません。ただし、.rc ファイルは単なるテキスト ファイルであり、構文は MSDN に記載されているため、任意のテキスト エディターを使用して .rc ファイルを作成できます。 詳細については、「 リソース ファイルについて」を参照してください。
アクセラレータ テーブルの定義
アクセラレータ テーブルは、キーボード ショートカットの表です。 各ショートカットは、次の方法で定義されます。
- 数値識別子。 この番号は、ショートカットによって呼び出されるアプリケーション コマンドを識別します。
- ショートカットの ASCII 文字または仮想キー コード。
- 省略可能な修飾子キー: Alt、Shift、または Ctrl。
アクセラレータ テーブル自体には、アプリケーション リソースの一覧内のテーブルを識別する数値識別子があります。 簡単な描画プログラム用のアクセラレータ テーブルを作成しましょう。 このプログラムには、描画モードと選択モードの 2 つのモードがあります。 描画モードでは、ユーザーは図形を描画できます。 選択モードでは、ユーザーは図形を選択できます。 このプログラムでは、次のキーボード ショートカットを定義します。
ショートカット | command |
---|---|
Ctrl + M | モードを切り替えます。 |
F1 | 描画モードに切り替えます。 |
F2 | 選択モードに切り替えます。 |
まず、テーブルとアプリケーション コマンドの数値識別子を定義します。 これらの値は任意です。 識別子のシンボリック定数は、ヘッダー ファイルで定義することで割り当てることができます。 次に例を示します。
#define IDR_ACCEL1 101
#define ID_TOGGLE_MODE 40002
#define ID_DRAW_MODE 40003
#define ID_SELECT_MODE 40004
この例では、値 IDR_ACCEL1
によってアクセラレータ テーブルが識別され、次の 3 つの定数によってアプリケーション コマンドが定義されます。 規則により、リソース定数を定義するヘッダー ファイルには、多くの場合、resource.h という名前が付けられます。 次の一覧は、リソース定義ファイルを示しています。
#include "resource.h"
IDR_ACCEL1 ACCELERATORS
{
0x4D, ID_TOGGLE_MODE, VIRTKEY, CONTROL // ctrl-M
0x70, ID_DRAW_MODE, VIRTKEY // F1
0x71, ID_SELECT_MODE, VIRTKEY // F2
}
アクセラレータのショートカットは、中かっこ内で定義されます。 各ショートカットには、次のエントリが含まれています。
- ショートカットを呼び出す仮想キー コードまたは ASCII 文字。
- アプリケーション コマンド。 この例ではシンボリック定数が使用されていることに注意してください。 リソース定義ファイルには resource.h が含まれています。ここで、これらの定数が定義されています。
- VIRTKEY キーワード (keyword)は、最初のエントリが仮想キー コードであることを意味します。 もう 1 つのオプションは、ASCII 文字を使用することです。
- 省略可能な修飾子: Alt、CONTROL、または Shift。
ショートカットに ASCII 文字を使用する場合、小文字は大文字とは異なるショートカットになります。 (たとえば、「a」と入力すると、"A" と入力した場合とは異なるコマンドが呼び出される場合があります)。これはユーザーを混乱させる可能性があるため、一般に、ショートカットには ASCII 文字ではなく仮想キー コードを使用することをお勧めします。
アクセラレータ テーブルの読み込み
アクセラレータ テーブルのリソースは、プログラムで使用する前に読み込む必要があります。 アクセラレータ テーブルを読み込むには、 LoadAccelerators 関数を 呼び出します。
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
メッセージ ループに入る前に、この関数を呼び出します。 最初のパラメーターは、モジュールへのハンドルです。 (このパラメーターは WinMain 関数に渡されます。詳細については、「 WinMain: アプリケーション エントリ ポイント」を参照してください。2 番目のパラメーターはリソース識別子です。 関数は、リソースへのハンドルを返します。 ハンドルは、システムによって管理されるオブジェクトを参照する不透明な型であることを思い出してください。 関数が失敗した場合は、 NULL を返します。
DestroyAcceleratorTable を呼び出すことで、アクセラレータ テーブルを解放できます。 ただし、プログラムの終了時にテーブルが自動的に解放されるため、この関数を呼び出す必要があるのは、あるテーブルを別のテーブルに置き換える場合だけです。 この興味深い例は、 トピック「Creating User Editable Accelerators(ユーザー編集可能アクセラレータの作成)」にあります。
キー ストロークをコマンドに変換する
アクセラレータ テーブルは、キー ストロークを WM_COMMAND メッセージに変換することによって機能します。
WM_COMMAND の wParam パラメーターには、コマンドの数値識別子が含まれています。 たとえば、前に示したテーブルを使用すると、キー ストローク Ctrl + M は、値 ID_TOGGLE_MODE
を持つWM_COMMAND メッセージに変換されます。 これを行うには、メッセージ ループを次のように変更します。
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(win.Window(), hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
このコードは、メッセージ ループ内の TranslateAccelerator 関数への呼び出しを追加します。 TranslateAccelerator 関数は、各ウィンドウ メッセージを調べて、キーダウン メッセージを探します。 ユーザーがアクセラレータ テーブルに一覧表示されているキーの組み合わせのいずれかを押すと、 TranslateAccelerator によって ウィンドウにWM_COMMAND メッセージが送信されます。 この関数は、ウィンドウ プロシージャを直接呼び出して WM_COMMAND を送信します。 TranslateAccelerator がキー ストロークを正常に変換すると、関数は 0 以外の値を返します。つまり、メッセージの通常の処理をスキップする必要があります。 それ以外の場合、 TranslateAccelerator は 0 を返します。 その場合は、通常どおり、ウィンドウ メッセージを TranslateMessage と DispatchMessage に渡します。
描画プログラムが WM_COMMAND メッセージを処理する方法を次に示します。
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DRAW_MODE:
SetMode(DrawMode);
break;
case ID_SELECT_MODE:
SetMode(SelectMode);
break;
case ID_TOGGLE_MODE:
if (mode == DrawMode)
{
SetMode(SelectMode);
}
else
{
SetMode(DrawMode);
}
break;
}
return 0;
このコードでは、 SetMode
が 2 つのモードを切り替えるためにアプリケーションによって定義された関数であることを前提としています。 各コマンドの処理方法の詳細は、明らかにプログラムによって異なります。
次へ