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
指定攔截函式接收事件的進程標識碼。 指定零 (0) ,以接收目前桌面上所有進程的事件。
[in] idThread
類型: DWORD
指定攔截函式接收事件之線程的標識碼。 如果此參數為零,攔截函式會與目前桌面上所有現有的線程相關聯。
[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 在 Managed 程式代碼中設定回呼時,您應該使用 GCHandle 結構來避免例外狀況。 這會告訴垃圾收集行程不要移動回呼。
針對內容不足的事件,事件會在呼叫 SetWinEventHook 的相同線程上傳遞。 在某些情況下,即使您要求WINEVENT_INCONTEXT事件,事件仍會從內容外傳遞。 這些案例包括來自控制台視窗的事件,以及來自具有不同位深度 (64 位與呼叫端) 32 位之進程的事件。
當攔截函式處理事件時,可能會觸發其他事件,這可能會導致攔截函式在原始事件的處理完成之前重新輸入。 攔截函式中重新進入的問題在於除非攔截函式處理這種情況,否則事件會依序完成。 如需詳細資訊,請參閱 防止重新進入。
Windows 市集應用程式開發如果 dwFlags WINEVENT_INCONTEXT AND (idProcess = 0 |idThread = 0) ,除非 UIAccess 進程 (輔助功能工具) ,否則不會針對 Windows 市集應用程式進程和 Windows 執行階段 訊息代理程式進程載入視窗勾點 DLL。 通知會在安裝程序的線程上傳遞。
此行為類似於當攔截 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) |
程式庫 | User32.lib |
Dll | User32.dll |
可轉散發套件 | sp6 和更新版本和 Windows 95 Windows NT 4.0 上的 Active Accessibility 1.3 RDK |