c#钩子本线程内消息拦截的方法

发布时间:2020-11-08编辑:脚本学堂
C#钩子本线程内消息拦截的方法,供大家参考。说到c#的钩子,其实就是调用一下API而已。

C#钩子本线程内消息拦截的方法,供大家参考。
说到c#的钩子,其实就是调用一下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
{
    ....
}