首先
我們使用DllImport屬性導入SetUserHookCallback函數
作為我們的抽象基鉤子類SystemHook的一個靜態的外部的方法
為此
我們必須映射一些外部數據類型
首先
我們必須創建一個代理作為我們的函數指針
這是通過定義上面的HookProcessHandler來實現的
我們需要一個函數
它的C++簽名為(int
WPARAM
LPARAM)
在Visual Studio
NET C++編譯器中
int與C#中是一樣的
也就是說
在C++與C#中int就是Int
事情並不總是這樣
一些編譯器把C++ int作為Int
對待
我們堅持使用Visual Studio
NET C++編譯器來實現這個工程
因此
我們不必擔心編譯器差別所帶來的另外的定義
接下來我們需要用C#傳遞WPARAM和LPARAM值這些確實是指針它們分別指向C++的UINT和LONG值用C#來說它們是指向uint和int的指針如果你還不確定什麼是WPARAM你可以通過在C++代碼中單擊右鍵來查詢它並且選擇Go to definition這將會引導你到在windefh中的定義
//從windefh:
typedef UINT_PTR WPARAM;
typedef LONG_PTR LPARAM;
因此我們選擇SystemUIntPtr和SystemIntPtr作為我們的變量類型它們分別相應於WPARAM和LPARAM類型當它們使用在C#中時
現在讓我們看一下鉤子基類是怎樣使用這些導入的方法來傳遞一個回叫函數(代理)到C++中它允許C++庫直接調用你的系統鉤子類的實例首先在構造器中SystemHook類創建一個到私有方法InternalHookCallback的代理它匹配HookProcessedHandler代理簽名然後它把這個代理和它的HookType傳遞到C++庫以使用SetUserHookCallback方法來注冊該回叫函數如上面所討論的下面是其代碼實現
public SystemHook(HookTypes type){
_type = type;
_processHandler = new HookProcessedHandler(InternalHookCallback);
SetUserHookCallback(_processHandler _type);
}
InternalHookCallback的實現相當簡單InternalHookCallback在用一個catchall try/catch塊包裝它的同時僅傳遞到抽象方法HookCallback的調用這將簡化在派生類中的實現並且保護C++代碼記住一旦一切都准備妥當這個C++鉤子就會直接調用這個方法
[MethodImpl(MethodImplOptionsNoInlining)]
private void InternalHookCallback(int code UIntPtr wparam IntPtr lparam){
try { HookCallback(code wparam lparam); }
catch {}
}
我們已增加了一個方法實現屬性它告訴編譯器不要內聯這個方法這不是可選的至少在我添加try/catch之前是需要的看起來由於某些原因編譯器在試圖內聯這個方法這將給包裝它的代理帶來各種麻煩然後C++層將回叫而該應用程序將會崩潰
現在讓我們看一下一個派生類是怎樣用一個特定的HookType來接收和處理鉤子事件下面是虛擬的MouseHook類的HookCallback方法實現
protected override void HookCallback(int code UIntPtr wparam IntPtr lparam){
if (MouseEvent == null) { return; }
int x = y = ;
MouseEvents mEvent = (MouseEvents)wparamToUInt();
switch(mEvent) {
case MouseEventsLeftButtonDown:
GetMousePosition(wparam lparam ref x ref y);
break;
//
}
MouseEvent(mEvent new Point(x y));
}
首先注意這個類定義一個事件MouseEvent該類在收到一個鉤子事件時激發這個事件這個類在激發它的事件之前把數據從WPARAM和LPARAM類型轉換成NET中有意義的鼠標事件數據這樣可以使得類的消費者免於擔心解釋這些數據結構這個類使用導入的GetMousePosition函數我們在C++ DLL中定義的用來轉換這些值為此請看下面幾段的討論
[] [] [] [] []
From:http://tw.wingwit.com/Article/program/net/201311/15483.html