在這個方法中我們檢查是否有人在聽這一個事件如果沒有不必繼續處理這一事件然後我們把WPARAM轉換成一個MouseEvents枚舉類型我們已小心地構造了MouseEvents枚舉來准確匹配它們在C++中相應的常數這允許我們簡單地把指針的值轉換成枚舉類型但是要注意這種轉換即使在WPARAM的值不匹配一個枚舉值的情況下也會成功mEvent的值將僅是未定義的(不是null只是不在枚舉值范圍之內)為此請詳細分析SystemEnumIsDefined方法
接下來在確定我們收到的事件類型後該類激活這個事件並且通知消費者鼠標事件的類型及在該事件過程中鼠標的位置
最後注意有關轉換WPARAM和LPARAM值對於每個類型的事件這些變量的值和意思是不同的因此在每一種鉤子類型中我們必須區別地解釋這些值我選擇用C++實現這種轉換而不是盡量用C#來模仿復雜的C++結構和指針例如前面的類就使用了一個叫作GetMousePosition的C++函數下面是C++ DLL中的這個方法
bool GetMousePosition(WPARAM wparam LPARAM lparam int & x int & y) {
MOUSEHOOKSTRUCT * pMouseStruct = (MOUSEHOOKSTRUCT *)lparam;
x = pMouseStruct>ptx;
y = pMouseStruct>pty;
return true;
}
不是盡量映射MOUSEHOOKSTRUCT結構指針到C#我們簡單地暫時把它回傳到C++層以提取我們需要的值注意因為我們需要從這個調用中返回一些值我們把我們的整數作為參考變量傳遞這直接映射到C#中的int*但是我們可以重載這個行為通過選擇正確的簽名來導入這個方法
private static extern bool InternalGetMousePosition(UIntPtr wparam
IntPtr lparam ref int x ref int y)
通過把integer參數定義為ref int我們得到通過C++參照傳遞給我們的值如果我們想要的話我們還可以使用out int
五限制
一些鉤子類型並不適合實現全局鉤子我當前正在考慮解決辦法它將允許使用受限制的鉤子類型到目前為止不要把這些類型添加回該庫中因為它們將導致應用程序的失敗(經常是系統范圍的災難性失敗)下一節將集中討論這些限制背後的原因和解決辦法
HookTypesCallWindowProcedure
HookTypesCallWindowProret
HookTypesComputerBasedTraining
HookTypesDebug
HookTypesForegroundIdle
HookTypesJournalRecord
HookTypesJournalPlayback
HookTypesGetMessage
HookTypesSystemMessageFilter
六兩種類型的鉤子
在本節中我將盡量解釋為什麼一些鉤子類型被限制在一定的范疇內而另外一些則不受限制如果我使用有點偏差術語的話請原諒我我還沒有找到任何有關這部分題目的文檔因此我編造了我自己的詞匯另外如果你認為我根本就不對請告訴我好了
當Windows調用傳遞到SetWindowsHookEx()的回調函數時它們會因不同類型的鉤子而被區別調用基本上有兩種情況切換執行上下文的鉤子和不切換執行上下文的鉤子用另一種方式說也就是在放鉤子的應用程序進程空間執行鉤子回調函數的情況和在被鉤住的應用程序進程空間執行鉤子回調函數的情況
鉤子類型例如鼠標和鍵盤鉤子都是在被Windows調用之前切換上下文的整個過程大致如下
應用程序X擁有焦點並執行
用戶按下一個鍵
Windows從應用程序X接管上下文並把執行上下文切換到放鉤子的應用程序
Windows用放鉤子的應用程序進程空間中的鍵消息參數調用鉤子回調函數
Windows從放鉤子的應用程序接管上下文並把執行上下文切換回應用程序X
Windows把消息放進應用程序X的消息排隊
稍微一會兒之後當應用程序X執行時它從自己的消息排隊中取出消息並且調用它的內部按鍵(或松開或按下)處理器
[] [] [] [] []
From:http://tw.wingwit.com/Article/program/net/201311/15482.html