|3||Code Libraries|| |
Win32 Hooks in VB - The vbAccelerator Hook Library
The ultimate low-level control over Windows
this code has been superceded by the version at the new site.
Hooks Compared to Sub-Classing
Essentially a Windows Hook is like a subclass except it applies to the next point up in the message chain. In Win32, messages are queued and sent to the appropriate window via the WindowProc function. A subclass can intercept messages by replacing the existing WindowProc function with a new one.
With a Hook, you get to see all messages before Windows has decided which WindowProc procedure to direct the message to. You can modify or discard most messages at this point too. So using the Hook technique you not only get to act on messages at the highest point; you can also get at messages regardless of which window is going to get the message. This is very useful for process Keyboard or Mouse messages on a global basis in your application, because these messages are normally directed to the window with the focus, making it very awkward to perform this technique using Subclassing because you would have to subclass every single window handle in your application to follow the mouse events. Using a Hook, the process is simple!
Let's say you want to place a button on a PictureBox child of an MDI form. This button has the caption &New... and hence the accelerator key Alt+N. In normal Windows applications you would expect chooing Alt+N would activate that button regardless of what window has the focus. But it doesn't work whenever the child form has the focus! In fact Alt+N only does anything when the MDI form has the focus.
This is actually a fundamental problem in VB for MDI forms - there is no way for an accelerator on another form to be active when there is a child form active. We could solve this problem by duplicating the New button onto the child form, but in order for it to respond to accelerator keys it must be visible and part of the tab order - not what you want.
Solving the problem with a Windows Hook is quite simple. We install a hook of type WH_KEYBOARD. Then the app receives all keyboard events for the entire application. When the keyboard events indicate that Alt+N has been pressed, the code just needs to check whether the MDIForm is the same as the window returned by GetActiveWindow; if it is it then the code fires the cmdNew_Click event and eats the keyboard message.
Hook Scope: System Wide or Local Thread Hooks
One of the features of the Win32 Hook library is that it allows you to specify whether the scope of your hook is local to the current thread or whether it applies to all windows in the entire system. System Wide hooks are always a topic of interest because they let you modify windows in other applications; for example the stupidly-named Window Blinds application uses this method to apply a skin when drawing all windows on your system (well, it tries to, anyway!)
Before you get excited, though, VB on its own cannot be used to create a system-wide hook. This is because the hook procedure must reside within a Windows DLL, and VB cannot create these beasts (because you cannot specify to export the HookProc function). Also I should point out that system-wide hooks aren't much fun to write: you can't debug them, and if anything goes wrong it takes your whole system down! If you have some C knowledge, however, you can steal code either from the Spy utility provided with the NT Resource Kit or there is a most interesting sample at CodeGuru which adds a Pin button to the caption of all windows on the system.
Types Of Windows Hooks
There are 14 different types of Windows Hooks defined for Win32, however, some of these are not implemented and some cannot be used in Visual Basic or are of very limited value when not used System Wide.
That leaves the following:
When you install a Hook, Win32 actually adds it to what is termed the "Hook Chain". This allows you to install multiple Hooks of the same type in an application. When the first Hook is added, Windows places it at the start of the chain and begins passing messages to the Hook and receiving them from it. If another hook of the same type is added on the same thread, windows then directs output from the first hook to the second one before receiving the output for its own use.
This means that you must be careful when using a Hook to modify or remove messages. If there are two Hooks on the same thread, and one removes messages, behaviour may differ depending on the order the Hooks are installed. And in VB5 there is very little control over the order that controls are created...
The Windows Hooks Library
The hooks library is designed to be used either as a DLL or compiled directly into your application. An example of compiling the library directly into code is provided in the vbAccelerator Accelerator control, so this section will cover using the DLL version.
The Hooks Library consists of two parts:
Documentation for the vbAccelerator Windows Hook Library's properties, methods and classes is available as an RTF. This documentation was created with the Active X Documenter.
Click here to download/view the vbalHook method and event documentation
This sample will give you a quick introduction to the Hooks library. Start a new project, and add a reference to the vbAccelerator Window Hooks Library by choosing Project->References and selecting "vbAccelerator Windows Hook Helper DLL". If it isn't there, click Browse and search for vbalHook.DLL on your disk. Once you have a reference, add various controls to your form including a TextBox control. Then add the following code:
The Sample Code
There are two samples provided with the download: