vb.net 如何在后台听键盘并按需触发按键?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15038413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 12:29:12  来源:igfitidea点击:

How to listen keyboard in background and fire keystrokes on demand?

vb.netvisual-studio-2008keystrokekeyboard-hookkeystrokes

提问by user2101855

I want to make a program in vb.NET 2008 which will listen keyboard in background, i.e. even though the application is minimized (globally). If a specific key is been pressed by user, it should keep firing 2 other keys at regular given time intervals until the user presses that specific key again.

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

How can this be done in vb.NET 2008?

这如何在 vb.NET 2008 中完成?

回答by Parimal Raj

Source : Here

来源:这里

Usage: To create the hook

用法:创建钩子

Private WithEvents kbHook As New KeyboardHook

Then each event can be handled:

然后可以处理每个事件:

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

Keyboard Hook Class :

键盘挂钩类:

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

回答by Arvin Salvador

If you use KeyboardHook class, make sure you have to build your program before using. With regards to the question for a specific key, you can trigger it in KeyDown or KeyUp event. But before that, you have to use sendkeys to send keys to active window.

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

SendKeys.Send("L") 'Sends letter L to active window.

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

Then you can do the following code; below checks if letter "a" is being pressed.

然后你可以执行以下代码;下面检查是否正在按下字母“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 

To trigger a specific key like a switch button, just declare a boolean variable to check if the button is switched or not. You can declare it globally:

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

Dim switch as boolean = false

Dim 开关为 boolean = false

Just update the area where you set a condition to check the letter pressed. It will look like below:

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

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

To have a specific time in sending keys, use timer. I hope it helps.

要指定发送密钥的时间,请使用计时器。我希望它有帮助。