2つのEnterキーの判定するには?

解決


DeepPort  2008-11-19 20:50:56  No: 145420

VB2005にて、Enterキーのテンキーと、キーボードを判定したく、以下の方法を試しましたが、同じ結果が返ってきて、判断できませんでした。

【KeyDownイベント】
             If e.KeyCode = Keys.Return Then
             ElseIf e.KeyCode = Keys.Enter Then
【KeyPressイベント】
           If e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Return) Then
           ElseIf e.KeyChar = Microsoft.VisualBasic.ChrW(Keys.Enter) Then

いろいろ調べてみて、Ms-ACCESS2000では、判断できるソースがありましたので、
そちらを参考にVB2005に書き換えようと試みていますが、MyMSG に値が入って来ないため、判断にも至りません。
Enterキーの判断方法をご存知の方いらっしゃいますか?

    Public Structure POINTAPI
        Dim X As Integer
        Dim Y As Integer
    End Structure

    Public Structure MSG
        Dim hWnd As Long
        Dim message As Long 'メッセージ情報
        Dim wParam As Long
        Dim lParam As Long
        Dim time As Long
        Dim pt As POINTAPI
    End Structure

    Private Declare Function PeekMessage Lib "user32" _
        Alias "PeekMessageA" (ByVal lpMsg As MSG, ByVal hWnd As IntPtr, _
        ByVal wMsgFilterMin As Integer, ByVal wMsgFilterMax As Integer, _
        ByVal wRemoveMsg As Integer) As Long
    Private Declare Function TranslateMessage Lib "user32" (ByVal lpMsg As MSG) As Integer
    Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (ByVal lpMsg As MSG) As Integer

    Const PM_NOREMOVE As Long = &H0
    Const WM_KEYFIRST As Long = &H100
    Const WM_KEYLAST As Long = &H108

【KeyPressイベント】
 Dim MyMsg As MSG, RetVal As Long
                RetVal = PeekMessage(MyMsg, Me.Handle, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)
                If RetVal <> 0 Then
                    If MyMsg.wParam = CDbl(vbNewLine) Then
                         If CBool(MyMsg.lParam And &H1000000) Then
                            MsgBox("テンキー")
                        Else
                            MsgBox("キーボード")
                        End If
                    End If
    else
                   TranslateMessage(MyMsg)
                    DispatchMessage(MyMsg)
             End If

因みにMs-ACCESS2000で、確認できましたソースは、以下になります
Private Declare Function PeekMessage Lib "user32" _
    Alias "PeekMessageA" (lpMsg As Msg, ByVal hwnd As Long, _
    ByVal wMsgFilterMin As Long, ByVal wMsgFilterMax As Long, _
    ByVal wRemoveMsg As Long) As Long

Private Declare Function TranslateMessage Lib "user32" (lpMsg As Msg) As Long

Private Declare Function DispatchMessage Lib "user32" Alias "DispatchMessageA" (lpMsg As Msg) As Long

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type Msg
    hwnd As Long
    message As Long
    wParam As Long
    lParam As Long
    time As Long
    pt As POINTAPI
End Type

Const PM_NOREMOVE = &H0

Const WM_KEYFIRST = &H100
Const WM_KEYLAST = &H108

Const VK_RETURN = &HD

Private Sub Form_Load()
    Me.KeyPreview = True
End Sub

Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    Dim MyMsg As Msg, RetVal As Long

    If KeyCode = vbKeyReturn Then
        Do
            RetVal = PeekMessage(MyMsg, Me.hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)

            If RetVal <> 0 Then
                If MyMsg.wParam = VK_RETURN Then
                    If MyMsg.lParam And &H1000000 Then
                        MsgBox "Enter from Keypad pressed"
                    Else
                        MsgBox "Enter from Keyboard pressed"
                    End If
                    Exit Do
                End If
            Else
                TranslateMessage MyMsg
                DispatchMessage MyMsg
            End If
        Loop
    End If

End Sub


Hongliang  2008-11-19 21:36:56  No: 145421

WndProc をオーバーライドすれば、OnKeyDown に渡る前の WM_KEYDOWN を拾えます。


魔界の仮面弁士  2008-11-19 22:11:13  No: 145422

> If e.KeyCode = Keys.Return Then
> ElseIf e.KeyCode = Keys.Enter Then
上記では判定できません。そもそも
  If Keys.Enter = Keys.Return Then
は True となってしまうはずですし。
(Return と Enter は、どちらも数値としては「13」です)

> Ms-ACCESS2000では、判断できるソースがありましたので、
これかな?
http://support.microsoft.com/kb/188550/en-us

> MyMSG に値が入って来ないため、判断にも至りません。
こうかな。

Public Class Form1
    Public Event EnterKeyPress(ByVal IsKeyPad As Boolean)

    Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Debug.WriteLine(keyData.ToString() & ":" & msg.ToString())

        Const WM_KEYDOWN As Integer = &H100
        If msg.Msg = WM_KEYDOWN AndAlso keyData = Keys.Return Then
            If IntPtr.Size = 4 Then
                RaiseEvent EnterKeyPress(CBool(msg.LParam.ToInt32() And &H1000000I))
            Else
                RaiseEvent EnterKeyPress(CBool(msg.LParam.ToInt64() And &H1000000L))
            End If
        End If

        Return MyBase.ProcessCmdKey(msg, keyData)
    End Function

    Private Sub Form1_EnterKeyPress(ByVal IsKeyPad As Boolean) Handles Me.EnterKeyPress
        ListBox1.Items.Add(IsKeyPad)
    End Sub
End Class


DeepPort  2008-11-19 23:40:22  No: 145423

動作しました
ご回答、ありがとうございました

VB2005使用しはじめ、日が浅い初心者事もあり、伝わりにくい表現にも関わらず、ありがとうございました。

APIを使わずとも、ProcessCmdKey・Overrides により、取得できるのですね。
教えていただいたソースの完全理解に励みます

どうもありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加