I found some code which shows the keys that have been hooked. I have simplified the code alot from the example, but it seems to report the hooked keys twice and I need this only to happen once. I am have been looking at it for sometime but I can't see what is making it report the hook twice and not once.

The best way to see this happening is by pressing a key and the output message will be displayed twice.

I thought perhaps its reporting the keydown and keyup events maybe not sure whats going on.

Also can anyone explain to me why WH_KEYBOARD_LL has to = 13? How do you know it's 13 and not some other number, can't seem to find a referance to this anywhere.

VB Code:
  1. Imports System.Runtime.InteropServices
  2. Imports System.Reflection
  3. Imports System.Drawing
  4. Imports System.Threading
  5.  
  6. Module Keyboard
  7.  
  8.     Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As KeyboardHookDelegate, ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer
  9.     Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Integer) As Integer
  10.     Declare Function keybd_event Lib "user32" Alias "keybd_event" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) As Long
  11.  
  12.     Public Structure keyboardStructure
  13.         Public vkCode As Integer
  14.         Public scanCode As Integer
  15.         Public flags As Integer
  16.         Public time As Integer
  17.         Public dwExtraInfo As Integer
  18.     End Structure
  19.  
  20.  
  21.  
  22.  
  23.  
  24.     Private Const WH_KEYBOARD_LL As Integer = 13&
  25.     Public KeyboardHandle As Integer
  26.  
  27.  
  28.     Public Sub checkKeys(ByRef Hookstruct As keyboardStructure)
  29.  
  30.         Debug.WriteLine("Hookstruct.vkCode: " & Hookstruct.vkCode)
  31.  
  32.         If (Hookstruct.vkCode = 49) Then
  33.             keybd_event(50, 0, 0, 0)
  34.         End If
  35.  
  36.     End Sub
  37.  
  38.  
  39.     Private Sub hookOutput(ByVal Text As String)
  40.         Debug.WriteLine(Text)
  41.  
  42.     End Sub
  43.  
  44.  
  45.     Public Function keyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As keyboardStructure) As Integer
  46.         checkKeys(lParam)
  47.     End Function
  48.  
  49.  
  50.     Public Delegate Function KeyboardHookDelegate(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As keyboardStructure) As Integer
  51.  
  52.     <MarshalAs(UnmanagedType.FunctionPtr)> Private callback As KeyboardHookDelegate
  53.  
  54.     Public Sub HookKeyboard()
  55.         callback = New KeyboardHookDelegate(AddressOf keyboardCallback)
  56.  
  57.         KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, callback, Marshal.GetHINSTANCE([Assembly].GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
  58.  
  59.         Call CheckHooked()
  60.     End Sub
  61.  
  62.     Public Sub CheckHooked()
  63.         If (Hooked()) Then
  64.             '' Debug.WriteLine("Keyboard hooked")
  65.             MessageBox.Show("Keyboard hooked")
  66.         Else
  67.             ''Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
  68.             MessageBox.Show("Keyboard hook failed: " & Err.LastDllError)
  69.         End If
  70.     End Sub
  71.  
  72.     Private Function Hooked()
  73.         Hooked = KeyboardHandle <> 0
  74.     End Function
  75.  
  76.     Public Sub UnhookKeyboard()
  77.         If (Hooked()) Then
  78.             Call UnhookWindowsHookEx(KeyboardHandle)
  79.         End If
  80.     End Sub
  81.  
  82. End Module