要實現系統鉤子其實很簡單調用三個Win的API即可
SetWindowsHookEx 用於設置鉤子(設立一道卡子盤查需要的信息)
[DllImport( userdll CallingConvention = CallingConventionStdCall )]
public static extern IntPtr SetWindowsHookEx ( WH_Codes idHook HookProc lpfn
IntPtr pInstance int threadId );
CallNextHookEx 用於傳遞鉤子(消息是重要的所以從哪裡來就應該回到哪裡去除非你決定要封鎖消息)
[DllImport( userdll CallingConvention = CallingConventionStdCall )]
public static extern int CallNextHookEx ( IntPtr pHookHandle int nCode
Int wParam IntPtr lParam );
UnhookWindowsHookEx 卸載鉤子(卸載很重要卡子設多了會造成擁堵)
[DllImport( userdll CallingConvention = CallingConventionStdCall )]
public static extern bool UnhookWindowsHookEx ( IntPtr pHookHandle );
在《HOW TO在 Visual C# NET 中設置窗口掛鉤》一文中有如下描述 在 NET 框架中不支持全局掛鉤
您無法在 Microsoft NET 框架中實現全局掛鉤若要安裝全局掛鉤掛鉤必須有一個本機動態鏈接庫 (DLL) 導出以便將其本身插入到另一個需要調入一個有效而且一致的函數的進程中這需要一個 DLL 導出而 NET 框架不支持這一點托管代碼沒有讓函數指針具有統一的值這一概念因為這些函數是動態構建的代理網上查找了很多代碼大都另外包含了一個C++的DLL用於標識包含lpfn所指的子程的DLL似乎也驗證了這一說法
但實際上並非如此使用如下代碼即可實現全局鉤子
IntPtr pInstance = MarshalGetHINSTANCE( AssemblyGetExecutingAssembly()ManifestModule );
WinAPISetWindowsHookEx( WH_MOUSE_LLm_MouseHookProcedure pInstance );注ManifestModule屬性是Net Framework 中新增加的所以當你依然使用Net Framework x的時候可以使用GetModules方法獲取當前程序集的所有模塊然後用其中的一個作為GetHINSTAN方法的參數來獲得合適的句柄指針
鉤子應用DEMO-屏幕放大器
點擊下載可執行文件(Shift + Esc 退出程序)
點擊下載源文件
所謂屏幕放大器類似與WINDOWS系統中的輔助工具中的放大鏡
前兩天在找資料的時候突然發現在中Graphics類多了一個CopyFromScreen方法可以直接實現屏幕抓取於是有了做屏幕放大器的想法
首先我定義了是SKHOOK類來截取鍵盤及鼠標
由於需要獲得全局的鼠標消息來確定截屏位置同時要建立一個全局的快捷鍵來退出程序所以只能用上面說的鉤子來實現
然後我通過鼠標點來設置采樣區域以及窗體的位置
采樣區域為鼠標點為中心的*的矩形區域窗體位置只實現了簡單的鼠標跟隨同時保證了和采樣區域不重疊
另外我使用了一個BackgroundWorker來定時刷新更新窗體主要是為了實現動畫內容(GIFFlash等)的顯示
至於移動的時候使用SetWindowPos主要是為了保證窗體一直位於頂層否則的話一些置頂的窗口(如QQ)等將覆蓋當前窗口
已知問題
不支持視頻截取
部分ToolTip提示無法顯示
可能會造成背景窗口部分顯示失效
SKHook類中對於鍵盤事件處理存在不足
還有一個問題就是當鼠標移動比較快的時候窗口邊框會有殘影不知道是什麼原因這個問題在以往的Fram窗體中一直是困擾我的問題至今沒有找到解決的辦法
From:http://tw.wingwit.com/Article/program/net/201311/13719.html