ALTキーを押すと最初のメニュー項目(ファイル(F))がアクチベートされます。
次に、たとえば「O」キーを押すと「オプション(O)」をクリックしたのと同じ効果が
得られます。この状態で下矢印キーを押すと「ツールチップ(T)」が強調表示
されます。
また、ALTキーを押して「ファイル(F)」をアクチベートした後、右矢印キーを
押すと「編集(E)」がアクチベートされます。
このような機能は、どのようにプログラムすればよいのでしょうか。実はこれは
メッセージフックなのです。メッセージフックについては
第160章を参照してください。
では、具体的にどうするかというと、メインウィンドウのプロシージャに
WM_CREATEメッセージが来たら、WH_KEYBOARDタイプのフックを開始します。
ヘルプでは、WM_MSGFILTERでフックするような説明になっていますが、
WH_KEYBOARDの方が簡単です。
たとえばフックプロシージャを
LRESULT CALLBACK KbdHook(int code, WPARAM wp, LPARAM lp)
とすると、ALTキーまたはF10キーが押された時、最初のメニュー項目が アクチベートされなくてはいけません。
codeがHC_ACTIONでwpがVK_MENU(ALTキー)または、VK_F10の時IE様メニューバーに TB_SETHOTITEMメッセージを送ります。
wParamには、ホットにしたいアイテムのインデックスを指定します。TB_SETHOTITEM wParam = (WPARAM)(INT)iHot; lParam = 0;
戻り値は以前のホットアイテムのインデックスです。前回ホットアイテムが なかったときは-1が返ります。
ホットアイテムが存在する状態で、F,E,Iなどのショーカットキーが 押されたときは、そのメニュー項目のポップアップを表示します。 これは、以前(第312章)に作ったShowMyPopMenu関数を使うと便利です。
ホットアイテムが存在する状態で、何かキーが押された時、それがショートカットキーであるかどうかは いちいち、調べてもよいのですが、TB_MAPACCELERATORメッセージを使うとスマート(?)です。
chAccelには押されたキーを指定します。すると、pIDBtnにそのショートカットキーの idのポインタが入ります。TB_MAPACCELERATOR wParam = (WPARAM)(TCHAR) chAccel; lParam = (LPARAM)(LPUINT) pIDBtn;
そもそも、押されたキーがショートカットキーでない時は、 戻り値が0になります。
左右のカーソルキーが押されたときは、TB_SETHOTITEMメッセージを使って ホットアイテムを左右に移動させます。
さて、左キーを押すと、そのキーが押されたときと、離したときの2回フックが起こります。 これでは、一度左キーを押すと2つ分ホットアイテムが移動してしまいます。 そこで、キーが押された時のみ(または離された時)にホットアイテムが移動するように工夫します。
このプロシージャのlpには、キーストロークメッセージの付加情報が格納されています。 キーが押されているのかどうかはlpの第31ビット(最上位ビット)が1かどうかでわかります。 よく使う手は
HIWORD(lp) & 0x8000
または、 HIWORD(lp) & KF_UP
です。KF_UPはwinuser.hで0x8000と定義されています。 0x8000は2進法で書くと
1000000000000000
となます(16ビット)。そこで、lpの上位16ビットを取ってきて ビット演算をすればよいことがわかります。
こう書くと、簡単そうに思われますが実際にプログラムを書くときは、かなり面倒なことが起こります。 ちょっとしたミスで、深みにはまり堂々巡りが起こってしまいます。そんな時は、 あっさり休憩を取るなり、翌日にやり直すつもりで眠ってしまいましょう。
今回の部分を含め、かなり長いプログラムとなってしまったので、サンプルは 次章で示します。
Update 05/Aug/2001 By Y.Kumei