[index] [詰め合わせ] [ダイアログボックス] [メニュー] [アクセラレータ] [String Table] [その他]
アクセラレータ(accelerator)
アクセラレータは、通常のアルファベットキーのほか、[F1] のようなファンクションキーなどが押されたときに、特定のメッセージに結びつけるようにしたいとき使います。
#include <windows.h> // #include <commctrl.h> // #include "myprog.h" #define IDM_ACTF1 100 #define IDM_CTRLF1 101 #define IDM_SHIFTF1 102 #define IDM_CTRLUP 103 #define IDM_CTRLDOWN 104 #define IDM_NEXT 105 #define IDM_NKEY 106 MYACCEL ACCELERATORS DISCARDABLE BEGIN VK_F1 , IDM_ACTF1 , VIRTKEY, NOINVERT VK_F1 , IDM_CTRLF1 , VIRTKEY, CONTROL , NOINVERT VK_F1 , IDM_SHIFTF1, VIRTKEY, SHIFT , NOINVERT VK_UP ,IDM_CTRLUP , VIRTKEY, CONTROL, NOINVERT VK_DOWN ,IDM_CTRLDOWN , VIRTKEY, CONTROL, NOINVERT VK_DOWN ,IDM_NEXT , VIRTKEY, SHIFT, CONTROL, NOINVERT "N" , IDM_NKEY , VIRTKEY , NOINVERT END
VK_F1 は [F1] キーを表しています。VK_UP と VK_DOWN はそれぞれ、キーボードの [↑]キー、[↓]キーです。
VK_F1 が3つもあるのは、それぞれ、[SHIFT] キーを同時に押したとき、[CTRL] キーを同時に押したとき、なにも押してないとき、の3種類を定義しているからです。
通常のアルファベットキーもショートカットキーに指定することが可能です。例えば [N] キーなら上の例のようになります。
上記では使用していませんがほかに、
ASCII キーワードなどがあります。
[仮想キー]
VK は、Virtual Key の略です。日本語では 「仮想キー」。ほかに VK_ のどのようなものがあるかは、ヘッダファイル <winuser.h> をあたってみるか、仮想キーや、仮想キーコード などを調べてください。結構たくさんあります。
[ [SHIFT] キーと [CTRL] キー ]
上記リソーススクリプト例を参照してください。
[ WM_COMMAND と メッセージID]
アクセラレータとして定義されたキーが押された場合には、(以下で述べるようにショートカットキーの仕組みが組み込まれていれば)、対象のウィンドウに WM_COMMAND メッセージが送られ、wParam※ の 下位ワード(LOWORD) に メッセージID を持っています。(※ ウィンドウプロシージャやダイアログプロシージャの第3引数のことを言っています)
つまり、この メッセージID の扱いは、ダイアログボックスのコントロールの コントロールID 及び、メニューにおけるメニューアイテムのID とまったく同様です。
さて、ショートカットキーを有効にするには、リソースのリンク ( brc32.exe ) はこのさいもちろんとして、以下で述べるように メッセージループの部分を少々書き換える必要があります。
ウィンドウズのアプリケーションに慣れてしまうと、エディットボックス以外はキーなんかほとんど使うことなく、なんだかんだでマウス主体で動かしていることに気づくはずです。そして、キーボードの UI (ユーザ・インターフェース) を介した重要性も意識しなくなります。 キーボードは UI の主要な要素に違いありません。アクセラレータに頼らずとも、キーのイベントを知るには、原始的には、直接メッセージループの部分の MSG 構造体のパラメータに渡されるキー情報を見ることで可能です。アクセラレータはその手間を軽減してくれる便利な方法、つまり WM_COMMAND メッセージに変換してしまうという方法 (のための対応テーブル表) です。※ keybd_event() 関数はキーボードイベントを「発生」させることができます。 |
すなわち、アクセラレータを有効にするには、あるいは 「その変換を行うため」 には、具体的に TranslateAccelerator() という関数を用い、メッセージループの部分を以下のように少し変える(組み込む)必要があります。
[ 関数 WinMain() 内.......]
HACCEL
hAccel = LoadAccelerator( GetModuleHandle(NULL), "MYACCEL" ) ; while ( 0 != ( ret = GetMessage( &msg, NULL, 0, 0 ))) { if ( ret != -1 ) { if( ! TranslateAccelerator( msg.hwnd , hAccel, &msg )) { TranslateMessage( &msg ) ; DispatchMessage( &msg ) ; } } } // msg.hwnd の部分は一時的です。このようにすると全てのウィンドウに対してアクセラレータが有効になります。特定のウィンドウ(メインウィンドウなど)だけ有効にしたい場合はよくあります。そのときは、そのウィンドウのハンドルを指定するようにします。 // GetModuleHandle(NULL) も一時的です。ここは WinMain() 関数内だから、WinMain() 関数の第一引数(インスタンスハンドル : 変数名 hInstance 等)をそのまま使ってもいいでしょう。 // MSG 構造体の説明 .のところで、おもしろいものを紹介しました。これを活用するとメッセージループがこれ以上煩雑にならないで済みます。
TranslateAccelerator() 関数により、メッセージループの部分で、キーボードのイベントが、 「アクセラレータ」 で定義しておいたメッセージID を wParamパラメータ の下位ワードに持つような、WM_COMMAND メッセージに、変換されます(つまり親のウィンドウに送られます)。
WM_COMMAND のメッセージ処理の仕方はここで述べることではありません。ただ非常に定番のやりかたです。 [メニュー] での説明などを見てキーワードを得て、少し調べてみてください。WM_COMMAND 自体が有力キーワードです。
※ LoadAccelerator() 関数でロードしたリソースの開放はする必要はありません。
hAccel はアクセラレータリソースのハンドルです。
アプリケーションへのすべてのメッセージ(イベント)は、メッセージループを経ます。キー入力もイベントだからほかでもないわけです。
[トップ] [level4:言葉] [index]