ELDeveloper
Programmer
Saw a bunch of questions about this including my own and came up with a solution. I found most of this from user strongm and added to it to trap system keys also. I only expanded on it enough to disable screen prints, including using the ALT key. It seems stable, but when running your app in the IDE, don't press the stop button or VB will die the next time you start it since the Hooks were left in place.
Just call ToggleHook(True) whenever you want it to start and ToggleHook(False) when you want it to stop. Thanks again strongm!
Enjoy =)
Option Explicit
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
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 = 256
Public Const SYS_KEY = 260
Public Const WH_KEYBOARD_LL = 13
Public Type WM_COMMAND
wNotifyCode As Long 'notification code
wID As Long 'item, control, or accelerator identifier
hwndCtl As Long 'handle of control
End Type
Public Type KBDLLHOOKSTRUCT
vkCode As Long ' virtual keycode
scanCode As Long ' hardware scancode
flags As Long ' Read MSDN documentation for further info on this member
time As Long
dwExtraInfo As Long
End Type
Public prevLowLevelKybd As Long
Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
' LowLevelKeyboardProc is only supported in NT 4.0 SP3 and later
On Error GoTo ErrorHandler
Dim HookStruct As KBDLLHOOKSTRUCT
Dim CommandStruct As WM_COMMAND
' Is it a keyboard message?
If wParam = WM_KEYDOWN Then 'a non-system key was pressed
CopyMemory HookStruct, ByVal lParam, Len(HookStruct)
Select Case HookStruct.vkCode
Case 44, 106
Wait (1) 'must wait since printscreen is obviously slow - use whatever sleep function you have
Clipboard.Clear
Debug.Print "Clearing Clipboard - <SHIFT | CNTRL>+PrintScreen"
Debug.Print Clipboard.GetData(2) 'should be a 0 to represent no BMPs
End Select
ElseIf wParam = SYS_KEY Then 'a system key was pressed
CopyMemory CommandStruct, ByVal lParam, Len(CommandStruct)
Select Case CommandStruct.wID
Case 84
Wait (1) 'must wait since printscreen is obviously slow - use whatever sleep function you have
Clipboard.Clear
Debug.Print "Clearing Clipboard - ALT+PrintScreen"
Debug.Print Clipboard.GetData(2) 'should be a 0 to represent no BMPs
End Select
Else 'WM_SYSCOMMAND
End If
' OK, pass everything on for default processing
LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
Exit Function
ErrorHandler:
If Err.Number = 521 Then 'don't fight for control of the clipboard, just wait it out
Wait (1)
Err.Clear
Resume
End If
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
Just call ToggleHook(True) whenever you want it to start and ToggleHook(False) when you want it to stop. Thanks again strongm!
Enjoy =)
Option Explicit
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
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 = 256
Public Const SYS_KEY = 260
Public Const WH_KEYBOARD_LL = 13
Public Type WM_COMMAND
wNotifyCode As Long 'notification code
wID As Long 'item, control, or accelerator identifier
hwndCtl As Long 'handle of control
End Type
Public Type KBDLLHOOKSTRUCT
vkCode As Long ' virtual keycode
scanCode As Long ' hardware scancode
flags As Long ' Read MSDN documentation for further info on this member
time As Long
dwExtraInfo As Long
End Type
Public prevLowLevelKybd As Long
Public Function LowLevelKeyboardProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
' LowLevelKeyboardProc is only supported in NT 4.0 SP3 and later
On Error GoTo ErrorHandler
Dim HookStruct As KBDLLHOOKSTRUCT
Dim CommandStruct As WM_COMMAND
' Is it a keyboard message?
If wParam = WM_KEYDOWN Then 'a non-system key was pressed
CopyMemory HookStruct, ByVal lParam, Len(HookStruct)
Select Case HookStruct.vkCode
Case 44, 106
Wait (1) 'must wait since printscreen is obviously slow - use whatever sleep function you have
Clipboard.Clear
Debug.Print "Clearing Clipboard - <SHIFT | CNTRL>+PrintScreen"
Debug.Print Clipboard.GetData(2) 'should be a 0 to represent no BMPs
End Select
ElseIf wParam = SYS_KEY Then 'a system key was pressed
CopyMemory CommandStruct, ByVal lParam, Len(CommandStruct)
Select Case CommandStruct.wID
Case 84
Wait (1) 'must wait since printscreen is obviously slow - use whatever sleep function you have
Clipboard.Clear
Debug.Print "Clearing Clipboard - ALT+PrintScreen"
Debug.Print Clipboard.GetData(2) 'should be a 0 to represent no BMPs
End Select
Else 'WM_SYSCOMMAND
End If
' OK, pass everything on for default processing
LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
Exit Function
ErrorHandler:
If Err.Number = 521 Then 'don't fight for control of the clipboard, just wait it out
Wait (1)
Err.Clear
Resume
End If
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