Как слушать клавиатуру в фоновом режиме и запускать нажатия клавиш по запросу?

Я хочу сделать программу в vb.NET 2008, которая будет слушать клавиатуру в фоновом режиме, т.е. даже если приложение свернуто (глобально). Если пользователь нажал определенную клавишу, он должен продолжать активировать 2 другие клавиши через равные промежутки времени, пока пользователь снова не нажмет эту конкретную клавишу.

Как это можно сделать в vb.NET 2008?


person user2101855    schedule 23.02.2013    source источник
comment
Да, это возможно. Но почему вы хотите это сделать.   -  person Arpit    schedule 23.02.2013


Ответы (2)


Источник: здесь

Использование: для создания крючка

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
person Parimal Raj    schedule 23.02.2013
comment
У меня возникла ошибка Не удалось установить клавиатурный хук. что случилось? - person Sajitha Rathnayake; 28.10.2014
comment
Код работает отлично. Но вам нужно Project -> [Project Name] Properties -> Debug -> Снимите флажок «Включить процесс размещения Visual Studio», поскольку это перехватывает перехваченные сообщения перед вашей программой. - person Eslam Sameh Ahmed; 22.10.2016
comment
Здравствуйте, я пытаюсь выполнить команду с этим кодом 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 Однако это не работает. Есть ли что-то, что я делаю неправильно? - person Arthor; 18.11.2017
comment
я получаю, что не удалось установить исключение перехвата клавиатуры, Visual Studio 2017, возможность отключить процесс хостинга не существует - person MirrorMirror; 21.01.2021

Если вы используете класс KeyboardHook, убедитесь, что вам нужно собрать свою программу перед использованием. Что касается вопроса для конкретного ключа, вы можете вызвать его в событии KeyDown или KeyUp. Но перед этим вы должны использовать sendkeys для отправки ключей в активное окно.

SendKeys.Send("L") 'Отправляет букву L в активное окно.

Затем вы можете сделать следующий код; ниже проверяет, нажата ли буква «а».

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 

Чтобы активировать определенную клавишу, например кнопку переключения, просто объявите логическую переменную, чтобы проверить, переключена ли кнопка или нет. Вы можете объявить его глобально:

Тусклый переключатель как логическое значение = ложь

Просто обновите область, где вы установили условие для проверки нажатой буквы. Это будет выглядеть следующим образом:

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

Чтобы иметь определенное время для отправки ключей, используйте таймер. Я надеюсь, что это помогает.

person Arvin Salvador    schedule 18.10.2016