コマンドボタン上でカーソルキーの動きを制御したい
複数(3個以上)のコマンドボタンを並べてあるフォーム上で(これはこれで気味が悪い(笑))、「カーソルキーの右を押したらフォーカスも下へではなく、横に移動させたい」と思った時のテクです。
最初にハッキリ言うと『コマンドボタンにフォーカスが居る場合のカーソルキー入力』は、VBだろうがVC++だろうが、キー入力イベントは発生しません。ウィンドウ・プロシーシャにすら流れて来ないんです。
じゃぁ、どうするか!?
フォーカスの出入りを捕らえるしかありません。
ですが、単純に LostFocus イベントでは困った事に、あまり正常に動いてはくれません(爆)
私が取った方法は、Win32APIの、SetWindowLong() によって、コマンドボタンのウィンドウ・ハンドルに流れてくるイベント・メッセージを先に監視し、フォーカス移動の際に発生するGDI系のイベントを押さえ、その押さえたタイミングで GetKeyboardState() 関数によってキーボードのキー入力状態を取得し、フォーカス移動がカーソルキーによって行われた場合に『自前のフォーカス移動処理をさせる』と言う方法です。
挙動を観ての推測ですが、コマンドボタン上ではフォーカス移動に直接関わるキー、すなわちカーソルキー・TABキーはキー入力イベントが発生しない。ウィンドウ・プロシージャにキー入力イベントとして渡さずにOSが先に処理し、LostFocus イベントのみを渡すと言う事だと思います。
また挙動を観て他に判った事は、コレにはリターンキーも含まれている(スペースバー(スペースキー)は、キー入力イベントとして押さえられます)と言う事です。
で・・・、サンプルソースを全部載せる気にはなれないので、一部だけ(笑)
-----<<ここから>>--------------------------------------------------
Rem グローバル変数
Rem ウィンドウプロシージャハンドル保持変数
Public lpPrevWndProc As Long
Public glHWin1 As Long
Rem 2回同じプロシージャフックを呼ぶと暴走するのでそれを防止する
Public bNever As Boolean
Rem その他
Private lKeys As Long
Private cBuf(256) As Byte
Rem Hook - in
Public Sub Hook()
lpPrevWndProc = SetWindowLong(glHWin1, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Rem Hook - out
Public Sub Unhook()
Dim temp As Long
temp = SetWindowLong(glHWin1, GWL_WNDPROC, lpPrevWndProc)
End Sub
Rem Window-Pro.
Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Rem Debug.Print "Message: "; hw, uMsg, wParam, lParam
Rem フォーカスが移動した時にのみ発生しているメッセージを確認した時、
If uMsg = &H100E Then
Rem キーボードの状態を取得し、カーソルキーの入力をチェックする。
lKeys = GetKeyboardState(cBuf(0))
If cBuf(37) And &H80 Then
TEST.Label1.Caption = "Left!"
ElseIf cBuf(38) And &H80 Then
TEST.Label1.Caption = " Up !"
ElseIf cBuf(39) And &H80 Then
TEST.Label1.Caption = "Right!"
ElseIf cBuf(40) And &H80 Then
TEST.Label1.Caption = "Down!"
End If
End If
WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
End Function
-----<<ここまで>>--------------------------------------------------
これらをプログラムの然るべき箇所に設置し、望むべき改造を施してやればOKです。
何故って、ラベルに表示するだけですからね(笑)<フォーム名も固定だし(爆)
また、API使用の宣言は行っていませんので、まるまるCOPY&PASTEする人は気を付ける事。
AddressOf は『関数のポインタ』を渡させるのに必要なモノです。詳しい説明はWin32API利用の本を読んで下さい(笑)
つまり、フック時には Function WindowProc() のアドレスを渡している訳です。なおアン・フック時にはフック時の返り値である、『変更前のプロシージャへのポインタ』をセットしてあげます。
使ったモノはちゃんと返さないとね(笑)
また自前の作業が終わったら CallWindowProc で、やっぱり『変更前のプロシージャへのポインタ』を渡してあげれば、それ以外の通常のイベント処理をやってくれます。じゃないと、自分で処理するしか無いッスよ(笑)
Debug.Print はデバッグ作業中に、イミディエイトでイベントメッセージを眺めるのに使いましょう(笑)
これを行うメリットは、カーソルキーと同じ配置のコマンドボタンを用意して、コマンドボタンの入力とカーソルキーの入力を一致させたい場合に特に有功であると思います。見た目とカーソルキーが一致する訳ですから。
これを用いたアルゴリズムによる損害などの責任は、私には負う義務・理由はありません。利用される方にのみあります。
利用する際には、事後でも結構ですから e-mail でも下さい。事前承諾は一切しませんから、お好きな様に。
無いとは思いますが、記事に利用される場合には事前承諾を取ってからにして下さい。
自分で試したテストルーチンなので、ちゃんと動きます。

戻 る