Using Hooks - Win32 Apps - Microsoft Learn
Using Hooks - Win32 Apps - Microsoft Learn
Using Hooks
Windows and Messages
T Windows Training
T Window Classes Article • 01/07/2021 • 6 contributors Feedback
Learning path
T Window Procedures Use advance techniques in canvas apps
to perform custom updates and
T Messages and Message Queues In this article
optimization - Training
T Timers Installing and Releasing Hook Procedures Use advance techniques in canvas apps
T Window Properties to perform custom updates and
Monitoring System Events
optimization
T Configuration
Hooks
The following code examples demonstrate how to perform the following
T
Procedures
(winuser.h) - Win32 apps
Installs an application-defined hook
procedure into a hook chain. (ANSI)
Download PDF
You can install a hook procedure by calling the SetWindowsHookEx function
and specifying the type of hook calling the procedure, whether the CallNextHookEx function (winuser.h) -
Win32 apps
procedure should be associated with all threads in the same desktop as the
Passes the hook information to the next
calling thread or with a particular thread, and a pointer to the procedure
hook procedure in the current hook
entry point. chain. A hook procedure can call this…
You must place a global hook procedure in a DLL separate from the Show 5 more
application installing the hook procedure. The installing application must
have the handle to the DLL module before it can install the hook procedure.
To retrieve a handle to the DLL module, call the LoadLibrary function with
the name of the DLL. After you have obtained the handle, you can call the
GetProcAddress function to retrieve a pointer to the hook procedure. Finally,
use SetWindowsHookEx to install the hook procedure address in the
appropriate hook chain. SetWindowsHookEx passes the module handle, a
pointer to the hook-procedure entry point, and 0 for the thread identifier,
indicating that the hook procedure should be associated with all threads in
the same desktop as the calling thread. This sequence is shown in the
following example.
C++ = Copy
HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL;
static HHOOK hhookSysMsg;
hinstDLL = LoadLibrary(TEXT("c:\\myapp\\sysmsg.dll"));
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "SysMessageProc");
hhookSysMsg = SetWindowsHookEx(
WH_SYSMSGFILTER,
hkprcSysMsg,
hinstDLL,
0);
You can release a thread-specific hook procedure (remove its address from
the hook chain) by calling the UnhookWindowsHookEx function, specifying
the handle to the hook procedure to release. Release a hook procedure as
soon as your application no longer needs it.
WH_CALLWNDPROC
WH_CBT
WH_DEBUG
WH_GETMESSAGE
WH_KEYBOARD
WH_MOUSE
WH_MSGFILTER
The user can install and remove a hook procedure by using the menu. When
a hook procedure is installed and an event that is monitored by the
procedure occurs, the procedure writes information about the event to the
client area of the application's main window.
C++ = Copy
#include <windows.h>
#include <strsafe.h>
#include "app.h"
#define NUMHOOKS 7
// Global variables
MYHOOKDATA myhookdata[NUMHOOKS];
HWND gh_hwndMain;
// Hook procedures
gh_hwndMain = hwndMain;
switch (uMsg)
{
case WM_CREATE:
hmenu = GetMenu(hwndMain);
myhookdata[IDM_CALLWNDPROC].nType = WH_CALLWNDPROC;
myhookdata[IDM_CALLWNDPROC].hkprc = CallWndProc;
myhookdata[IDM_CBT].nType = WH_CBT;
myhookdata[IDM_CBT].hkprc = CBTProc;
myhookdata[IDM_DEBUG].nType = WH_DEBUG;
myhookdata[IDM_DEBUG].hkprc = DebugProc;
myhookdata[IDM_GETMESSAGE].nType = WH_GETMESSAGE;
myhookdata[IDM_GETMESSAGE].hkprc = GetMsgProc;
myhookdata[IDM_KEYBOARD].nType = WH_KEYBOARD;
myhookdata[IDM_KEYBOARD].hkprc = KeyboardProc;
myhookdata[IDM_MOUSE].nType = WH_MOUSE;
myhookdata[IDM_MOUSE].hkprc = MouseProc;
myhookdata[IDM_MSGFILTER].nType = WH_MSGFILTER;
myhookdata[IDM_MSGFILTER].hkprc = MessageProc;
return 0;
case WM_COMMAND:
switch (LOWORD(wParam))
{
// The user selected a hook command from the menu.
case IDM_CALLWNDPROC:
case IDM_CBT:
case IDM_DEBUG:
case IDM_GETMESSAGE:
case IDM_KEYBOARD:
case IDM_MOUSE:
case IDM_MSGFILTER:
index = LOWORD(wParam);
if (!afHooks[index])
{
myhookdata[index].hhook = SetWindowsHookEx(
myhookdata[index].nType,
myhookdata[index].hkprc,
(HINSTANCE) NULL, GetCurrentThreadId());
CheckMenuItem(hmenu, index,
MF_BYCOMMAND | MF_CHECKED);
afHooks[index] = TRUE;
}
else
{
UnhookWindowsHookEx(myhookdata[index].hhook);
CheckMenuItem(hmenu, index,
MF_BYCOMMAND | MF_UNCHECKED);
afHooks[index] = FALSE;
}
default:
return (DefWindowProc(hwndMain, uMsg, wParam,
lParam));
}
break;
//
// Process other messages.
//
default:
return DefWindowProc(hwndMain, uMsg, wParam, lParam);
}
return NULL;
}
/****************************************************************
WH_CALLWNDPROC hook procedure
****************************************************************/
hdc = GetDC(gh_hwndMain);
switch (nCode)
{
case HC_ACTION:
hResult = StringCchPrintf(szCWPBuf, 256/sizeof(TCHAR),
"CALLWNDPROC - tsk: %ld, msg: %s, %d times ",
wParam, szMsg, c++);
if (FAILED(hResult))
{
// TODO: writer error handler
}
hResult = StringCchLength(szCWPBuf, 256/sizeof(TCHAR), &c
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 15, szCWPBuf, cch);
break;
default:
break;
}
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_GETMESSAGE hook procedure
****************************************************************/
switch (nCode)
{
case HC_ACTION:
switch (wParam)
{
case PM_REMOVE:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR),
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case PM_NOREMOVE:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR),
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
default:
hResult = StringCchCopy(szRem, 16/sizeof(TCHAR),
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
}
hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szMSGBuf, 256/sizeof(TCHAR),
"GETMESSAGE - wParam: %s, msg: %s, %d times ",
szRem, szMsg, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szMSGBuf, 256/sizeof(TCHAR), &c
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 35, szMSGBuf, cch);
break;
default:
break;
}
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_DEBUG hook procedure
****************************************************************/
hdc = GetDC(gh_hwndMain);
switch (nCode)
{
case HC_ACTION:
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"DEBUG - nCode: %d, tsk: %ld, %d times ",
nCode,wParam, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch)
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 55, szBuf, cch);
break;
default:
break;
}
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_CBT hook procedure
****************************************************************/
hdc = GetDC(gh_hwndMain);
switch (nCode)
{
case HCBT_ACTIVATE:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_CLICKSKIPPED:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_CREATEWND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_DESTROYWND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_KEYSKIPPED:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_MINMAX:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_MOVESIZE:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_QS:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_SETFOCUS:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case HCBT_SYSCOMMAND:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "HCBT_
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
default:
hResult = StringCchCopy(szCode, 128/sizeof(TCHAR), "Unkno
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
}
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "CBT - nCode
szCode, wParam, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 75, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_MOUSE hook procedure
****************************************************************/
hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"MOUSE - nCode: %d, msg: %s, x: %d, y: %d, %d times ",
nCode, szMsg, LOWORD(lParam), HIWORD(lParam), c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 95, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_KEYBOARD hook procedure
****************************************************************/
hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR), "KEYBOARD - n
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 115, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc);
/****************************************************************
WH_MSGFILTER hook procedure
****************************************************************/
switch (nCode)
{
case MSGF_DIALOGBOX:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_D
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case MSGF_MENU:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_M
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
case MSGF_SCROLLBAR:
hResult = StringCchCopy(szCode, 32/sizeof(TCHAR), "MSGF_S
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
default:
hResult = StringCchPrintf(szCode, 128/sizeof(TCHAR), "Unk
if (FAILED(hResult))
{
// TODO: write error handler
}
break;
}
hdc = GetDC(gh_hwndMain);
hResult = StringCchPrintf(szBuf, 128/sizeof(TCHAR),
"MSGFILTER nCode: %s, msg: %s, %d times ",
szCode, szMsg, c++);
if (FAILED(hResult))
{
// TODO: write error handler
}
hResult = StringCchLength(szBuf, 128/sizeof(TCHAR), &cch);
if (FAILED(hResult))
{
// TODO: write error handler
}
TextOut(hdc, 2, 135, szBuf, cch);
ReleaseDC(gh_hwndMain, hdc);
Feedback
Was this page helpful? Yes No
Manage cookies Previous Versions Blog Contribute Privacy Terms of Use Trademarks © Microsoft 2025