|
看了很多資料,都提到系統(tǒng)鉤子(Hook)必須是一個dll,這樣Windows才能在所有進程中共享鉤子代碼。 與鉤子相關(guān)的3個Windows API函數(shù)是: SetWindowsHookEx、UnhookWindowsHookEx、CallNextHookEx,它們的簡要說明如下: HHOOK SetWindowsHookEx( int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId); idHook -- 系統(tǒng)鉤子類型,實際上是一個int值,具體的定義請看MSDN lpfn -- 鉤子回調(diào)函數(shù)指針,當(dāng)收到鉤子消息時就執(zhí)行這個回調(diào)函數(shù),回調(diào)函數(shù)有3個參數(shù),不同類型的鉤子這3個參數(shù)有不同的含義,具體請看MSDN。 hMod -- DLL實例句柄(我猜是這樣,我不熟悉Win32API編程),當(dāng)鉤子為系統(tǒng)鉤子時這個參數(shù)是必須的,如果是單個程序或者線程使用的鉤子那么可以不用這個值。 dwThreadId -- 線程ID,如果是單個程序或者線程使用的鉤子這個參數(shù)是必須的。 SetWindowsHookEx返回所設(shè)置的鉤子的句柄。 BOOL UnhookWindowsHookEx(HHOOK hhk); hhk -- 所要注銷的鉤子的句柄 UnhookWindowsHookEx返回注銷鉤子是否成功。
LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam); hhk -- 起始鉤子句柄,如果是在鉤子回調(diào)函數(shù)中調(diào)用CallNextHookEx時傳的通常是本鉤子句柄。 nCode -- 鉤子回調(diào)函數(shù)參數(shù)1,具體含義視鉤子類型而定。 wParam -- 鉤子回調(diào)函數(shù)參數(shù)2,具體含義視鉤子類型而定。 lParam -- 鉤子回調(diào)函數(shù)參數(shù)3,具體含義視鉤子類型而定。 從以上3個函數(shù)的簡要說明可以看出所用到的參數(shù)幾乎都是簡單的參數(shù),稍微復(fù)雜就是回調(diào)函數(shù)(在C#中用delegate類型來實現(xiàn),后面會提到),但是最讓人頭疼的就是DLL的實例句柄,C#制作的DLL并不像C做的DLL有DllMain入口可以接受到DLL實例句柄。 我目前唯一的辦法就是使用C做一個系統(tǒng)鉤子DLL再讓C#調(diào)用。底下是DLL的代碼。 #define _WIN32_WINNT 0x0500 #include < Windows.h > #include < WinUser.h > ![]() #define Dll_Export __declspec(dllexport) /* DLL實例句柄 */ ![]() HINSTANCE instance = NULL; ![]() BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD ul_reason_for_call, LPVOID lpReserved) { instance = hInstance; return TRUE; } ![]() /* *功能:設(shè)置系統(tǒng)鉤子 *hookType -- 鉤子類型 *hookproc -- 鉤子回調(diào)函數(shù) */ ![]() Dll_Export HHOOK SetHook( int hookType,HOOKPROC hookproc) { return SetWindowsHookEx(hookType, hookproc, instance, NULL); } ![]() /* *功能:注銷鉤子 *hook -- 鉤子句柄 */ Dll_Export BOOL UnHook(HHOOK hook) { if (hook != NULL) return UnhookWindowsHookEx(hook); else return 0 ; } 然后在C#項目中創(chuàng)建一個系統(tǒng)鉤子類,提供創(chuàng)建鉤子和注銷鉤子的接口,代碼如下 public class Hook { [DllImport( " LowLevelHook.dll " )] public extern static IntPtr SetHook( int hookType, HookProc hookProc); ![]() [DllImport( " LowLevelHook.dll " )] public extern staticbool UnHook(IntPtr hook); } 上面用到的User32.HookProc類型不是.NET框架提供的,是自己定義的一個委托類型,聲明如下 public delegate int HookProc( int nCode, IntPtr wParam, IntPtr lParam); 現(xiàn)在你的C#程序就可以使用各種系統(tǒng)鉤子了,我們目前已經(jīng)使用的有低級別鼠標(biāo)鉤子和低級別鍵盤鉤子。 應(yīng)用低級別鼠標(biāo)鉤子時會遇到這樣一個問題: 低級別鼠標(biāo)鉤子的回調(diào)函數(shù)lParam是一個MSLLHOOKSTRUCT結(jié)構(gòu)體指針,C#中怎么獲取這個結(jié)構(gòu)體的實例呢?實現(xiàn)代碼如下 MSLLHOOKSTRUCT _mstr; unsafe { _mstr =* (User32.MSLLHOOKSTRUCT * )lParam.ToPointer(); } 通過聲明非安全代碼來獲取指針?biāo)笇ο蟆? MSLLHOOKSTRUCT結(jié)構(gòu)體的C#定義如下: [StructLayout(LayoutKind.Sequential)] public struct MSLLHOOKSTRUCT { public Point Point; public int MouseData; public int Flags; public int Time; public int ExtraInfo; } |
|
|