It's unfortunate that when we feel a storm, we can roll ourselves over 'cause we're uncomfortable, oh well the devil makes us sin, but we like it when we're spinning, in his grin...

Δευτέρα 19 Δεκεμβρίου 2011

keyboard hooking VB.NET

 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  

Create the hook:
 Private WithEvents kbHook As New KeyboardHook  

And use it like this:

 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  

Thanks to sim0n.

1 σχόλιο: