SetWindowsHookExA 函数 (winuser.h)

将应用程序定义的挂钩过程安装到挂钩链中。 你将安装挂钩过程来监视系统的某些类型的事件。 这些事件与特定线程相关联,或者与调用线程位于同一桌面中的所有线程相关联。

语法

HHOOK SetWindowsHookExA(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId
);

参数

[in] idHook

类型:int

要安装的挂钩过程的类型。 此参数可以是下列值之一。

价值 意义
WH_CALLWNDPROC
4

安装一个挂钩过程,用于在系统将其发送到目标窗口过程之前监视消息。 有关详细信息,请参阅 CallWndProc 挂钩过程。

WH_CALLWNDPROCRET
12
安装一个挂钩过程,用于在目标窗口过程处理消息后监视消息。 有关详细信息,请参阅 [HOOKPROC 回调函数](nc-winuser-hookproc.md) 挂钩过程。
WH_CBT
5
安装一个挂钩过程,用于接收对 CBT 应用程序有用的通知。 有关详细信息,请参阅 [CBTProc](/windows/win32/winmsg/cbtproc) 挂钩过程。
WH_DEBUG
9

安装用于调试其他挂钩过程的挂钩过程。 有关详细信息,请参阅 DebugProc 挂钩过程。

WH_FOREGROUNDIDLE
11

安装将在应用程序前台线程即将处于空闲状态时调用的挂钩过程。 此挂钩可用于在空闲时间执行低优先级任务。 有关详细信息,请参阅 ForegroundIdleProc 挂钩过程。

WH_GETMESSAGE
3

安装一个挂钩过程,用于监视发布到消息队列的消息。 有关详细信息,请参阅 GetMsgProc 挂钩过程。

WH_JOURNALPLAYBACK
1

警告

Windows 11 及更新:不支持日记挂钩 API。 建议改用 SendInput TextInput API。

安装一个挂钩过程,该挂钩过程发布以前由 WH_JOURNALRECORD 挂钩过程记录的消息。 有关详细信息,请参阅 JournalPlaybackProc 挂钩过程。

WH_JOURNALRECORD
0

警告

Windows 11 及更新:不支持日记挂钩 API。 建议改用 SendInput TextInput API。

安装一个挂钩过程,用于记录发布到系统消息队列的输入消息。 此挂钩可用于录制宏。 有关详细信息,请参阅 JournalRecordProc 挂钩过程。

WH_KEYBOARD
2

安装监视击键消息的挂钩过程。 有关详细信息,请参阅 KeyboardProc 挂钩过程。

WH_KEYBOARD_LL
13
安装用于监视低级别键盘输入事件的挂钩过程。 有关详细信息,请参阅 LowLevelKeyboardProc 挂钩过程。
WH_MOUSE
7

安装监视鼠标消息的挂钩过程。 有关详细信息,请参阅 MouseProc 挂钩过程。

WH_MOUSE_LL
14

安装一个挂钩过程,用于监视低级别鼠标输入事件。 有关详细信息,请参阅 LowLevelMouseProc 挂钩过程。

WH_MSGFILTER
-1

安装一个挂钩过程,用于监视对话框、消息框、菜单或滚动条中输入事件生成的消息。 有关详细信息,请参阅 MessageProc 挂钩过程。

WH_SHELL
10
安装一个挂钩过程,用于接收对 shell 应用程序有用的通知。 有关详细信息,请参阅 [ShellProc](/windows/win32/winmsg/shellproc) 挂钩过程。
WH_SYSMSGFILTER
6

安装一个挂钩过程,用于监视对话框、消息框、菜单或滚动条中输入事件生成的消息。 挂钩过程监视与调用线程位于同一桌面中的所有应用程序的消息。 有关详细信息,请参阅 SysMsgProc 挂钩过程。

[in] lpfn

类型:HOOKPROC

指向挂钩过程的指针。 如果 dwThreadId 参数为零或指定由其他进程创建的线程的标识符,则 lpfn 参数必须指向 DLL 中的挂钩过程。 否则,lpfn 可以指向与当前进程关联的代码中的挂钩过程。

[in] hmod

类型:HINSTANCE

DLL 的句柄,其中包含由 lpfn 参数指向的挂钩过程。 如果 dwThreadId 参数指定由当前进程创建的线程,并且挂钩过程位于与当前进程关联的代码中,则必须将 hMod 参数设置为 NULL

[in] dwThreadId

类型:DWORD

要与之关联的挂钩过程的线程的标识符。 对于桌面应用,如果此参数为零,则挂钩过程与调用线程在同一桌面上运行的所有现有线程相关联。 有关 Windows 应用商店应用,请参阅“备注”部分。

返回值

类型:HHOOK

如果函数成功,则返回值为挂钩过程的句柄。

如果函数失败,则返回值 NULL。 若要获取扩展的错误信息,请调用 GetLastError

言论

SetWindowsHookEx 可用于将 DLL 注入另一个进程。 不能将 32 位 DLL 注入 64 位进程,64 位 DLL 无法注入到 32 位进程中。 如果应用程序需要在其他进程中使用挂钩,则需要将 32 位应用程序调用 SetWindowsHookEx 将 32 位 DLL 注入 32 位进程,而 64 位应用程序调用 SetWindowsHookEx 将 64 位 DLL 注入 64 位进程。 32 位和 64 位 DLL 必须具有不同的名称。

由于挂钩在应用程序的上下文中运行,因此它们必须与应用程序的“位性”匹配。 如果 32 位应用程序在 64 位 Windows 上安装全局挂钩,则会将 32 位挂钩注入到每个 32 位进程(通常的安全边界适用)。 在 64 位进程中,线程仍标记为“挂钩”。但是,由于 32 位应用程序必须运行挂钩代码,因此系统会在挂钩应用的上下文中执行挂钩;具体而言,在调用 SetWindowsHookEx的线程上。 这意味着挂钩应用程序必须继续泵送消息,否则可能会阻止 64 位进程的正常运行。

如果 64 位应用程序在 64 位 Windows 上安装全局挂钩,则会将 64 位挂钩注入到每个 64 位进程中,而所有 32 位进程都使用挂钩应用程序的回调。

若要挂钩 64 位 Windows 安装桌面上的所有应用程序,请安装一个 32 位全局挂钩和一个 64 位全局挂钩,每个挂钩进程都来自相应的进程,并确保在挂钩应用程序中保持泵送消息以避免阻止正常运行。 如果已有 32 位全局挂钩应用程序,并且它不需要在每个应用程序的上下文中运行,则可能不需要创建 64 位版本。

如果 hMod 参数 NULLdwThreadId 参数为零或指定由另一个进程创建的线程的标识符,则可能会出现错误。

调用 CallNextHookEx 函数 函数链接到下一个挂钩过程是可选的,但强烈建议这样做:否则,安装了挂钩的其他应用程序不会收到挂钩通知,因此行为可能不正确。 应调用 CallNextHookEx,除非绝对需要阻止其他应用程序看到通知。

在终止之前,应用程序必须调用 UnhookWindowsHookEx 函数 函数来释放与挂钩关联的系统资源。

挂钩的范围取决于挂钩类型。 某些挂钩只能与全局范围一起设置;也可以仅为特定线程设置其他线程,如下表所示。

范围
WH_CALLWNDPROC 线程或全局
WH_CALLWNDPROCRET 线程或全局
WH_CBT 线程或全局
WH_DEBUG 线程或全局
WH_FOREGROUNDIDLE 线程或全局
WH_GETMESSAGE 线程或全局
WH_JOURNALPLAYBACK 仅限全局
WH_JOURNALRECORD 仅限全局
WH_KEYBOARD 线程或全局
WH_KEYBOARD_LL 仅限全局
WH_MOUSE 线程或全局
WH_MOUSE_LL 仅限全局
WH_MSGFILTER 线程或全局
WH_SHELL 线程或全局
WH_SYSMSGFILTER 仅限全局

对于指定的挂钩类型,首先调用线程挂钩,然后调用全局挂钩。 请注意,可以在安装挂钩的线程上调用WH_MOUSE、WH_KEYBOARD、WH_JOURNAL*、WH_SHELL和低级别挂钩,而不是线程处理挂钩。 对于这些挂钩,如果 32 位挂钩领先于挂钩链中的 64 位挂钩,则调用 32 位和 64 位挂钩。

全局挂钩是共享资源,安装一个挂钩会影响与调用线程相同的桌面中的所有应用程序。 所有全局挂钩函数都必须位于库中。 全局挂钩应限制为专用应用程序或在应用程序调试期间用作开发助手。 不再需要挂钩的库应删除其挂钩过程。

Windows 应用商店应用开发 如果 dwThreadId 为零,则 Windows 应用商店应用进程和 Windows 运行时代理进程不会在进程内加载窗口挂钩 DLL,除非它们由 UIAccess 进程(辅助功能工具)安装。 通知在安装程序的线程上传送这些挂钩:

  • WH_JOURNALPLAYBACK
  • WH_JOURNALRECORD
  • WH_KEYBOARD
  • WH_KEYBOARD_LL
  • WH_MOUSE
  • WH_MOUSE_LL
此行为类似于挂钩 DLL 与目标应用程序进程之间存在体系结构不匹配的情况,例如,挂钩 DLL 为 32 位,应用程序进程为 64 位。

例子

有关示例,请参阅 安装和释放挂钩过程

注意

winuser.h 标头将 SetWindowsHookEx 定义为一个别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将中性编码别名与不中性编码的代码混合使用可能会导致编译或运行时错误不匹配。 有关详细信息,请参阅函数原型的 约定。

要求

要求 价值
最低支持的客户端 Windows 2000 Professional [仅限桌面应用]
支持的最低服务器 Windows 2000 Server [仅限桌面应用]
目标平台 窗户
标头 winuser.h (包括 Windows.h)
User32.lib
DLL User32.dll
API 集 ext-ms-win-ntuser-window-l1-1-0(在 Windows 8 中引入)

另请参阅

CallNextHookEx 函数

CallWindowProc 函数

UnhookWindowsHookEx 函数

CBTProc

CallWndProc

CallWndRetProc

DebugProc

ForegroundIdleProc

GetMsgProc

JournalPlaybackProc

JournalRecordProc

KeyboardProc

LowLevelKeyboardProc

LowLevelMouseProc

MessageProc

MouseProc

ShellProc

SysMsgProc

概念

挂钩