Sure. I'm aware of all that, which is why the approach has to be slightly different.
All the following in a module: [tt]
Option Explicit
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Public Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Public Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Public Const HC_ACTION = 0
Public Const WM_KEYDOWN = &H100
Public Const VK_SHIFT = &H10
Public Const VK_CAPITAL = &H14
Public prevLowLevelKybd As Long
Public Type KBDLLHOOKSTRUCT
vkCode As Long ' virtual keycode
scanCode As Long ' hardware scancode
flags As Long
time As Long
dwExtraInfo As Long
End Type
Public Const WH_KEYBOARD_LL = 13
Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim HookStruct As KBDLLHOOKSTRUCT
Dim IsShifted As Boolean
If (nCode = HC_ACTION) Then
If wParam = WM_KEYDOWN Then
CopyMemory HookStruct, ByVal lParam, Len(HookStruct)
IsShifted = (GetKeyState(VK_SHIFT) And &H8000) Or (GetKeyState(VK_CAPITAL) And &H1) ' Check if character is shifted or not. Don't really need to bother with this if only interested in virtual key codes
' At this point we have correct info in HookStruct, and shifted status in IsShifted.
' So do whatever it it that you want to do...
End If
End If
LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
End Function
Public Sub ToggleHook(WantHook As Boolean)
If WantHook = True Then
prevLowLevelKybd = SetWindowsHookEx(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, App.hInstance, 0)
Else
UnhookWindowsHookEx prevLowLevelKybd
prevLowLevelKybd = 0
End If
End Sub
[/tt]
And, for this example, I have a small form with a checkbox on it call chkHookIt and the following code: [tt]
Option Explicit
Private Sub chkHookIt_Click()
ToggleHook (chkHookIt = vbChecked)
End Sub
Private Sub Form_Unload(Cancel As Integer)
If prevLowLevelKybd <> 0 Then UnhookWindowsHookEx prevLowLevelKybd
End Sub[/tt]