| TheProgrammingZone's front page. All the latest programming and game development news, as well as this week's feature game project!
| Game projects under development by members of the TheProgrammingZone Community. Show them your support, and check out their games!
| A forum to interact with your fellow programmers.
|TheProgrammingZone's products. Check out some of our in house products that we made.
|You want to contact the guy behind TheProgrammingZone? Here's where to do it!
prev | 1 | next
All about windows hooks
This is a complicated topic, so you might like to read what Microsoft say about it at http://msdn.microsoft.com/library/techart/msdn_hooks32.htm as additional reference.
Subclassing is a good technique for intercepting messages going to a specific window - but what if you want to watch all of the windows for a particular message? It would be far too onerous to subclass every window on the system - indeed it is unlikely that this would even be possible. Fortunately there is an alternative - Windows Hooks.
A windows hook works in a similar way to subclassing, in that you write a function to deal with the messages and then tell windows to pass the messages to it. The difference with a hook is that you are dealing with the messages before they are dispatched to an individual window's message queue so it is possible to watch for messages across all the windows in a thread or, in some cases, all the windows on the entire operating system.
However, if every message on the system were first passed through your procedure before being sent to the eventual destination window it would very seriously degrade the performance of the operating system. For this reason there are actually a number of different windows hooks you can install, each of which only intercepts a smaller subset of the range of messages.
The hook types are:
• WH_CALLWNDPROC and WH_CALLWNDPROCRET hooks allow you to monitor messages sent to a window using the SendMessage API call. The first is called before the message is passed to the window procedure to which the message is being sent (but you are not allowed to remove or modify the message unfortunately) and the latter is called when the window procedure has processed the message which allows you to examine the value returned by that window procedure.
• WH_CBT - This hook was designed for use by computer based training applications. It gets called whenever a window is created, destroyed, resized or moved. With this hook it is possible to prevent the action from happening. (Thus, for example, you could use this hook to prevent the creation of those nasty pop up adverts that seem to be everywhere on the net these days) To do so you simply return 1 from the hook procedure.
• WH_DEBUG - This hook was designed for use in debugging applications that themselves involve hooks. Basically a debug hook procedure is called before any of the other installed hooks and contains information about what is going to be passed to the other hook procedure.
• WH_FOREGROUNDIDLE - This hook is called whenever the foreground thread (in other words, the currently active application) is about to become idle. You can use this hook to trigger any routine maintenance or background processing with the minimum impact on the perceived speed of the operating system.
• WH_GETMESSAGE - This hook procedure is called whenever a message is removed from a window's message queue by the GetMessage API call or when a message is investigated using the PeekMessage API call. Using this hook you are allowed to alter the message being investigated/processed.
• WH_JOURNALPLAYBACK and WH_JOURNALRECORD hooks are used to record and playback messages being removed from the system message queue. Using these hooks it is possible to write applications that mimic the behavior of the windows recorder application. You could also use these hooks to automate repetitive tasks to provide a macro-like facility for windows.
• WH_KEYBOARD - This hook procedure is called whenever a keyboard event is about to be processed. Using this you can prevent keystrokes being processed (for example, to prevent the normal ALT+TAB behavior) or watch for a given key event and act on it. This latter gives you the ability to implement global hotkeys in your applications.
• WH_MOUSE - This hook procedure is called whenever a mouse event is about to be processed by a window.
• WH_MSGFILTER - This hook procedure is called whenever an event occurs in a dialog box, message box, menu or scroll bar but before the message is processed. Using this it is possible to override the default behavior of dialog and message boxes - for example if you want to restrict which directory the user can select in the save file dialog box.
• WH_SHELL - This hook procedure is called when a shell event is being processed. You can use this hook to prevent the user showing the task list, to monitor the user switching between keyboard layouts, to be notified when the title of a minimized application changes etc.
• WH_SYSMSGFILTER - This is the same as the WH_MSGFILTER hook except in that it can monitor events in any dialog box, message box, menu or scroll bar on a system-wide basis.
In Windows NT and Windows 2000, two additional hooks have been added:
• WH_KEYBOARD_LL - This is a low level version of the keyboard hook which allows you to install a global keyboard hooking procedure with less impact on the system than the WH_KEYBOARD hook.
• WH_MOUSE_LL - This is a low level version of the mouse hook which allows you to install a global keyboard hooking procedure with less impact on the system than the WH_MOUSE hook.
You install a hook procedure into the windows hook chain by calling the SetWindowsHookEx API function. This takes four parameters: idHook is the type of hook to install, from the list above, hookProc is the address of the procedure that you are installing, hMod is the handle of the DLL which contains the hook procedure (or null if the hook is only for the thread containing that procedure) and hThread is the handle of the thread for which you are installing the hook (or null to install a hook system-wide).
In Visual basic the declaration for this is:
Public Enum enHookTypes
WH_CALLWNDPROC = 4
WH_CBT = 5
WH_DEBUG = 9
WH_FOREGROUNDIDLE = 11
WH_GETMESSAGE = 3
WH_HARDWARE = 8
WH_JOURNALPLAYBACK = 1
WH_JOURNALRECORD = 0
WH_MOUSE = 7
WH_MSGFILTER = (-1)
WH_SHELL = 10
WH_SYSMSGFILTER = 6
WH_KEYBOARD_LL = 13
WH_MOUSE_LL = 14
WH_KEYBOARD = 2
Private 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
As with subclassing you must reset the window procedure back to what it was before you close down your application so in windows hooks you must remove your hook from the hook chain before closing down your application. Failure to do so will definitely cause a general protection fault. To remove the hook from the windows hook chain, you call the UnhookWindowsHookEx API function.
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
And in order to ensure that your hook procedure does not interfere with the normal operation of other hook procedures (if any are installed) you must use the CallNextHookEx API call
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
The format of the hook procedure for all of these hook types is the same, and in VB it is represented thus:
Public Function VB_HOOKPROC(ByVal code As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'\\ Note: If the code passed in is less than zero, it must be passed direct to the next hook proc
If code < 0 Then
VB_HOOKPROC = CallNextHookEx(Eventhandler.HookIdByType(Eventhandler.CurrentHookType), code, wParam, lParam)
'\\ Process the hook here
prev | 1 | next