• ベストアンサー

フォーカスについて

エンターを押すと、特定のコマンドボタンが押ささるプログラムを作っているのですが、エンターを押すとフォーカスがセットされているコマンドボタンが押ささってしまいます。 特定のコマンドボタンって言っても、1個のコマンドボタンなんですがなんかいい方法ありますか? それから、キーボードの矢印キーで、並んであるコマンドボタンにフォーカスを移動させたいのですがいい方法ありますか? TabIndexの関係だと思うのですが、上キーを押すと、すぐ上のボタンではなく右にいったり左にいったり・・・ どうか教えてください。 お願いします

質問者が選んだベストアンサー

  • ベストアンサー
  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.3

質問1.エンターを押すと、特定のコマンドボタンが押ささるプログラム 質問2.キーボードの矢印キーで、並んであるコマンドボタンにフォーカスを移動 まず最初に、、、 質問が二つ以上になる時は、別スレッドでお願いします。 質問2についてのサンプルです。 TabIndexを使用してフォーカスが順次移動するのは、知っての通りです。 VBの仕様を捻じ曲げなければなりません。ならばOSからVBに処理が渡る直前に、そのOSから届くイベントを処理しちゃいましょう。フックという方法を使用しました。これを使用すると、特定のイベントタイプを監視できます。 最初にコマンドボタンを25個、フォーム1に貼り付けます。 0,1,2,3,4 5,3,7,8,9 .... ...    ...24 といったようにコントロール配列にしてください。 下記のコードを貼り付け実行してください。 フォームのキャプションに注目すると 「フックしていません」 となっているはずです。[Enter]か[クリック]をすることにより 「フックしています」 になります。 その状態の時にカーソルを押すと、望みの結果が得られると思います。 -----Form1ここから----- Option Explicit Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hHook As Long) As Long Private Declare Function SetWindowsHookEx Lib "user32.dll" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long Private Const WH_KEYBOARD = 2 Private Sub Command1_Click(Index As Integer)   'フック中でない時   If g_lngHook = 0 Then     '(キーボードからの入力を)フックする     g_lngHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf KeyboardProc, 0&, App.ThreadID)     Me.Caption = "フック中です"        'フック中の時   Else     'フックを解除してあげる     Call UnhookWindowsHookEx(g_lngHook)     g_lngHook = 0     Me.Caption = "フックしていません"   End If End Sub Private Sub Command1_GotFocus(Index As Integer)   '現在のフォーカスを持つコマンドボタンのインデックスを得る   g_intIndex = Index End Sub Private Sub Form_Activate()   If Me.Tag = "これから起動する" Then     Command1(0).SetFocus     Me.Tag = ""   End If End Sub Private Sub Form_Load()   Me.Tag = "これから起動する"   Me.Caption = "フックしていません" End Sub Private Sub Form_Unload(Cancel As Integer)   'フックした状態で終了しようとした時、フックを解除する   If g_lngHook <> 0 Then     Call UnhookWindowsHookEx(g_lngHook)   End If End Sub -----Form1ここまで----- -----標準モジュールここから----- Option Explicit Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Public g_lngHook  As Long   'フックプロシージャのハンドル Public g_intIndex  As Integer '現在のフォーカスを持つコマンドボタンのインデックス Public Function KeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long                  Static blnReEnter As Boolean  'キーイベント2重発生防止フラグ      Select Case wParam     'カーソルキーを押された時     Case vbKeyRight, vbKeyLeft, vbKeyUp, vbKeyDown              'キーイベント2重発生防止       If blnReEnter = False Then         blnReEnter = True         KeyboardProc = 1         Exit Function       End If              'カーソルによる処理分岐       With Form1         Select Case wParam           Case vbKeyRight             'カーソルが一番右列にある?             If (g_intIndex Mod 5) = 4 Then               .Command1(g_intIndex - 4).SetFocus             Else               .Command1(g_intIndex + 1).SetFocus             End If           Case vbKeyLeft             'カーソルが一番左列にある?             If (g_intIndex Mod 5) = 0 Then               .Command1(g_intIndex + 4).SetFocus             Else               .Command1(g_intIndex - 1).SetFocus             End If           Case vbKeyUp             'カーソルが一番上行にある?             If (g_intIndex < 5) Then               .Command1(g_intIndex + 20).SetFocus             Else               .Command1(g_intIndex - 5).SetFocus             End If           Case vbKeyDown             'カーソルが一番下行にある?             If (g_intIndex >= 20) Then               .Command1(g_intIndex - 20).SetFocus             Else               .Command1(g_intIndex + 5).SetFocus             End If         End Select       End With              KeyboardProc = 1       blnReEnter = False          'カーソルキー以外を押された時     Case Else       '何もしない       KeyboardProc = CallNextHookEx(g_lngHook, nCode, wParam, lParam)       Exit Function   End Select End Function -----標準モジュールここまで----- ・・・で、質問1の方は、これらを応用して、フラグを立てたらできるような気がします。

tetudamon
質問者

お礼

大変お礼が遅くなりました。申し訳ございません。 とても参考になりました。 ありがとうございました これからも、何かありましたらよろしくお願いします

その他の回答 (3)

  • TAGOSAKU7
  • ベストアンサー率65% (276/422)
回答No.4

ふと思ったのですが、オリジナルの処理を求めるのならば、コマンドボタンにこだわらない方がいいかもしれないですね。 いっそのことピクチャボックスにしてしまっては? EnterとClickと処理を分けたいのであれば、それが一番手っ取り早いような気がするのですが。。。 ピクチャボックスにコマンドボタンの絵を張っておいて、フォーカスを得た時や失った時も必要なのであれば、LostやGotフォーカスで、絵の差し替えをしてあげると、同じような動きになると思います。クリックも反応させたいのであれば、マウスのUpDownMoveで差し替えることになります。 それをユーザコントロールにしておいたら非常に便利だと思いますよ。

  • bin-chan
  • ベストアンサー率33% (1403/4213)
回答No.2

コマンドボタンのプロパティに[Default]という項目があります。 (初期値はfalseになってます) こいつをTrueにすればフォーム上での[Enter]押下をClickイベントが受け取ります。 ボタンに「影」が付きますからよく見てね。 反対にEscを押下した際にClickイベントを発生させるのは プロパティ[Cansel]。 要するに「はい」「いいえ」のようなフォームの場合に、どちらを「主」とするか、 のような設定方法です。 > 並んであるコマンドボタンにフォーカスを移動させたいのですが アクセスキーを利用した方が簡単でしょう。 Alt+(指定の文字)でフォーカスが移動します。 やり方はCaptionに&(指定の文字)とするだけ。 実行(E) (←カッコ内のEには下線が付く)の場合なら Captionに 実行(&E)と記述するだけでOK。 見栄えがしますよ!

tetudamon
質問者

お礼

大変お礼が遅くなりました。申し訳ございません。 何とか、解決いたしました。 これからも、何かありましたらよろしくお願いします

回答No.1

KeyDownのイベントで、エンターが押されたときに、行いたい特定の処理をするようにすれば良いと思います。 同様に、矢印キーの場合も、それぞれにフォーカスをセットする(多分SetFocusだったと思う)ようにすれば良いのではないでしょうか

tetudamon
質問者

お礼

大変お礼が遅くなりました。申し訳ございません。 何とか、解決いたしました。 これからも、何かありましたらよろしくお願いします

関連するQ&A