【问题标题】:How to listen keyboard in background and fire keystrokes on demand?如何在后台听键盘并按需触发击键?
【发布时间】:2013-02-08 21:51:54
【问题描述】:

我想在 vb.NET 2008 中制作一个程序,它将在后台监听键盘,即即使应用程序已最小化(全局)。如果用户按下了某个特定的键,它应该以固定的给定时间间隔继续触发其他 2 个键,直到用户再次按下该特定键。

如何在 vb.NET 2008 中做到这一点?

【问题讨论】:

  • 是的,这是可能的。但是你为什么要这样做。

标签: vb.net visual-studio-2008 keystroke keyboard-hook keystrokes


【解决方案1】:

来源:Here

用法: 创建钩子

Private WithEvents kbHook As New KeyboardHook

那么就可以处理每个事件了:

Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown
    Debug.WriteLine(Key.ToString) 
End Sub 
Private Sub kbHook_KeyUp(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyUp 
    Debug.WriteLine(Key) 
End Sub

键盘挂钩类:

Imports System.Runtime.InteropServices

Public Class KeyboardHook

    <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
            Select Case wParam
                Case WM_KEYDOWN, WM_SYSKEYDOWN
                    RaiseEvent KeyDown(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
                Case WM_KEYUP, WM_SYSKEYUP
                    RaiseEvent KeyUp(CType(CType(Marshal.PtrToStructure(lParam, struct.GetType()), KBDLLHOOKSTRUCT).vkCode, Keys))
            End Select
        End If
        Return CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)
    End Function

    Public Sub New()
        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

    Protected Overrides Sub Finalize()
        If Not HHookID = IntPtr.Zero Then
            UnhookWindowsHookEx(HHookID)
        End If
        MyBase.Finalize()
    End Sub

End Class

【讨论】:

  • 我遇到了无法设置键盘挂钩错误。怎么了?
  • 代码运行良好。但是你必须项目 -> [项目名称] 属性 -> 调试 -> 取消选中“启用 Visual Studio 托管进程”,因为它会在你的程序之前拦截挂钩的消息。
  • 您好,我正在尝试使用此代码Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown Debug.WriteLine(Key.ToString) If Key.ToString() = "A" Then DF1Com1.Write("O:1/0", "1") End If End Sub 执行命令但是它不起作用。是不是我做错了什么?
  • 我得到了无法设置键盘挂钩异常,Visual Studio 2017,禁用托管进程的选项不存在
【解决方案2】:

如果您使用 KeyboardHook 类,请确保您必须在使用前构建您的程序。对于特定键的问题,您可以在 KeyDown 或 KeyUp 事件中触发它。但在此之前,您必须使用 sendkeys 将密钥发送到活动窗口。

SendKeys.Send("L") '将字母 L 发送到活动窗口。

然后你可以做下面的代码;下面检查是否按下了字母“a”。

Private Sub kbHook_KeyDown(ByVal Key As System.Windows.Forms.Keys) Handles kbHook.KeyDown
    Debug.WriteLine(Key.ToString) 
    if Key.ToString() = "a" then
     'trigger your sendkeys
    end if
End Sub 

要触发一个特定的按键,比如切换按钮,只需声明一个布尔变量来检查按钮是否被切换。您可以全局声明它:

将开关调暗为 boolean = false

只需更新您设置条件以检查按下的字母的区域。如下所示:

if Key.ToString() = "a" then
  if switch = false then
    switch = true
    'trigger send keys
  else
    switch = false
    'deactivate send keys
  end if
end if

要确定发送密钥的特定时间,请使用计时器。希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2013-03-03
    • 2013-03-12
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 2012-03-08
    • 2016-08-26
    相关资源
    最近更新 更多