MFC線程鈎子和全局鈎子[HOOK DLL]



第一部分:API函數簡介

1.       SetWindowsHookEx函數

函數原型

HHOOK SetWindowsHookEx(

  int idHook,        // hook type

  HOOKPROC lpfn,     // hook procedure

  HINSTANCE hMod,    // handle to application instance

  DWORD dwThreadId   // thread identifier

);

函數功能:該函數將一個應用程序定義的掛鈎處理過程安裝到掛鈎鏈中去,您可以通過安裝掛鈎處理過程來對系統的某些類型事件進行監控,這些事件與某個特定的線程或系統中的所有事件相關.具體參數詳見MSDN;

舉例:

線程鈎子:

HHOOK g_hMouse;//全局變量,保存鈎子的句柄

LRESULT CALLBACK MouseProc(

  int nCode,      // hook code

  WPARAM wParam,  // message identifier

  LPARAM lParam   // mouse coordinates

)

{

  //……

}

g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());

2.       CallNextHookEx函數

函數原型:

LRESULT CallNextHookEx(

  HHOOK hhk,      // handle to current hook

  int nCode,      // hook code passed to hook procedure

  WPARAM wParam,  // value passed to hook procedure

  LPARAM lParam   // value passed to hook procedure

);

函數功能:調用下一個鈎子

3.       UnhookWindowsHookEx

函數原型:

BOOL UnhookWindowsHookEx(

  HHOOK hhk   // handle to hook procedure

);

第二部分:HOOKDLL

1.線程鈎子的創建過程:

 1. 聲明一個全局的HHOOK類型的變量,用於保存創建鈎子的句柄,如:

HHOOK g_hMouse;//全局變量,保存鈎子的句柄

 2. 在應用程序的初始化函數中,安裝鈎子;注意SetWindowsHookEx的參數!

g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());

3.       編寫處理鈎子消息的回調函數:

LRESULT CALLBACK MouseProc(

  int nCode,      // hook code

  WPARAM wParam,  // message identifier

  LPARAM lParam   // mouse coordinates

)

{

    //編寫需要處理的部分

         return 1;

//不需要處理的部分,調用

return CallNextHookEx(g_hMouse, nCode, wParam, lParam);

}

4.       卸載鈎子函數

UnhookWindowsHookEx(g_hMouse);

2.系統鈎子的創建過程:

運行機制:DLL函數中的代碼所創建的任何對象(包括變量)都歸調用它的線程或進程所有。當進程在載入DLL時,操作系統自動把DLL地址映射到該進程的私有空間,也就是進程的虛擬地址空間,而且也復制該DLL的全局數據的一份拷貝到該進程空間。也就是說每個進程所擁有的相同的DLL的全局數據,它們的名稱相同,但其值卻並不一定是相同的,而且是互不干涉的。因此,在Win32環境下要想在多個進程中共享數據,就必須進行必要的設置。在訪問同一個Dll的各進程之間共享存儲器是通過存儲器映射文件技術實現的。也可以把這些需要共享的數據分離出來,放置在一個獨立的數據段里,並把該段的屬性設置為共享。必須給這些變量賦初值,否則編譯器會把沒有賦初始值的變量放在一個叫未被初始化的數據段中。#pragma data_seg預處理指令用於設置共享數據段。例如:

#pragma data_seg("SharedDataName")

HHOOK hHook=NULL;

#pragma data_seg()

#pragma data_seg("SharedDataName")#pragma data_seg()之間的所有變量將被訪問該Dll的所有進程看到和共享。再加上一條指令

#pragma comment(linker,"/section:.SharedDataName,rws")

那么這個數據節中的數據可以在所有DLL的實例之間共享。所有對這些數據的操作都針對同一個實例的,而不是在每個進程的地址空間中都有一份。

 

系統鈎子的創建需要將鈎子的放在DLL中,因此其重建構成需要兩部分:1.編寫程序,生成Dll2.編寫應用程序調用Dll中的函數

2.1 DLL中的代碼的編寫

方案 1:源代碼:http://download.csdn.net/detail/nuptboyzhb/4202102

1.       新建一個擴展MFC類型DLL工程;

2.       DLL的句柄參數和要安裝鈎子的句柄聲明為共享數據:

#pragma data_seg("Titlename") //名稱任意起

        HHOOK glhHook=NULL; //安裝的鼠標鈎子句柄

        HINSTANCE glhInstance=NULL;//DLL實例句柄

#pragma data_seg()

注意:共享數據必須初始化,否則微軟編譯器會把沒有初始化的數據放到.BSS段中,從而導致多個進程之間的共享行為失敗。

3.       新建一個CMouseHook的導出類,用於實現鈎子的安裝和卸載

class AFX_EXT_CLASS CMouseHook:public CObject //AFX_EXT_CLASS宏聲明類為導出類

{

public:

       CMouseHook();//鈎子類的構造函數

       ~CMouseHook();//鈎子類的析構函數

       BOOL StartHook(HWND hWnd);//安裝鈎子函數

       BOOL StopHook();//卸載鈎子函數

};

注意:AFX_EXT_CLASS用於聲明該類為導出類;

4.       編寫安裝鈎子,卸載鈎子,鈎子過程的函數

安裝鈎子:glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);

卸載鈎子:UnhookWindowsHookEx(glhHook);

鈎子過程:

//鼠標鈎子函數的實現

LRESULT CALLBACK MouseProc(int nCode,WPARAM wparam,LPARAM lparam)

{

    LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;

    if (nCode>=0)

    {

             //處理過程的代碼…..

    }

    return CallNextHookEx(glhHook,nCode,wparam,lparam); //繼續傳遞消息

}

2.2 主程序的調用

新建一個應用程序,將上述生成的.dll文件和.lib文件及類聲明的文件.h拷貝到當前目錄中,並在頭文件中包含生成的類聲明.h文件;靜態方式加載動態鏈接庫

#pragma comment(lib,"MousehookDll.lib")   //隱式鏈接DLL

然后就可以聲明一個由DLL文件導出的類CMouseHook的一個變量;然后在應用程序的初始化函數中調用該變量的StartHook函數安裝鈎子;在需要取消鈎子的地方,調用StopHook()函數;

附錄:鈎子過程函數參數詳解

從上面的步驟中可以看到,鈎子的安裝和卸載是一個較為固定格式和步驟;真正關鍵的是:不同的鈎子類型,回調函數的參數意義不同,那我們就一一介紹各個參數的意義吧!

a.       MouseProc(int nCode,WPARAM wparam,LPARAM lparam)WH_MOUSE

1.nCode 跟所有其他鈎子處理函數一樣,只要記得當 nCode小於0時:調用CallNextHookEx()就可以了。

HC_ACTION nCode等於HC_ACTION,wParamlParam 包含鼠標信息   HC_NOREMOVE nCode等於HC_NOREMOVE,wParamlParam 包含鼠標信息,並且鼠標消息沒有從消息隊列里移除

2. wParam 指定鼠標消息ID

3. lParam 一個MOUSEHOOKSTRUCT 結構的指針

  typedef struct tagMOUSEHOOKSTRUCT {

    POINT     pt; //保存鼠標在屏幕上的x,y坐標

    HWND      hwnd; //接收到鼠標消息的窗口的句柄

    UINT      wHitTestCode; //詳細描述參見WM_NCHITTEST消息

    ULONG_PTR dwExtraInfo; //指定與本消息聯系的額外消息

} MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;

 

b.      KeyboardProc(int nCode,WPARAM wparam,LPARAM lparam) WH_KEYBOARD

2.wParam:按鍵的虛擬鍵值消息,例如:VK_F1 VK_F2 等;

3. lParam:32位內存,內容描述包括:指定擴展鍵值,掃描碼,上下文,重復次數。

0-15位:描述:按下鍵盤次數。

16-23:指定掃描碼. 依賴於OEM

24:24位為1時候:表示按鍵是擴展鍵;24位為0時候:表示按鍵是數字鍵盤按鍵

25-28:保留位

29:上下文鍵:為1時: ALT按下,其他情況為0

30:如果是按鍵按下后發送的消息,30位為0,如果是按鍵抬起后30位為1

31:指定轉變狀態;31位為0時候,按鍵正在被按下,為1時候,按鍵正在被釋放

c.       GetMsgProc(int nCode,WPARAM wparam,LPARAM lparam) WH_GETMESSAGE

 2.wParam:標明消息是否從消息對列中取出,它有如下兩個值:

           PM_NOREMOVE未從消息隊列中取出

           PM_REMOVE:已經從消息隊列中取出

3. lParam: 它是指向MSG結構體的一個指針

typedef struct tagMSG {

  HWND   hwnd; //接收消息的窗口句柄

  UINT   message; //消息的標識,如WM_CLOSE

  WPARAM wParam;// 指定消息的附加信息

  LPARAM lParam; // 不同的消息不一樣;

  DWORD  time; //消息投遞到消息隊列中的時間

  POINT  pt; //消息投遞到消息隊列中時的鼠標位置(屏幕坐標)

} MSG, *PMSG;

d.      未完待續


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM