鉤子其實就是調用一下API而已:
?
1、安裝鉤子:
SetWindowsHookEx
??? 函數原形:HHOOK SetWindowsHookEx(
?????????????????????? int?????? idHook,??? // 鉤子類型,
?????????????????????? HOOKPROC? lpfn,????? // 鉤子函數地址
?????????????????????? INSTANCE? hMod,????? // 鉤子所在的實例的句柄,
?????????????????????? DWORD???? dwThreadId // 鉤子所監視的線程的線程號
????????????????????? )
??? hMod: 對于線程序鉤子,參數傳NULL;
??? 對于系統鉤子:參數為鉤子DLL的句柄
dwThreadId:對于全局鉤子,該參數為NULL。
??? 鉤子類型用WH_CALLWNDPROC=4(發送到窗口的消息。由SendMessage觸發)
??? 返回:成功:返回SetWindowsHookEx返回所安裝的鉤子句柄;
????????? 失敗:NULL;
?
2、回調,你要截獲消息就在這里進行:
LRESULT WINAPI MyHookProc(
????????? int???? nCode ,???? // 指定是否需要處理該消息
????????? WPARAM? wParam,???? // 包含該消息的附加消息
????????? LPARAM? lParam????? // 包含該消息的附加消息
??????????????????????? )
?
3、調用下一個鉤子
LRESULT CallNextHookEx(
????????? HHOOK?? hhk,????? // 是您自己的鉤子函數的句柄。用該句柄可以遍歷鉤子鏈
????????? int???? nCode,??? // 把傳入的參數簡單傳給CallNextHookEx即可
????????? WPARAM? wParam,?? // 把傳入的參數簡單傳給CallNextHookEx即可
????????? LPARAM? lParam??? // 把傳入的參數簡單傳給CallNextHookEx即可
????????????????????? );
?
4、用完后記得卸載鉤子哦,要不然你的系統會變得奇慢無比!
BOOL UnhookWindowsHookEx(
???????? HHOOK????? hhk?????? // 要卸載的鉤子句柄。
????????????????????? )
?
把上面這些API用C#封裝一下,就可以直接用了!
給個線程鉤子的例子吧(兩個Form都在同一個線程中運行):
?
using System.Runtime.InteropServices;
?
public class Form1 : System.Windows.Forms.Form
{
??? ...
??? //定義委托(鉤子函數,用于回調)
??? public delegate int HookProc(int code, IntPtr wparam, ref CWPSTRUCT cwp);
?
??? //安裝鉤子的函數
??? [DllImport("User32.dll",CharSet = CharSet.Auto)]
??? public static extern IntPtr SetWindowsHookEx(int type, HookProc hook, IntPtr instance, int threadID);
??? //調用下一個鉤子的函數
??? [DllImport("User32.dll",CharSet = CharSet.Auto)]
??? public static extern int CallNextHookEx(IntPtr hookHandle, int code, IntPtr wparam, ref CWPSTRUCT cwp);
??? //卸載鉤子
??? [DllImport("User32.dll",CharSet = CharSet.Auto)]
??? public static extern bool UnhookWindowsHookEx(IntPtr hookHandle);
??? //獲取窗體線程ID
??? DllImport("User32.dll",CharSet = CharSet.Auto)]
??? public static extern int GetWindowThreadProcessId(IntPtr hwnd, int ID);
?
??? private HookProc hookProc;
??? private IntPtr hookHandle = IntPtr.Zero;
?
??? public Form1()
??? {
??????? ....
??????? //掛接鉤子處理方法
??????? this.hookProc = new HookProc(myhookproc);
??? }
?
??? //開始攔截
private bool StartHook()
??? {
??????? Form2 f=new Form2();
??????? f.Show();//加上這個
??????? //安裝鉤子,攔截系統向Form2發出的消息
??????? this.hookHandle = SetWindowsHookEx(4, hookProc, IntPtr.Zero ,GetWindowThreadProcessId(f.Handle,0));
??????? return (this.hookHandle != 0);
??? }
?
??? //停止攔截
??? private bool StopHook()
??? {
??????? return UnhookWindowsHookEx(this.hookHandle);
??? }
?
??? //鉤子處理函數,在這里攔截消息并做處理
??? private int myhookproc(int code, IntPtr wparam, ref CWPSTRUCT cwp)
??? {
??????? switch(code)
??????? {
??? case 0:
??? switch(cwp.message)
??? {
??????? case 0x0000F://WM_PAINT,攔截WM_PAINT消息
??????????????? //do something
??????? break;
??? }
??????????? break;
??????? }
??????? return CallNextHookEx(hookHandle,code,wparam, ref cwp);
??? }
???
??? [StructLayout(LayoutKind.Sequential)]
??? public struct CWPSTRUCT
??? {
?public IntPtr lparam;
?public IntPtr wparam;
?public int message;
?public IntPtr hwnd;
??? }
}
?
public class Form2 : System.Windows.Forms.Form
{
??? ....
}