keyboard hooking reporting twice!
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:
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.Drawing
Imports System.Threading
Module Keyboard
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
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Integer) As Integer
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
Public Structure keyboardStructure
Public vkCode As Integer
Public scanCode As Integer
Public flags As Integer
Public time As Integer
Public dwExtraInfo As Integer
End Structure
Private Const WH_KEYBOARD_LL As Integer = 13&
Public KeyboardHandle As Integer
Public Sub checkKeys(ByRef Hookstruct As keyboardStructure)
Debug.WriteLine("Hookstruct.vkCode: " & Hookstruct.vkCode)
If (Hookstruct.vkCode = 49) Then
keybd_event(50, 0, 0, 0)
End If
End Sub
Private Sub hookOutput(ByVal Text As String)
Debug.WriteLine(Text)
End Sub
Public Function keyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As keyboardStructure) As Integer
checkKeys(lParam)
End Function
Public Delegate Function KeyboardHookDelegate(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As keyboardStructure) As Integer
<MarshalAs(UnmanagedType.FunctionPtr)> Private callback As KeyboardHookDelegate
Public Sub HookKeyboard()
callback = New KeyboardHookDelegate(AddressOf keyboardCallback)
KeyboardHandle = SetWindowsHookEx(WH_KEYBOARD_LL, callback, Marshal.GetHINSTANCE([Assembly].GetExecutingAssembly.GetModules()(0)).ToInt32, 0)
Call CheckHooked()
End Sub
Public Sub CheckHooked()
If (Hooked()) Then
'' Debug.WriteLine("Keyboard hooked")
MessageBox.Show("Keyboard hooked")
Else
''Debug.WriteLine("Keyboard hook failed: " & Err.LastDllError)
MessageBox.Show("Keyboard hook failed: " & Err.LastDllError)
End If
End Sub
Private Function Hooked()
Hooked = KeyboardHandle <> 0
End Function
Public Sub UnhookKeyboard()
If (Hooked()) Then
Call UnhookWindowsHookEx(KeyboardHandle)
End If
End Sub
End Module
Re: keyboard hooking reporting twice!
Once for key down, and once for key up again.
The flags can tell you which is which.
Re: keyboard hooking reporting twice!
WH_KEYBOARD_LL is a constant declared in one of the header files in the Windows API. You have to use a value that matches that constant. It must be 13 because that's what it has been declared as, but it doesn't have to be named WH_KEYBOARD_LL. It's just a convention to name your API constants the same as they have been named in the Windows API header files, but it's just an identifier in your code so you could call it anything you want. As to how you know that it's that value, those who've been programming with the Windows API have posted that it's so on the Web. If you ever need to know the value of a Windows API constant you should just Google it and others will have posted something about it on the Web. There have been some relatively definitive compilations of Windos API documentation made. You could check out gigemboy's signature for some tools. I believe that the API Viewer has all the constant values but I don't know for sure because it refuses to run on my machine.
Re: keyboard hooking reporting twice!
well i got it to only fire once with each key is used. however it will simulate the key press before the actual key press is it possible to get this to be after.
As far as im aware it intercepts the key being used, checks it, simulates a key, and then continues with the original key press. Is it possible to tell it to continue with the physical key press then do the simulated press?
Re: keyboard hooking reporting twice!
What you could do is instead of telling it to continue with the physical keypress, then do what you want, do this:
Simulate the key they want to press
Simulate the key you want afterwards
Then block the physical key by returning 1 inside the keyboard callback function
Re: keyboard hooking reporting twice!
Okay i wrote an example of how to do it. I couldn't get my head around it last time :P
The difficulties with my solution is your own simulated keypresses are hooked. So if they press "1", instead of letting the physical keypress go through then press yours, it's possible to simulate "1" then "2", then block the physical "1" that they pressed. But you're "1" is hooked and will just do the same thing all over again.
But here's an example that will sort it out.
First add a variable at the top
VB Code:
Private Simulating As Boolean = False
Next change your keyboardCallback function to this
VB Code:
Public Function keyboardCallback(ByVal Code As Integer, ByVal wParam As Integer, ByRef lParam As keyboardStructure) As Integer
If checkKeys(lParam) = True Then Return 1
End Function
And finally make your checkKeys sub a function that returns a boolean, with the following code inside
VB Code:
Public Function checkKeys(ByRef Hookstruct As keyboardStructure) As Boolean
If Hookstruct.vkCode = 49 Then
If Simulating = False And Hookstruct.flags = 0 Then
Simulating = True
keybd_event(49, 0, 0, 0)
keybd_event(50, 0, 0, 0)
Simulating = False
Else
Return False
End If
Return True
End If
Return False
End Function
And that's it so now checkKeys is a function that tells keyboardCallback when to block and when not to.
I hope that does exactly what you wanted :)