Kyle Marsh
Microsoft Developer Network Technology Group
Created: July 29, 1993
Revised: February 1994
Added exception for journal hooks in "Filter functions in DLLs" section.
Added .EXE file to where filters can reside in "WH_JOURNALRECORD" and "WH_JOURNALPLAYBACK" sections.
Changed HIWORD and LOWORD to HIBYTE and LOBYTE in "HC_ACTION" section.
Click to open or copy the files in the Hooks sample application.
This article describes hooks and their use in the Microsoft® Win32® application programming interface (API). It discusses hook functions, filter functions, and the following types of hooks:
Terminology In this article, the term Windows refers to the Windows family of operating systems, that is, 16-bit Windows, Windows NT®, and Windows for Workgroups. Likewise, Windows 3.1 refers to the 3.1 version of these operating systems.
In the Microsoft® Windows® operating system, a hook is a mechanism by which a function can intercept events (messages, mouse actions, keystrokes) before they reach an application. The function can act on events and, in some cases, modify or discard them. Functions that receive events are called filter functions and are classified according to the type of event they intercept. For example, a filter function might want to receive all keyboard or mouse events. For Windows to call a filter function, the filter function must be installed—that is, attached—to a Windows hook (for example, to a keyboard hook). Attaching one or more filter functions to a hook is known as setting a hook. If a hook has more than one filter function attached, Windows maintains a chain of filter functions. The most recently installed function is at the beginning of the chain, and the least recently installed function is at the end.
When a hook has one or more filter functions attached and an event occurs that triggers the hook, Windows calls the first filter function in the filter function chain. This action is known as calling the hook. For example, if a filter function is attached to the CBT hook and an event that triggers the hook occurs (for example, a window is about to be created), Windows calls the CBT hook by calling the first function in the filter function chain.
To maintain and access filter functions, applications use the SetWindowsHookEx and the UnhookWindowsHookEx functions.
Hooks provide powerful capabilities for Windows-based applications. These applications can use hooks to:
Applications have used hooks to:
To use hooks, you need to know:
Windows-based applications use the SetWindowsHookEx, UnhookWindowsHookEx, and CallNextHookEx functions to manage the hooks filter function chain. Before version 3.1, Windows implemented hook management with the SetWindowsHook, UnhookWindowsHook, and DefHookProc functions. Although these functions are implemented in Win32, they have fewer capabilities than the new (Ex) versions. Please convert your existing code to the new versions of these functions, and always use the new functions for new code.
SetWindowsHookEx and UnhookWindowsHookEx are described below. See "Calling the next function in the filter function chain" for a discussion of CallNextHookEx.
The SetWindowsHookEx function adds a filter function to a hook. This function takes four arguments:
Some hooks may be set with system scope only; some may be set only for a specific thread; and others may have either system or thread scope, as shown in the following table.
Hook | Scope |
WH_CALLWNDPROC | Thread or System |
WH_CBT | Thread or System |
WH_DEBUG | Thread or System |
WH_GETMESSAGE | Thread or System |
WH_JOURNALRECORD | System Only |
WH_JOURNALPLAYBACK | System Only |
WH_FOREGROUNDIDLE | Thread or System |
WH_SHELL | Thread or System |
WH_KEYBOARD | Thread or System |
WH_MOUSE | Thread or System |
WH_MSGFILTER | Thread or System |
WH_SYSMSGFILTER | System Only |
For a given hook type, thread hooks are called first, followed by system hooks.
It is a good idea to use thread hooks instead of system hooks for several reasons. Thread hooks:
SetWindowsHookEx returns a handle to the installed hook (an HHOOK). The application or library must use this handle to identify this hook later when it calls the UnhookWindowsHookEx function. SetWindowsHookEx returns NULL if it is unable to add the filter function to the hook. SetWindowsHookEx also sets the last error to one of the values listed below to indicate why the function failed.
Windows keeps the filter function chain internally (see the figure below) and does not rely on the filter functions to store the address of the next filter function in the chain correctly (as versions of Windows before 3.1 did). Thus, hooks are much more robust in Windows version 3.1 than they were in previous versions. In addition, performance is enhanced significantly because the filter function chain is kept internally.
The filter function chain in Windows 3.1
To remove a filter function from a hook's chain, call the UnhookWindowsHookEx function. This function takes the hook handle returned from SetWindowsHookEx and returns a value indicating whether the hook was removed. UnhookWindowsHookEx always returns TRUE at this time.
Filter (hook) functions are functions that are attached to a hook. Because filter functions are called by Windows and not by an application, they are sometimes referred to as callback functions. For consistency, this article uses the term filter functions.
All filter functions must have the following form:
LRESULT CALLBACK FilterFunc( nCode, wParam, lParam )int nCode;
WORD wParam;
DWORD lParam;
All filter functions should return a LONG. FilterFunc is a placeholder for the actual filter function name.
Filter functions receive three parameters: ncode (the hook code), wParam, and lParam. The hook code is an integer code that informs the filter function of any additional data it should know. For example, the hook code might indicate what action is causing the hook to be called.
In previous versions of Windows (before 3.1), the hook code indicated whether the filter function should process the event or call DefHookProc. If the hook code is less than zero, the filter function should not process the event; it should call DefHookProc, passing the three parameters it was passed without any modification. Windows used these negative codes to maintain the filter function chain, with help from the applications.
Windows 3.1 still requires that if Windows sends a filter function a negative hook code, the filter function must call CallNextHookEx with the parameters Windows passed to the filter function. The filter function must also return the value returned by CallNextHookEx. Windows 3.1 never sends negative hook codes to filter functions.
The second parameter passed to the filter function, wParam, is a WPARAM, and the third parameter, lParam, is an LPARAM. These parameters pass information needed by the filter function. Each hook attaches different meanings to wParam and lParam. For example, filter functions attached to the WH_KEYBOARD hook receive a virtual-key code in wParam, and lParam contains bit fields that describe the state of the keyboard at the time of the key event. Filter functions attached to the WH_MSGFILTER hook receive a NULL value in wParam and a pointer to a message structure in lParam. Some hooks attach different meanings for wParam and lParam depending on the event that causes the hook to be called. For a complete list of arguments and their meanings for each hook type, see the filter functions listed below in Platform SDK.
Hook | Filter function documentation |
WH_CALLWNDPROC | CallWndProc |
WH_CBT | CBTProc |
WH_DEBUG | DebugProc |
WH_GETMESSAGE | GetMsgProc |
WH_JOURNALRECORD | JournalRecordProc |
WH_JOURNALPLAYBACK | JournalPlaybackProc |
WH_SHELL | ShellProc |
WH_KEYBOARD | KeyboardProc |
WH_MOUSE | MouseProc |
WH_MSGFILTER | MessageProc |
WH_SYSMSGFILTER | SysMsgProc |
When a hook is set, Windows calls the first function in the hook's filter function chain, and the responsibility of Windows ends. The filter function is responsible for ensuring that the next filter function in the chain is called. Windows supplies CallNextHookEx to enable a filter function to call the next filter in the filter function chain. CallNextHookEx takes four parameters.
The first parameter is the value returned from the SetWindowsHookEx call. This value is currently ignored by Windows, but this behavior may change in the future.
The next three parameters—nCode, wParam, and lParam—are the parameters that Windows passed to the filter function.
Windows stores the filter function chain internally and keeps track of which filter function it is calling. When CallNextHookEx is called, Windows determines the next filter function in the chain and calls that function.
At times, a filter function may not want to pass an event to the other hook functions on the same chain. In particular, when a hook allows a filter function to discard an event and the filter function decides to do so, the function must not call CallNextHookEx. When a filter function modifies a message, it may decide not to pass the message to the rest of the filter function chain.
Because filter functions are not installed in any particular order, you cannot be sure where your function is in the filter function chain at any moment except at the moment of installation, when it is the first function in the chain. As a result, you are never absolutely certain that you will get every event that occurs. A filter function installed ahead of your filter function in the chain—a function that was installed after your function timewise—might not pass the event to your filter function.
Systemwide filter functions must reside in a DLL. In Win16 it was possible (although not recommended) to install a systemwide hook to a filter function in an application. This does not work in Win32. Do not install systemwide filter functions that are not in DLLs, even if it does seem to work on a particular system. The journal hooks, WH_JOURNALRECORD and WH_JOURNALPLAYBACK, are exceptions to this rule. Because of the way Windows calls these hooks, their filter functions do not have to be in a DLL.
Filter functions for systemwide hooks must be prepared to share any data they need across the different processes they are running from. A DLL is mapped into the address space of each of its client processes. Global variables within the DLL will be instance specific unless they are placed in a shared data section. For example, the HOOKSDLL.DLL library in the Hooks sample application needs to share two data items:
To share this data, HOOKSDLL puts these data items in a shared data section. Here are the steps HOOKSDLL takes to share the data:
// Shared DATA
#pragma data_seg(".SHARDATA")
static HWND hwndMain = NULL; // Main hwnd. We will get this from the app.
static int nLineHeight = 0; // Height of lines in window.
#pragma data_seg()
SECTIONS
.SHARDATA Read Write Shared
hooksdll.exp: hooksdll.obj hooksdll.def
$(implib) -machine:$(CPU) \
-def:hooks.def \
hooksdll.obj \
-out:hooksdll.lib
hooksdll.dll: hooksdll.obj hooksdll.def hooksdll.lib hooksdll.exp
$(link) $(linkdebug) \
-base:0x1C000000 \
-dll \
-entry:LibMain$(DLLENTRY) \
-out:hooksdll.dll \
hooksdll.exp hooksdll.obj hooksdll.rbj \
$(guilibsdll)
Windows calls this hook whenever the Windows SendMessage function is called. The filter functions receive a hook code from Windows indicating whether the message was sent from the current thread and receive a pointer to a structure containing the actual message.
The CWPSTRUCT structure has the following form:
typedef struct tagCWPSTRUCT {
LPARAM lParam;
WPARAM wParam;
DWORD message;
HWND hwnd;
} CWPSTRUCT, *PCWPSTRUCT, NEAR *NPCWPSTRUCT, FAR *LPCWPSTRUCT;
Filters can process the message, but cannot modify the message (this was possible in 16-bit Windows). The message is sent to the Windows function for which it was intended. This hook is a significant drain on system performance, especially when it is installed as a systemwide hook, so use it only as a development or debugging tool.
To write a CBT application, the developer must coordinate the CBT application with the application for which it is written. Windows supplies the WH_CBT hook to make this possible. Windows passes a hook code to the filter function, indicating which event has occurred and the appropriate data for the event.
A filter function attached to the WH_CBT hook needs to be aware of ten hook codes:
Windows calls the WH_CBT hook with this hook code when any window is about to be activated. In the case of thread-specific hooks, the window must be owned by the thread. If the filter function returns TRUE, the window is not activated.
The wParam parameter contains the handle to the window being activated. The lParam parameter contains a far pointer to CBTACTIVATESTRUCT, which has the following structure:
typedef struct tagCBTACTIVATESTRUCT
{
BOOL fMouse; // TRUE if activation results from a
// mouse click; otherwise FALSE.
HWND hWndActive; // Contains the handle to the
// currently active window.
} CBTACTIVATESTRUCT, *LPCBTACTIVATESTRUCT;
Windows calls the WH_CBT hook with this hook code when a window is about to be created. In the case of thread-specific hooks, the thread must be creating the window. The WH_CBT hook is called before Windows sends the WM_GETMINMAXINFO, WM_NCCREATE, or WM_CREATE messages to the window. Thus, the filter function can return TRUE and not allow the window to be created.
The wParam parameter contains the handle to the window being created. The lParam parameter contains a pointer to the following structure.
/*
* HCBT_CREATEWND parameters pointed to by lParam
*/
struct CBT_CREATEWND
{
struct tagCREATESTRUCT *lpcs; // The create parameters for the
// new window.
HWND hwndInsertAfter; // The window this window will
// be added after, in Z-order.
} CBT_CREATEWND, *LPCBT_CREATEWND;
A filter function can alter the hwndInsertAfter value or the values in lpcs.
Windows calls the WH_CBT hook with this hook code when Windows is about to destroy any window. In the case of thread-specific hooks, the thread must own the window. Windows calls the WH_CBT hook before the WM_DESTROY message is sent. If the filter function returns TRUE, the window is not destroyed.
The wParam parameter contains the handle to the window being destroyed. The lParam parameter contains 0L.
Windows calls the WH_CBT hook with this hook code when Windows is about to minimize or maximize a window. In the case of thread-specific hooks, the thread must own the window. If the filter function returns TRUE, the action does not occur.
The wParam parameter contains the handle to the window being minimized or maximized. The lParam is any one of the SW_* values defined in WINUSER.H specifying the operation that is taking place.
Windows calls the WH_CBT hook with this hook code when Windows is about to move or size a window, and the user has just finished selecting the new window position or size. In the case of thread-specific hooks, the thread must own the window. If the filter function returns TRUE, the action does not occur.
The wParam parameter contains the handle to the window being moved or sized. The lParam parameter contains an LPRECT that points to the drag rectangle.
Windows calls the WH_CBT hook with this hook code when Windows processes a system command. In the case of a thread-specific hook, the thread must own the window whose System menu is being used. The WH_CBT hook is called from within DefWindowsProc. If an application does not send the WH_SYSCOMMAND message to DefWindowsProc, this hook is not called. If the filter function returns TRUE, the system command is not processed.
The wParam parameter contains the system command (SC_TASKLIST, SC_HOTKEY, and so on) that is about to be performed. If wParam is SC_HOTKEY, the LOWORD of lParam contains the handle to the window for which the hot key applies. If wParam contains any value other than SC_HOTKEY and if the System menu command is selected with the mouse, the LOWORD of lParam contains the horizontal position of the cursor and the HIWORD of lParam contains the vertical position of the cursor.
The following system commands trigger this hook from within DefWindowProc:
SC_CLOSE | Close the window. |
SC_HOTKEY | Activate the window associated with the application-specified hot key. |
SC_HSCROLL | Scroll horizontally. |
SC_KEYMENU | Retrieve a menu through a keystroke. |
SC_MAXIMIZE | Maximize the window. |
SC_MINIMIZE | Minimize the window. |
SC_MOUSEMENU | Retrieve a menu through a mouse click. |
SC_MOVE | Move the window. |
SC_NEXTWINDOW | Move to the next window. |
SC_PREVWINDOW | Move to the previous window. |
SC_RESTORE | Save the previous coordinates (checkpoint). |
SC_SCREENSAVE | Execute the screen-save application. |
SC_SIZE | Size the window. |
SC_TASKLIST | Execute or activate the Windows Task Manager application. |
SC_VSCROLL | Scroll vertically. |
Windows calls the WH_CBT hook with this hook code when a mouse event is removed from a thread's input queue and the mouse hook is set. Windows will call a systemwide hook when a mouse event is removed from any input queue and either a systemwide mouse hook or a thread-specific hook for the current thread is installed. This hook code is not generated unless a filter function is attached to the WH_MOUSE hook. Despite its name, HCBT_CLICKSKIPPED is called not only for skipped mouse events but also whenever a mouse event is removed from the system queue. Its main use is to install a WH_JOURNALPLAYBACK hook in response to a mouse event. (See the "WM_QUEUESYNC" section below for more information.)
The wParam parameter contains the message identifier for the mouse message—for example, the WM_LBUTTONDOWN or any WM_?BUTTON* messages. The lParam parameter contains a far pointer to MOUSEHOOKSTRUCT, which has the following structure:
typedef struct tagMOUSEHOOKSTRUCT {
POINT pt; // Location of mouse in screen coordinates
HWND hwnd; // Window that receives this message
UINT wHitTestCode; // The result of hit-testing (HT_*)
DWORD dwExtraInfo; // Extra info associated with the current message
} MOUSEHOOKSTRUCT, FAR *LPMOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;
Windows calls the WH_CBT hook with this hook code when a keyboard event is removed from the system queue and the keyboard hook is set. Windows will call a systemwide hook when a keyboard event is removed from any input queue and either a systemwide keyboard hook or a thread-specific hook for the current thread is installed. This hook code is not generated unless a filter function is attached to the WH_KEYBOARD hook. Despite its name, HCBT_KEYSKIPPED is called not only for skipped keyboard events but also whenever a keyboard event is removed from the system queue. Its main use is to install a WH_JOURNALPLAYBACK hook in response to a keyboard event. (See the "WM_QUEUESYNC" section below for more information.)
The wParam parameter contains the virtual-key code—the same value as wParam of GetMessage or PeekMessage for WM_KEY* messages. The lParam parameter contains the same value as the lParam parameter of GetMessage or PeekMessage for WM_KEY* messages.
WM_QUEUESYNC
While executing, a CBT application often must react to events in the main application. Keyboard or mouse events usually trigger these events. For example, a user clicks an OK button in a dialog box, after which the CBT application wants to play a series of keystrokes to the main application. The CBT application can use a mouse hook to determine whether the OK button was clicked. Upon determining that it wants to play some keystrokes to the main application, the CBT application must wait until the main application completes the processing of the OK button before beginning to play the new keystrokes. The CBT application would not want to apply the keystrokes to the dialog box.
The CBT application can use the WM_QUEUESYNC message to monitor the main application and determine when an action is completed. The CBT application monitors the main application with a mouse or a keyboard hook and looks for events to which it must respond. By watching the main application with a mouse or a keyboard hook, the CBT application becomes aware of when an event that needs a response begins. The CBT application must wait until the event is completed before responding to it.
To determine when the action is complete, the CBT application takes these steps:
Windows calls the WH_CBT hook with this hook code when Windows is about to set the focus to any window. In the case of thread-specific hooks, the window must belong to the thread. If the filter function returns TRUE, the focus does not change.
The wParam parameter contains the handle to the window that receives the focus. The lParam parameter contains the handle to the window that loses the focus.
Windows calls the WH_CBT hook with this hook code when a WM_QUEUESYNC message is removed from the system queue while a window is being resized or moved. The hook is not called at any other time. In the case of thread-specific hooks, the window must belong to the thread.
Both the wParam and lParam parameters contain zero.
Windows calls this hook when Windows is about to call a filter function. Filters cannot modify the values for the hook but can stop Windows from calling the original filter function by returning a nonzero value.
The wParam parameter contains the ID of the hook to be called, for example, WH_MOUSE. The lParam parameter contains a pointer to the following structure:
typedef struct tagDEBUGHOOKINFO
{
DWORD idThread; // The thread ID for the current thread
LPARAM reserved;
LPARAM lParam; // The lParam for the target filter function
WPARAM wParam; // The wParam for the target filter function
int code;
} DEBUGHOOKINFO, *PDEBUGHOOKINFO, NEAR *NPDEBUGHOOKINFO, FAR* LPDEBUGHOOKINFO;
Windows calls this hook when there is no user input to process for the current thread. In the case of thread-specific hooks, Windows calls the hook only when that thread is the current thread and there is no input for the thread. This is a notification-only hook; both the wParam and lParam parameters are zero.
Windows calls this hook when the GetMessage or the PeekMessage function is about to return a message. The filter functions receive a pointer to a structure containing the actual message from Windows. The message, including any modifications, is sent to the application that originally called GetMessage or PeekMessage. The lParam parameter contains a pointer to a MSG structure:
typedef struct tagMSG { /* msg */
HWND hwnd; \\ The window whose Winproc will receive the message
UINT message; \\ The message number
WPARAM wParam;
LPARAM lParam;
DWORD time; \\ The time the message was posted
POINT pt; \\ The cursor position in screen coordinates
\\ of the message
} MSG;
This hook is not currently implemented in Win32.
Journal hooks are used to record and playback events. They are available only as systemwide hooks and should, therefore, be used as little as possible. These hooks affect all Windows-based applications; although the desktop allows no other hooks, journal hooks can record and play back events from and to the desktop. Another side-effect of journal hooks is that all system input queues are attached though the thread that installed the hook. This means that all system input must pass through this one point of execution.
Win32 takes special steps to allow a user to cancel a journal hook so that it does not lock the system. Windows will uninstall a record or playback journal hook when the user presses CTRL+ESC, ALT+ESC, or CTRL+ALT+DEL. Windows then notifies the application that had a journal hook installed by posting a WM_CANCELJOURNAL message.
This message is posted with a NULL window handle so that it is not dispatched to a window procedure. The best way to catch this message is to install a WH_GETMESSAGE filter function that watches for the message. The Win32 documentation also mentions that an application can catch the WM_CANCELJOURNAL message between a call to GetMessage (or PeekMessage) and DispatchMessage. Although the message can be caught at this point, the application may not be there when the message is sent. For example, if the application is in a dialog box, its main message loop will not be called.
The CTRL+ESC, ALT+ESC, and CTRL+ALT+DEL key combinations are built into the system so the user can always stop a journal hook. It would be nice if every application that uses a journal hook could also supply a way for the user to stop journalling. The suggested way to stop journalling is by using VK_CANCEL (CTRL+BREAK).
Windows calls this hook when it removes an event from the system queue. Thus, these filters are called for all mouse and keyboard events except for those played back by a journal playback hook. Filters may process the message (that is, record or save the event in memory or on disk or both), but cannot modify or discard the message. Filters for this hook may reside in a DLL or an .EXE file. Only the HC_ACTION hook code is implemented in Win32.
HC_ACTION
Windows calls the WH_JOURNALRECORD hook with this hook code when it takes an event from the system queue. The hook code signals the filter function that this is a normal event. The lParam parameter to the filter function contains a pointer to an EVENTMSG structure. The usual recording procedure is to take all EVENTMSG structures passed to the hook and store them in memory or, if events exceed memory storage capacity, write them to disk.
The EVENTMSG structure is defined in WINDOWS.H and has the following structure:
typedef struct tagEVENTMSG {
UINT message;
UINT paramL;
UINT paramH;
DWORD time;
HWND hwnd;
} EVENTMSG;
typedef struct tagEVENTMSG *PEVENTMSG, NEAR *NPEVENTMSG, FAR *LPEVENTMSG;
The message element of the EVENTMSG structure is the message ID for the message, the WM_* value. The paramL and paramH values depend on whether the event is a mouse or a keyboard event. If it is a mouse event, the values contain the x and y coordinates of the event. If it is a keyboard event, paramL contains the scan code in the HIBYTE and the virtual-key code in the LOBYTE, and paramH contains the repeat count. Bit 15 of the repeat count specifies whether the event is an extended key. The time element of the EVENTMSG structure contains the system time (when the event occurred), which it obtained from the return value of GetTickCount. The hwnd is the window handle for the event.
The amount of time between events is determined by comparing the time element of an event with the time of subsequent events. This time delta is needed when playing back the recorded events.
This hook is used to provide mouse and keyboard messages to Windows as if they were inserted in the system queue. This hook is generally used to play back events recorded with the WH_JOURNALRECORD hook, but also provides the best way to send events to another application. Whenever a filter function is attached to this hook, Windows calls the first filter function in the function chain to get events. Windows discards any mouse moves while WH_JOURNALPLAYBACK is installed. All other keyboard and mouse input is queued until the WH_JOURNALPLAYBACK hook has no filter functions attached. Filters for this hook may reside in a DLL or an .EXE file. A filter function attached to this hook needs to be aware of the following hook codes:
HC_GETNEXT
Windows calls the WH_JOURNALPLAYBACK hook with this hook code when it accesses a thread's input queue. In most cases, Windows makes this call many times for the same message. The lParam parameter to the filter function contains a pointer to an EVENTMSG structure (see above). The filter function must put the message, the paramL value, and the paramH value into the EVENTMSG structure. These are usually copied directly from the recorded event made during WH_JOURNALRECORD.
The filter function must tell Windows when to process the message that the filter function is giving Windows. Windows needs two values for its scheduling: (1) the amount of time Windows should wait before processing the message; (2) the time at which the message is to be processed. The usual method of calculating the time to wait before processing is to subtract the EVENTMSG time element of the previous message from the EVENTMSG time element of the current message. This technique plays back messages at the speed at which they were recorded. If the message is to be processed immediately for much faster playback, the amount of time returned from the function is zero.
The time at which the message should be processed is usually obtained by adding the amount of time Windows should wait before processing the message to the current system time obtained from GetTickCount. For immediate playback, use the value returned from GetTickCount.
If the system is not otherwise active, Windows uses the values that the filter function has supplied to process the event. If the system is active, Windows examines the system queue. Each time it does, it asks for the same event with an HC_GETNEXT hook code. Each time the filter function receives HC_GETNEXT, it should return the new amount of time to wait, assuming that time elapsed between calls. The time element of the EVENTMSG structure and of the message, the paramH value, and the paramL value will probably not need changing between calls.
HC_SKIP
Windows calls the WH_JOURNALPLAYBACK hook with this hook code when it has completed processing a message it received from WH_JOURNALPLAYBACK. This occurs at the time that Windows would have removed the event from the system queue, if the event had been in the system queue instead of being generated by a WH_JOURNALPLAYBACK hook. This hook code signals to the filter function that the event that the filter function returned on the prior HC_GETNEXT call has been returned to an application. The filter function should prepare to return the next event on the next HC_GETEVENT call. When the filter function determines that it has no more events to play back, it should unhook itself during this HC_SKIP call.
Windows calls this hook when the GetMessage or the PeekMessage function is about to return a WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, WM_SYSKEYDOWN, or WM_CHAR message. In the case of thread-specific hooks, the message must be from the thread's input queue. The filter function receives the virtual-key code and the state of the keyboard at the time of the keyboard hook. Filters can tell Windows to discard the message. A filter function attached to this hook needs to be aware of the following two hook codes:
Windows calls the WH_KEYBOARD hook with this hook code when an event is being removed from the system queue.
Windows calls the WH_KEYBOARD hook with this hook code when there is a keyboard event that is not being removed because an application is calling PeekMessage with the PM_NOREMOVE option. If this hook code is passed, the key-state table will not accurately reflect the previous key state. An application needs to be aware of the existence of this condition.
Windows calls this hook when a GetMessage or a PeekMessage function is called and Windows has a mouse message to process. Like the WH_KEYBOARD hook, this filter function receives a hook code, which indicates whether the message is being removed (HC_NOREMOVE), an identifier specifying the mouse message, and the x and y coordinates of the mouse. Filters can tell Windows to discard the message. Filters for this hook must reside in a DLL.
Windows calls this hook when a dialog box, a message box, a scroll bar, or a menu retrieves a message, or when the user presses the ALT+TAB or ALT+ESC keys while the application that set the hook is active. This hook is thread specific, so it is always safe for its filter functions to reside in an application or in a DLL. The filter receives the following hook codes:
There are other MSGF_ values defined in WINUSER.H but they are not used in WH_MSGFILTER hooks at this time.
The lParam parameter contains a pointer to a structure containing the message. The WH_SYSMSGFILTER hooks are called before the WH_MSGFILTER hooks. If any of the WH_SYSMSGFILTER hook functions return TRUE, the WH_MSGFILTER hooks are not called.
Windows calls this hook when actions occur to top-level (that is, unowned) windows. In the case of thread-specific hooks, Windows calls this hook only for windows that belong to the thread. This is a notification-only hook, so the filter function cannot modify or discard the event. The wParam parameter contains the handle to the window; the lParam parameter is not used. Three hook codes are defined in WINUSER.H for this hook:
This hook is identical to WH_MSGFILTER except that it is a systemwide hook. Windows calls this hook when a dialog box, a message box, a scroll bar, or a menu retrieves a message, or when the user presses the ALT+TAB or ALT+ESC keys. The filter receives the same hook code as WH_MSGFILTER.
The lParam parameter contains a pointer to a structure containing the message. The WH_SYSMSGFILTER hooks are called before the WH_MSGFILTER hooks. If any of the WH_SYSMSGFILTER hook functions return TRUE, the WH_MSGFILTER hooks are not called.