setWinEventHook 函数 (winuser.h)
为一系列事件设置事件挂钩函数。
语法
HWINEVENTHOOK SetWinEventHook(
[in] DWORD eventMin,
[in] DWORD eventMax,
[in] HMODULE hmodWinEventProc,
[in] WINEVENTPROC pfnWinEventProc,
[in] DWORD idProcess,
[in] DWORD idThread,
[in] DWORD dwFlags
);
参数
[in] eventMin
类型: UINT
指定挂钩函数处理的事件范围中最低事件值的事件 常量 。 此参数可以设置为 EVENT_MIN ,以指示可能的最低事件值。
[in] eventMax
类型: UINT
指定由挂钩函数处理的事件范围中最高事件值的事件常量。 此参数可以设置为 EVENT_MAX ,以指示可能的最高事件值。
[in] hmodWinEventProc
类型: HMODULE
如果在 dwFlags 参数中指定了WINEVENT_INCONTEXT标志,则为包含 lpfnWinEventProc 中的挂钩函数的 DLL 的句柄。 如果挂钩函数不位于 DLL 中,或者指定了WINEVENT_OUTOFCONTEXT标志,则此参数为 NULL。
[in] pfnWinEventProc
类型: WINEVENTPROC
指向事件挂钩函数的指针。 有关此函数的详细信息,请参阅 WinEventProc。
[in] idProcess
类型: DWORD
指定挂钩函数从中接收事件的进程的 ID。 指定零 (0) 从当前桌面上的所有进程接收事件。
[in] idThread
类型: DWORD
指定挂钩函数从中接收事件的线程的 ID。 如果此参数为零,则挂钩函数与当前桌面上的所有现有线程相关联。
[in] dwFlags
类型: UINT
标记值,用于指定要跳过的挂钩函数和事件的位置。 以下标志有效:
值 | 含义 |
---|---|
|
包含回调函数的 DLL 映射到生成事件的进程的地址空间中。 使用此标志,系统会在事件通知发生时向回调函数发送事件通知。 指定此标志时,挂钩函数必须位于 DLL 中。 当调用进程和生成进程都不是 32 位或 64 位进程,或者生成进程是控制台应用程序时,此标志不起作用。 有关详细信息,请参阅 上下文中挂钩函数。 |
|
回调函数不会映射到生成事件的进程的地址空间中。 由于挂钩函数是跨进程边界调用的,因此系统必须对事件进行排队。 虽然此方法是异步的,但事件保证按顺序排列。 有关详细信息,请参阅 上下文外挂钩函数。 |
|
防止挂钩的此实例接收此进程中线程生成的事件。 此标志不会阻止线程生成事件。 |
|
防止此挂钩实例接收注册此挂钩的线程生成的事件。 |
以下标志组合有效:
- WINEVENT_INCONTEXT |WINEVENT_SKIPOWNPROCESS
- WINEVENT_INCONTEXT |WINEVENT_SKIPOWNTHREAD
- WINEVENT_OUTOFCONTEXT |WINEVENT_SKIPOWNPROCESS
- WINEVENT_OUTOFCONTEXT |WINEVENT_SKIPOWNTHREAD
有关 Windows 应用商店应用开发的信息,请参阅“备注”部分。
返回值
类型: HWINEVENTHOOK
如果成功,则返回一个 HWINEVENTHOOK 值,该值标识此事件挂钩实例。 应用程序保存此返回值,以便将其与 UnhookWinEvent 函数一起使用。
如果不成功,则返回零。
注解
此函数允许客户端指定他们感兴趣的进程和线程。
如果 idProcess 参数为非零且 idThread 为零,则挂钩函数将从该进程中的所有线程接收指定的事件。 如果 idProcess 参数为零且 idThread 为非零,则挂钩函数仅从 idThread 指定的线程接收指定的事件。 如果两者均为零,则挂钩函数将从所有线程和进程接收指定的事件。
如果客户端想要注册其他挂钩函数或侦听其他事件,则可以多次调用 SetWinEventHook 。
调用 SetWinEventHook 的客户端线程必须具有消息循环才能接收事件。
使用 SetWinEventHook 在托管代码中设置回调时,应使用 GCHandle 结构以避免异常。 这会告知垃圾回收器不要移动回调。
对于上下文外事件,事件在名为 SetWinEventHook 的同一线程上传递。 在某些情况下,即使请求WINEVENT_INCONTEXT事件,事件仍会根据上下文传递。 这些方案包括控制台窗口的事件,以及来自与调用方不同的位深度 (64 位与 32 位) 的进程的事件。
当挂钩函数处理事件时,可能会触发其他事件,这可能会导致挂钩函数在原始事件的处理完成之前重新进入。 挂钩函数中重入的问题在于,除非挂钩函数处理这种情况,否则事件会不按顺序完成。 有关详细信息,请参阅 防止重新进入。
Windows 应用商店应用开发如果 dwFlags WINEVENT_INCONTEXT AND (idProcess = 0 |idThread = 0) ,则 Windows 应用商店应用进程和Windows 运行时代理进程不会在进程内加载窗口挂钩 DLL,除非它们由 UIAccess 进程 (辅助功能工具) 安装。 通知在安装程序的线程上传递。
此行为类似于挂钩 DLL 与目标应用程序进程之间存在体系结构不匹配的情况,例如,当挂钩 DLL 为 32 位且应用程序进程为 64 位时发生的情况。
示例
以下示例代码演示客户端应用程序如何侦听菜单开始和菜单结束事件。 为简单起见,事件处理程序只向标准输出发送一些信息。
// Global variable.
HWINEVENTHOOK g_hook;
// Initializes COM and sets up the event hook.
//
void InitializeMSAA()
{
CoInitialize(NULL);
g_hook = SetWinEventHook(
EVENT_SYSTEM_MENUSTART, EVENT_SYSTEM_MENUEND, // Range of events (4 to 5).
NULL, // Handle to DLL.
HandleWinEvent, // The callback.
0, 0, // Process and thread IDs of interest (0 = all)
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}
// Unhooks the event and shuts down COM.
//
void ShutdownMSAA()
{
UnhookWinEvent(g_hook);
CoUninitialize();
}
// Callback function that handles events.
//
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
LONG idObject, LONG idChild,
DWORD dwEventThread, DWORD dwmsEventTime)
{
IAccessible* pAcc = NULL;
VARIANT varChild;
HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);
if ((hr == S_OK) && (pAcc != NULL))
{
BSTR bstrName;
pAcc->get_accName(varChild, &bstrName);
if (event == EVENT_SYSTEM_MENUSTART)
{
printf("Begin: ");
}
else if (event == EVENT_SYSTEM_MENUEND)
{
printf("End: ");
}
printf("%S\n", bstrName);
SysFreeString(bstrName);
pAcc->Release();
}
}
要求
要求 | 值 |
---|---|
最低受支持的客户端 | Windows 2000 Professional [仅限桌面应用] |
最低受支持的服务器 | Windows Server 2003 [仅限桌面应用] |
目标平台 | Windows |
标头 | winuser.h (包括 Windows.h) |
Library | User32.lib |
DLL | User32.dll |
可再发行组件 | 具有 SP6 及更高版本和 Windows 95 的 Windows NT 4.0 上的活动辅助功能 1.3 RDK |