Skip to content

Instantly share code, notes, and snippets.

@KOZ60
Last active October 1, 2023 13:51
Show Gist options
  • Save KOZ60/f3d4706c830ef31d333b41132baa63a8 to your computer and use it in GitHub Desktop.
Save KOZ60/f3d4706c830ef31d333b41132baa63a8 to your computer and use it in GitHub Desktop.
LowLevelKeyboardHook.vb
Imports System.ComponentModel
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
<DesignerCategory("code")>
<DefaultEvent("KeyDown")>
Public Class LowLevelKeyboardHook
Inherits Component
Private HookHandle As IntPtr = IntPtr.Zero
Private HookProcHandle As LowLevelKeyboardProcDelegate
Public Event KeyDown As KeyEventHandler
Public Event KeyUp As KeyEventHandler
Public Sub New()
End Sub
Public Sub New(container As IContainer)
Me.New()
If container Is Nothing Then
Throw New ArgumentNullException("container")
End If
container.Add(Me)
End Sub
Public Sub Start()
If HookHandle = IntPtr.Zero Then
HookProcHandle = AddressOf LowLevelKeyboardProc
HookHandle = SetWindowsHookEx(WH_KEYBOARD_LL,
HookProcHandle,
GetModuleHandle(Nothing),
0)
End If
End Sub
Public Sub [Stop]()
If HookHandle <> IntPtr.Zero Then
UnhookWindowsHookEx(HookHandle)
HookProcHandle = Nothing
HookHandle = IntPtr.Zero
End If
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
Me.Stop()
End Sub
Private Function LowLevelKeyboardProc(
code As Integer, wParam As IntPtr, lparam As IntPtr) As IntPtr
Try
If code = HC_ACTION Then
Dim st = Marshal.PtrToStructure(Of KBDLLHOOKSTRUCT)(lparam)
Dim vkCode As Keys = st.vkCode Or Control.ModifierKeys
Dim ke = New KeyEventArgs(vkCode)
Select Case wParam.ToInt64()
Case WM_KEYDOWN
OnKeyDown(ke)
Case WM_KEYUP
OnKeyUp(ke)
End Select
End If
Finally
End Try
Return CallNextHookEx(HookHandle, code, wParam, lparam)
End Function
Protected Overridable Sub OnKeyDown(ke As KeyEventArgs)
RaiseEvent KeyDown(Me, ke)
End Sub
Protected Overridable Sub OnKeyUp(ke As KeyEventArgs)
RaiseEvent KeyUp(Me, ke)
End Sub
Private Const User32 = "user32.dll"
Private Const Kernel32 = "kernel32.dll"
Private Const WH_KEYBOARD_LL = 13
Private Const HC_ACTION = 0
Private Const WM_KEYDOWN = &H100
Private Const WM_KEYUP = &H101
Private Delegate Function LowLevelKeyboardProcDelegate(
code As Integer, wParam As IntPtr, lparam As IntPtr) As IntPtr
<StructLayout(LayoutKind.Sequential)>
Private Structure KBDLLHOOKSTRUCT
Public vkCode As Keys
Public scanCode As Keys
Public flags As Integer
Public time As Integer
Public dwExtraInfo As IntPtr
End Structure
<DllImport(User32, CharSet:=CharSet.Auto)>
Private Shared Function SetWindowsHookEx(
idHook As Integer, lpfn As LowLevelKeyboardProcDelegate,
hInstance As IntPtr, threadId As Integer) As IntPtr
End Function
<DllImport(User32, CharSet:=CharSet.Auto)>
Private Shared Function UnhookWindowsHookEx(hhk As IntPtr) _
As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport(User32, CharSet:=CharSet.Auto)>
Private Shared Function CallNextHookEx(
idHook As IntPtr, code As Integer,
wParam As IntPtr, lparam As IntPtr) As IntPtr
End Function
<DllImport(Kernel32, CharSet:=CharSet.Auto)>
Private Shared Function GetModuleHandle(lpModuleName As String) As IntPtr
End Function
End Class
@KOZ60
Copy link
Author

KOZ60 commented Oct 1, 2023

How to use:

Public Class Form1

    Private WithEvents KbdHook As New LowLevelKeyboardHook

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

    Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        KbdHook.Stop()
    End Sub

    Private Sub KbdHook_KeyDown(sender As Object, e As KeyEventArgs) Handles KbdHook.KeyDown
        If e.KeyCode = Keys.C AndAlso e.Control Then
            TextBox1.AppendText(Now & " CTRL + C KEYDOWN" & vbCrLf)
        End If
    End Sub

End Class

It is safer to use it by pasting it on Form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment