tagCANDY CGI VBレスキュー(花ちゃん) - VBレスキュー(花ちゃん)の投稿サンプル用掲示板 - Visual Basic 6.0 VB2005 VB2010
VB2005用トップページへVBレスキュー(花ちゃん)のトップページVB6.0用のトップページ
VBレスキュー(花ちゃん)の投稿サンプル用掲示板
     サンプル投稿用掲示板  VB2005 〜 用トップページ  VB6.0 用 トップページ
どのキーが押されたかを取得する方法色々(VB.NET) ( No.0 )  [親スレッドへ]
日時: 2013/02/12 20:07
名前: VBレスキュー(花ちゃん)

***********************************************************************************
* カテゴリー:[キー操作][イベント][]                         *
* キーワード:キー認識,キーイベント,キーコード,KeyData,KeyCode ,押された,テンキー *  
***********************************************************************************
タイトル:フォームでキーイベントを受取る
記 事 No:11047
投 稿 日:2013/02/05(Tue) 16:47
元質問者:佐藤hs  
-----------------------------------------------------------------------------------
下の様にしましたが、F1キーは認識されますが、CTRLキーが認識されません。何故でしょうか?
    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal _
           e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        If e.KeyData = Keys.ControlKey Then
            MsgBox("Controlキーが押されました。")
        End If
        If e.KeyData = Keys.F1 Then
            MsgBox("F1キーが押されました。")
        End If
    End Sub

上記について、Hongliang さんが、記事No.11048 で回答されているのでそちらもご覧下さい。

-----------------------------------------------------------------------------------
タイトル:どのキーが押されたかを取得する方法色々(468) - VB2010
動作確認:Windows Vista / Windows 7 / VB2010 Pro SP1Rel / Framework 4.0 SP1Rel で
[Option Compare Text][Option Explicit On][Option Infer On][Option Strict On]で確認
投 稿 日:2013/02/07
投 稿 者:VBレスキュー(花ちゃん)  
-----------------------------------------------------------------------------------
下記が全てではありませんし、下記の方法では取得できない特殊キーもあります。
使用目的に合わせて色々試して(どのイベント内で取得するかも含め)見て下さい。
(一部期待通りに動作しない悪い例の場合もあります。)
e.Shift / e.Control / e.Alt 等を使って比較される場合は、3つのキーの状態をすべて
指定して比較する必要があります。
If e.Control Then のようなコードでは、期待通り(Control キーを単独で押している)の動作を
してくれません。
詳しくは、下記リンク等の MSDN の各解説サイトをご覧ください。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.keyeventargs.keycode.aspx

又、今回は、KeyDown イベントで取得していますが、.NET Framework 2.0 からは PreviewKeyDown
イベントが追加されたのでそちらも試して見て下さい。
(9.PreviewKeyDown イベントでの取得 に追加)
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.previewkeydown.aspx

NumLock、CapsLock、ScrollLockキーが有効かどうかを判定する方法について 下記を参照して下さい。
 http://msdn.microsoft.com/ja-jp/library/cc720817.aspx


Imports System.Runtime.InteropServices

Public Class Form1

Private Sub TextBox1_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
'1.押されたキーを取得
   'e.KeyCode プロパティ :KeyDown イベント又は KeyUp イベントのキーボード コードを取得します。
   'e.KeyData プロパティ :KeyDown イベント又は KeyUp イベントのキー データを取得します。
   'e.KeyValue プロパティ:KeyDown イベント又は KeyUp イベントのキーボード値を取得します。

   Dim msg As String = String.Format("KeyCode  = {0}" & vbCrLf & _
                                     "KeyData  = {1}" & vbCrLf & _
                                     "KeyValue = {2}" _
         , e.KeyCode.ToString, e.KeyData.ToString, e.KeyValue.ToString)
   MessageBox.Show(msg)
End Sub



Private Sub TextBox2_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox2.KeyDown
'2.Shift キー が押された事を取得
   '(Ctrl キー や Alt キー の場合も同様です。キーコードを変えて試して下さい。)
   '(Shift キー / CTRLShift キー / ALTShift キー を同時に押した場合も試して下さい。)

   'e.Shift プロパティ:Shift キーが押されたかどうかを示す値を取得します。
   If e.Shift Then
      '(1)× この場合、Shift + CTRL + ALT でも反応します。従ってそれでも問題が無い場合に使用して下さい。
      MessageBox.Show("(1)× If e.Shift Then")
   End If

   If e.Shift = True And e.Control = False And e.Alt = False Then
      '(2)○ この場合は、Shift キー 単独で押され時に反応します。
      MessageBox.Show("(2)○ If (e.Shift = True And e.Control = False And e.Alt = False) Then")
   End If

   If e.KeyCode = Keys.ShiftKey Then
      '(3)× この場合、Shift + CTRL + ALT でも反応します。従ってそれでも問題が無い場合に使用して下さい。
      MessageBox.Show("(3)× If e.KeyCode = Keys.ShiftKey Then")
   End If

   If e.KeyCode = Keys.Shift Then
      '(4)× これでは取得できません。
      MessageBox.Show("(4) If e.KeyCode = Keys.Shift Then")
   End If

   If e.KeyData = (Keys.ShiftKey Or Keys.Shift) Then
      '(5)○ この場合は、Shift キー 単独で押され時に反応します。
      MessageBox.Show("(5)○ If e.KeyData = (Keys.ShiftKey Or Keys.Shift) Then")
   End If

   'e.Modifiers プロパティ:KeyDown イベント又は KeyUp イベントの修飾フラグを取得します。
   'このフラグは、Ctrl キー、Shift キー、および Alt キーのどの組み合わせが押されたのかを示します。
   If e.Modifiers = Keys.Shift Then
      '(6)◎ この場合は、Shift キー 単独で押され時に反応します。
      MessageBox.Show("(6)◎ If e.Modifiers = Keys.Shift Then")
   End If

   If e.KeyValue = 16 Then
      '(7)× この場合、Shift + CTRL + ALT でも反応します。従ってそれでも問題が無い場合に使用して下さい。
      MessageBox.Show("(7)× If e.KeyValue = 16 Then")
   End If

End Sub



Private Sub TextBox3_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox3.KeyDown
'3.Ctrl キー + Alt キーが押された事を取得
   '(2.の結果を踏まえて試した分です。)

   If (e.Shift = False And e.Control = True And e.Alt = True) Then
      MessageBox.Show("(1)○ If (e.Shift = False And e.Control = True And e.Alt = True) Then")
   End If

   If e.KeyData = (Keys.Control Or Keys.Alt) Then
      MessageBox.Show("(2)◎ If e.KeyData = (Keys.Control Or Keys.Alt) Then")
   End If

   If e.Modifiers = (Keys.Alt Or Keys.Control) Then
      MessageBox.Show("(3)◎ If e.Modifiers = (Keys.Alt Or Keys.Control) Then")
   End If

End Sub



Private Sub TextBox4_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox4.KeyDown
'4.Ctr キー + Alt キー + A キー が押された事を取得
   '(3.の結果を踏まえて試した分です。)
   'これで、Shift + CTRL + ALT + 任意のキー の場合でも理解できるかと思いますので
   'これ以上の組み合わせのテストは省略します。

   If e.KeyCode = Keys.A And (e.Shift = False And e.Control = True And e.Alt = True) Then
      MessageBox.Show("(1)○ If e.KeyCode = Keys.A And (e.Shift = False And e.Control = True And e.Alt = True) Then")
   End If

   If e.KeyData = (Keys.Control Or Keys.Alt Or Keys.A) Then
      MessageBox.Show("(2)◎ If e.KeyData = (Keys.Control Or Keys.Alt Or Keys.A) Then")
   End If

   If e.KeyCode = Keys.A AndAlso e.Modifiers = (Keys.Alt Or Keys.Control) Then
      MessageBox.Show("(3)○ If e.KeyCode = Keys.A AndAlso e.Modifiers = (Keys.Alt Or Keys.Control) Then")
   End If

End Sub



#Region "左右どちらの Shift / Ctrl / Alt キーが押されたかを取得関係"

''' <summary>
''' 仮想キーの押下状態を取得する(1064)
''' </summary>
''' <param name="nVirtKey">仮想キーコードを指定します</param>
''' <returns>指定された仮想キーの状態を表し、
'''          最上位ビットが 1 のときはキーが押されていることを、0 のときは
'''     キーが押されていないことを示します</returns>
''' <remarks></remarks>
<DllImport("User32.dll", CharSet:=CharSet.Auto)> _
Private Shared Function GetKeyState( _
   ByVal nVirtKey As Integer) As Integer
End Function

Private Sub TextBox5_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox5.KeyDown
'5.左右どちらの Shift / Ctrl / Alt キーが押されたかを取得する。
   'VB2010 らしい簡単な方法があるのかなと思って調べて見たのですが見当たらないので。
   If GetKeyState(Keys.LShiftKey) < 0 Then
      MessageBox.Show("左の Shift キーが押されました。")
   ElseIf GetKeyState(Keys.RShiftKey) < 0 Then
      MessageBox.Show("右の Shift キーが押されました。")
   End If

   If GetKeyState(Keys.LControlKey) < 0 Then
      MessageBox.Show("左の Control キーが押されました。")
   ElseIf GetKeyState(Keys.RControlKey) < 0 Then
      MessageBox.Show("右の Control キーが押されました。")
   End If

   If GetKeyState(Keys.LMenu) < 0 Then
      MessageBox.Show("左の Alt キーが押されました。")
   ElseIf GetKeyState(Keys.RMenu) < 0 Then
      MessageBox.Show("右の Alt キーが押されました。")
   End If
End Sub

#End Region



#Region "標準のキーボードの Enter キーかテンキーの Enter キーのどちらが押されたかを取得関係"

'PeekMessage 関数がメッセージを処理した後、そのメッセージをキューから削除しません。
Private Const PM_NOREMOVE As Integer = &H0

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure POINTAPI
   Public x As Integer        'x座標
   Public y As Integer        'y座標
End Structure

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure MSG
   Public hwnd As IntPtr      'ウィンドウハンドル
   Public message As Integer  'メッセージID
   Public wParam As Integer   'WParamフィールド(メッセージID毎に異なる)
   Public lParam As Integer   'LParamフィールド(メッセージID毎に異なる)
   Public time As Integer     '時間
   Public pt As POINTAPI      'カーソル位置(スクリーン座標)
End Structure

''' <summary>
''' 呼び出し側スレッドのメッセージ キューから、メッセージを取得します。
''' </summary>
''' <param name="lpMsg">MSG構造体へのポインタを指定します</param>
''' <param name="hwnd">メッセージを取得するウィンドウのハンドルを指定します。</param>
''' <param name="wMsgFilterMin">取得するメッセージの範囲の最小値を指定します。</param>
''' <param name="wMsgFilterMax">取得するメッセージの範囲の最大値を指定します。</param>
''' <param name="wRemoveMsg">取得したメッセージを、メッセージ キューから削除するかを定数で指定します。</param>
''' <returns>メッセージを取得したときは、TRUE が返ります。</returns>
''' <remarks></remarks>
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Public Shared Function PeekMessage( _
   ByRef lpMsg As MSG, _
   ByVal hwnd As IntPtr, _
   ByVal wMsgFilterMin As Integer, _
   ByVal wMsgFilterMax As Integer, _
   ByVal wRemoveMsg As Integer) As Boolean
End Function

Private Sub TextBox6_KeyDown(sender As Object, _
               e As System.Windows.Forms.KeyEventArgs) Handles TextBox6.KeyDown
'6.どちらの Enter キー(標準/テンキー)が押されたかを取得
   'VB2010 らしい簡単な方法があるのかなと思って調べて見たのですが見当たらないので。

   Dim nMsg As MSG
   Dim pm As Boolean
   'メッセージを取得(あれば1が返る)
   pm = PeekMessage(nMsg, Me.Handle, 0, 0, PM_NOREMOVE)
   If pm <> False And nMsg.wParam = Keys.Return Then
      'lParam の 24 ビットめをチェックします。キーが拡張キーならば
      'ビット 24 は 1 になり、そうでなければ 0 が返ります。
      If CBool(nMsg.lParam And &H1000000) Then
         MsgBox("テンキー側の ENTER キーが押されました")
      Else
         MsgBox("標準キーボード側の ENTER キーが押されました")
      End If
   End If

End Sub

#End Region


'下記のイベントでは、Tab キーの検出ができます。
Private Sub TextBox9_PreviewKeyDown(sender As Object, e As  _
      System.Windows.Forms.PreviewKeyDownEventArgs) Handles TextBox9.PreviewKeyDown
'9.PreviewKeyDown イベントでの取得(.NET Framework 2.0 以降で追加)
   'PreviewKeyDown イベント:キーが押された場合、KeyDown イベントの前に発生します。
   'MSDN のPreviewKeyDown イベントの解説の項を読んでおいて下さい。

   Dim msg As String = String.Format("KeyCode  = {0}" & vbCrLf & _
                                     "KeyData  = {1}" & vbCrLf & _
                                     "KeyValue = {2}" _
         , e.KeyCode.ToString, e.KeyData.ToString, e.KeyValue.ToString)
   MessageBox.Show(msg)

End Sub

End Class

各コントロールの配置図及び実行図(画像をクリックすると元のサイズで見る事ができます。)



 [スレッド一覧へ] [親スレッドへ]