相信訊息鉤子大家聽的比較多,訊息鉤子能夠在應用程式處理系統訊息之前將其截獲,提前處理並可以決定是否繼續將訊息往下傳送,有些windows事件並沒有訊息對應,譬如快顯功能表,切換視窗,獲得焦點,捲軸滾動等等,要截獲這些事件可以使用SetWinEventHook,它的原型如下:
HWINEVENTHOOK WINAPI SetWinEventHook(
__in UINT eventMin,
__in UINT eventMax,
__in HMODULE hmodWinEventProc,
__in WINEVENTPROC lpfnWinEventProc,
__in DWORD idProcess,
__in DWORD idThread,
__in UINT dwflags
);
詳細說明見MSDN:http://msdn.microsoft.com/en-us/library/dd373640(VS.85).aspx,其中第四個參數類似訊息鉤子一樣是一個回呼函數,說明見:http://msdn.microsoft.com/en-us/library/dd373885(VS.85).aspx。
SetWinEventHook的第1,2個參數可以標識一個範圍,表示截獲哪個範圍類的事件,因為實際上在win32裡面這些事件的ID都是直接用defined直接從小到大定義的,有兩個宏分別表示最小的事件ID和最大的事件ID(EVENT_MIN和EVENT_MAX),如果你分別傳這兩個參數給eventMin和eventMax則可以截獲所有的事件,具體可以截獲的事件可以去MSDN查詢:http://msdn.microsoft.com/en-us/library/dd318066(VS.85).aspx。
要停止HOOK,請調用UnhookWinEvent,原型為:
BOOL WINAPI UnhookWinEvent(
__in HWINEVENTHOOK hWinEventHook
);
觀察回呼函數的參數,可以使用API AccessibleObjectFromEvent來使用微軟的MS Active Accessibility 介面技術,獲得IAccessible 介面,可以使用一些比較有趣的功能,通過程式來訪問UI元素等等,不過我也是剛剛瞭解到這個Accessibility 介面技術,有空再看看具體情況。^_^
事件鉤子也有進程內和進程外事件鉤子,相比訊息鉤子不同的是你收到一個事件發生的訊息後,並不能控制攔截該事件不再傳遞事件。
代碼說明:
……</p><p>void CSetWinEventHookDlg::OnOK()<br />{<br />if (NULL == m_hHook)<br />{<br />m_hHook = ::SetWinEventHook(<br />EVENT_MIN,<br />EVENT_MAX,<br />NULL,<br />WinEventsProc, 0, 0,<br />WINEVENT_OUTOFCONTEXT);<br />}</p><p>}</p><p>void CSetWinEventHookDlg::OnCancel()<br />{<br />if (m_hHook)<br />{<br />::UnhookWinEvent(m_hHook);<br />m_hHook = NULL;<br />}<br />}</p><p>……</p><p>VOID CALLBACK WinEventsProc(HWINEVENTHOOK hWinEventHook, DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime )<br />{<br /> switch(dwEvent)<br /> {<br /> case EVENT_SYSTEM_SWITCHSTART:<br /> CSetWinEventHookDlg::ChangUI(_T("Alt+Tab Start"));<br /> break;</p><p> case EVENT_SYSTEM_SWITCHEND:<br /> CSetWinEventHookDlg::ChangUI(_T("Alt+Tab End"));<br /> break;</p><p> case EVENT_SYSTEM_MENUPOPUPSTART:<br /> CSetWinEventHookDlg::ChangUI(_T("PopMenu Start"));<br /> break;</p><p> case EVENT_SYSTEM_MENUPOPUPEND:<br /> CSetWinEventHookDlg::ChangUI(_T("PopMenu End"));<br /> break;<br /> }<br />}<br />