使用 vb.net,挂钩指定的 USB 键盘,接收所需控制的字符并将接收到的字符阻止到其余窗口

Posted

技术标签:

【中文标题】使用 vb.net,挂钩指定的 USB 键盘,接收所需控制的字符并将接收到的字符阻止到其余窗口【英文标题】:Using vb.net, Hooking specified usb keyboard, receive chars in desired control and block received chars to rest of windows 【发布时间】:2021-03-05 07:40:17 【问题描述】:

我使用 VB.NET。 我已经编写了部分解决方案。也就是说,我在键盘上设置了一个钩子并获取输入的字符。我使用以下代码:

Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Private Overloads Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal HookProc As KBDLLHookProc, ByVal hInstance As IntPtr, ByVal wParam As Integer) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Private Overloads Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function
    <DllImport("User32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
    Private Overloads Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
    End Function
    <StructLayout(LayoutKind.Sequential)>
    Private Structure KBDLLHOOKSTRUCT
        Public vkCode As UInt32
        Public scanCode As UInt32
        Public flags As KBDLLHOOKSTRUCTFlags
        Public time As UInt32
        Public dwExtraInfo As UIntPtr
    End Structure
    <Flags()>
    Private Enum KBDLLHOOKSTRUCTFlags As UInt32
        LLKHF_EXTENDED = &H1
        LLKHF_INJECTED = &H10
        LLKHF_ALTDOWN = &H20
        LLKHF_UP = &H80
    End Enum
    Public Shared Event KeyDown(ByVal Key As Keys)
    Public Shared Event KeyUp(ByVal Key As Keys)
    Private Const WH_KEYBOARD_LL As Integer = 13
    Private Const HC_ACTION As Integer = 0
    Private Const WM_KEYDOWN = &H100
    Private Const WM_KEYUP = &H101
    Private Const WM_SYSKEYDOWN = &H104
    Private Const WM_SYSKEYUP = &H105
    Private Delegate Function KBDLLHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    Private KBDLLHookProcDelegate As KBDLLHookProc = New KBDLLHookProc(AddressOf KeyboardProc)
    Private HHookID As IntPtr = IntPtr.Zero
    Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        If (nCode = HC_ACTION) Then
            Dim struct As KBDLLHOOKSTRUCT
            Dim KeyboardSruct As KBDLLHOOKSTRUCT = Marshal.PtrToStructure(lParam, GetType(KBDLLHOOKSTRUCT))
            Select Case wParam
                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    If KeyboardSruct.vkCode <> 160 Then
                        Console.WriteLine(KeyboardSruct.vkCode)
                        Console.WriteLine(Chr(KeyboardSruct.vkCode))
                        rt1.AppendText(Chr(KeyboardSruct.vkCode))
                    End If
            End Select
        End If
        'Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End Function
    Protected Overrides Sub Finalize()
        If Not HHookID = IntPtr.Zero Then
            UnhookWindowsHookEx(HHookID)
        End If
        MyBase.Finalize()
    End Sub

    Private Sub KeyboardHook_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        HHookID = SetWindowsHookEx(WH_KEYBOARD_LL, KBDLLHookProcDelegate, System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
        If HHookID = IntPtr.Zero Then
            Throw New Exception("Could not set keyboard hook")
        End If

    End Sub
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub
End Class

但我要寻找的是只选择所需的键盘,一旦抓住了按下的键,避免 Windows 系统的其余部分接收来自该键盘的按下的键。也就是说,我需要对我的应用所需的键盘和应用内的所需控件进行独占控制。

关于如何做到这一点的任何帮助? 提前致谢。

【问题讨论】:

要挂钩特定键盘,请查找使用 Raw Input、SO examples and info 的示例。 感谢您的链接。使用一些原始输入样本,我得到了所需键盘上的钩子。我现在的问题只是如何避免从键盘捕获的消息到达操作系统中的其他窗口... 【参考方案1】:

使用Return CType(1, IntPtr) 为了避免从键盘捕获的消息到达操作系统中的其他窗口

Private Function KeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    If (nCode = HC_ACTION) Then
        Dim struct As KBDLLHOOKSTRUCT
        Dim KeyboardSruct As KBDLLHOOKSTRUCT = Marshal.PtrToStructure(lParam, GetType(KBDLLHOOKSTRUCT))
        Select Case wParam
            Case WM_KEYDOWN, WM_SYSKEYDOWN
                If KeyboardSruct.vkCode <> 160 Then
                    Console.WriteLine(KeyboardSruct.vkCode)
                    Console.WriteLine(Chr(KeyboardSruct.vkCode))
                    rt1.AppendText(Chr(KeyboardSruct.vkCode))
                    Return CType(1, IntPtr) ' Inhibit operation
                End If
        End Select
    End If
    Return CallNextHookEx(HHookID, nCode, wParam, lParam)
End Function

【讨论】:

虽然此代码可能会解决问题,但 including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。请edit您的回答添加解释并说明适用的限制和假设。

以上是关于使用 vb.net,挂钩指定的 USB 键盘,接收所需控制的字符并将接收到的字符阻止到其余窗口的主要内容,如果未能解决你的问题,请参考以下文章

如何从 VB.NET 中的 USB 端口获取数据

使用 MIDI 到 USB 电缆在 VB.NET 中获取信息

是否可以从 .NET 的全局键盘挂钩中确定当前用户

使用 vb.net 创建字母数字键盘

修改后的 USB 键盘驱动程序不接收按键 (Linux)

尝试为 VB.Net 应用程序创建键盘