純C#鉤子實現及應用(轉)

weixin_33858249發表於2017-11-15

純C#鉤子(Hook)實現

要實現系統鉤子其實很簡單,呼叫三個Win32的API即可。
SetWindowsHookEx 用於設定鉤子。(設立一道卡子,盤查需要的資訊)
        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
        public static extern IntPtr SetWindowsHookEx ( WH_Codes idHook, HookProc lpfn,
            IntPtr pInstance, int threadId );

CallNextHookEx 用於傳遞鉤子(訊息是重要的,所以從哪裡來,就應該回到哪裡去,除非你決定要封鎖訊息)

        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
        public static extern int CallNextHookEx ( IntPtr pHookHandle, int nCode,
            Int32 wParam, IntPtr lParam );

UnhookWindowsHookEx 解除安裝鉤子(解除安裝很重要,卡子設多了會造成擁堵)

        [DllImport( "user32.dll", CallingConvention = CallingConvention.StdCall )]
        public static extern bool UnhookWindowsHookEx ( IntPtr pHookHandle );

在《HOW TO:在 Visual C# .NET 中設定視窗掛鉤》一文中有如下描述:
在 .NET 框架中不支援全域性掛鉤
您無法在 Microsoft .NET 框架中實現全域性掛鉤。若要安裝全域性掛鉤,掛鉤必須有一個本機動態連結庫 (DLL) 匯出以便將其本身插入到另一個需要調入一個有效而且一致的函式的程式中。這需要一個 DLL 匯出,而 .NET 框架不支援這一點。託管程式碼沒有讓函式指標具有統一的值這一概念,因為這些函式是動態構建的代理。
網上查詢了很多程式碼,大都另外包含了一個C++的DLL,用於標識包含lpfn所指的子程的DLL,似乎也驗證了這一說法。

但實際上並非如此,使用如下程式碼即可實現全域性鉤子:
IntPtr pInstance = Marshal.GetHINSTANCE( Assembly.GetExecutingAssembly().ManifestModule );
Win32API.SetWindowsHookEx( WH_MOUSE_LL,m_MouseHookProcedure, pInstance, 0 );
注:ManifestModule屬性是.Net Framework 2.0中新增加的,所以當你依然使用.Net Framework 1.x的時候,可以使用GetModules方法獲取當前程式集的所有模組,然後用其中的一個作為GetHINSTAN方法的引數,來獲得合適的控制程式碼指標。 

鉤子應用DEMO-螢幕放大器 

點選下載可執行檔案Shift + Esc 退出程式)
點選下載原始檔

所謂螢幕放大器,類似與WINDOWS系統中的輔助工具中的放大鏡。
前兩天在找資料的時候突然發現在2.0中,Graphics類多了一個CopyFromScreen方法,可以直接實現螢幕抓取,於是有了做螢幕放大器的想法。

首先我定義了是SKHOOK類,來擷取鍵盤及滑鼠。
由於需要獲得全域性的滑鼠訊息來確定截圖位置,同時要建立一個全域性的快捷鍵來退出程式,所以只能用上面說的鉤子來實現。

然後我通過滑鼠點來設定取樣區域,以及窗體的位置。
取樣區域為滑鼠點為中心的50*50的矩形區域。窗體位置只實現了簡單的滑鼠跟隨,同時保證了和取樣區域不重疊。

另外我使用了一個BackgroundWorker來定時重新整理更新窗體。主要是為了實現動畫內容(GIF、Flash等)的顯示。

至於移動的時候使用SetWindowPos,主要是為了保證窗體一直位於頂層,否則的話一些置頂的視窗(如QQ)等將覆蓋當前視窗。

已知問題:
1。不支援視訊擷取
2。部分ToolTip提示無法顯示
3。可能會造成背景視窗部分顯示失效。
4。SKHook類中,對於鍵盤事件處理,存在不足。

還有一個問題,就是當滑鼠移動比較快的時候,視窗邊框會有殘影,不知道是什麼原因。這個問題在以往的Fram窗體中一直是困擾我的問題,至今沒有找到解決的辦法。




本文轉自94cool部落格園部落格,原文連結:http://www.cnblogs.com/94cool/archive/2009/05/26/1489386.html,如需轉載請自行聯絡原作者

相關文章