PRB: Cannot Alter Messages with WH_KEYBOARD Hook

ID: Q33690


The information in this article applies to:


SYMPTOMS

After creating a program that uses the WH_KEYBOARD hook function to intercept a user's keystrokes and changing the wParam value before passing the hook code on to CallNextHookEx() (DefHookProc() for Windows 3.0), whichever application currently has the focus still receives the original character typed in rather than the translated character.


CAUSE

Keyboard messages cannot be altered with the WH_KEYBOARD hook. All that can be done is to "swallow" the message (return TRUE) or have the message passed on (return FALSE). In a keyboard hook function, when you return CallNextHookEx() or DefHookProc(), you are passing the event to the next hook procedure in the potential hook chain, and giving it a chance to look at the event to decide whether or not to discard it. You are not passing the message to the system as if you had called DefWindowProc() from a Window procedure.


RESOLUTION

NOTE: In the discussion below, ignore the references to the WH_CALLWNDPROC hook for Win32-based applications. Win32 does not allow an application to change the message in a CallWndProc, as 16-bit Windows does.

To change the value of wParam (and hence the character message that is received by the window with the focus), you must install the WM_GETMESSAGE and WH_CALLWNDPROC hooks. The WH_GETMESSAGE hook traps all messages retrieved via GetMessage() or PeekMessage(). This is the way actual keyboard events are received: the message is placed in the queue by Windows and the application retrieves it via GetMessage() or PeekMessage(). However, because applications can send keyboard messages with SendMessage(), it is best to also install the WH_CALLWNDPROC hook. This hook traps messages sent to a window via SendMessage().

These hooks pass you the address of the message structure so you can change it. In Windows 3.0, when you return DefHookProc() within a WH_GETMESSAGE or WH_CALLWNDPROC hook procedure, you are passing the address of the (potentially altered) contents of the message structure on to the next hook function in the chain. In Windows 3.1 and Win32, you should use the CallNextHookEx() function to pass the hook information to the next hook function. If you alter the wParam before passing on the message, this will change the character message eventually received by the application with the focus.

NOTE: For Windows 3.0, keep in mind that the hook callback procedure must be placed in a DLL with fixed code so that it will be below the EMS line and thus will always be present. If the hook callback procedure is not in a fixed code segment, it could be banked out when it is called, and this would crash the system. System-wide hooks in Windows 3.1 and in Win32, however, must still reside in a DLL.


Keywords          : kbHook kbNTOS kbGrpUser kbWinOS 
Version           : 
Platform          : 
Issue type        : kbprb 

Last Reviewed: March 5, 1999