热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#钩子内部消息拦截

钩子其实就是调用一下API而已:1、安装钩子:SetWindowsHookEx函数原形:HHOOKSetWindowsHookEx(int

钩子其实就是调用一下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       // 要卸载的钩子句柄。

                      )

 

把上面这些APIC#封装一下,就可以直接用了!

给个线程钩子的例子吧(两个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

{

    ....

}

 

 

钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。

 

关于Hook的详细介绍,在微软的MSDN中有,http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx

下面是我在C#中来应用Hook:

 

实现效果:

 

当用户在TextBox中输入 b 的时候,TextBox 始终显示 a

 

实现过程:

 

1、新建一个C#WindowsApplication

 

2、在Form1中,添加下面一些变量:  

 

        internal enum HookType //枚举,钩子的类型

 

        {

 

            //MsgFilter     = -1,

 

            //JournalRecord    = 0,

 

            //JournalPlayback  = 1,

 

            Keyboard         = 2,

 

            //GetMessage       = 3,

 

            //CallWndProc      = 4,

 

            //CBT              = 5,

 

            //SysMsgFilter     = 6,

 

            //Mouse            = 7,

 

            //Hardware         = 8,

 

            //Debug            = 9,

 

            //Shell           = 10,

 

            //ForegroundIdle  = 11,

 

            //CallWndProcRet  = 12,

 

            //KeyboardLL        = 13,

 

            //MouseLL           = 14,

 

        };

 

        IntPtr _nextHookPtr; //记录Hook编号

 

 

3、在Form1中引入必须的API  

 

        [DllImport("kernel32.dll")]

        static extern int GetCurrentThreadId(); //取得当前线程编号的API

 

        [DllImport("User32.dll")]

 

        internal extern static void UnhookWindowsHookEx(IntPtr handle); //取消HookAPI

 

        [DllImport("User32.dll")]

 

        internal extern static IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr         hinstance, int threadID);  //设置HookAPI

 

        [DllImport("User32.dll")]

 

        internal extern static IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam); //取得下一个HookAPI

 

4、声明一个实现的委托

 

        internal delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);

 

5、添加自己的Hook处理过程 

 

        IntPtr MyHookProc(int code, IntPtr wparam, IntPtr lparam)

 

        {  

 

            if( code <0 ) return CallNextHookEx(_nextHookPtr,code, wparam, lparam); //返回&#xff0c;让后面的程序处理该消息           

 

             if( wparam.ToInt32() &#61;&#61; 98 || wparam.ToInt32() &#61;&#61; 66 ) //如果用户输入的是 b

 

            {

 

                this.textBox1.Text &#61; "a";

 

                 return   (IntPtr) 1; //直接返回了&#xff0c;该消息就处理结束了

 

            }

 

            else

 

            {

 

                return IntPtr.Zero; //返回&#xff0c;让后面的程序处理该消息

 

            }

 

        }

 

 6、添加加入Hook链和从Hook链中取消的函数

 

        public void SetHook()

 

        {

 

            if( _nextHookPtr !&#61; IntPtr.Zero ) //已经勾过了

 

              return;

 

            HookProc myhookProc &#61; new HookProc(MyHookProc); //声明一个自己的Hook实现函数的委托对象

 

            _nextHookPtr &#61; SetWindowsHookEx((int)HookType.Keyboard, myhookProc , IntPtr.Zero ,  GetCurrentThreadId()); //加到Hook链中

 

        }

 

        public void UnHook()

 

        {

 

            if( _nextHookPtr !&#61; IntPtr.Zero )

 

            {

 

                UnhookWindowsHookEx(_nextHookPtr); //Hook链中取消

 

                _nextHookPtr &#61; IntPtr.Zero;

 

            }

 

        }

 

 7、在Form1Load事件中添加 SetHook() &#xff0c; Form1closing 事件中添加 UnHook()

 

        private void Form1_Load(object sender, System.EventArgs e)

 

        {

 

            SetHook();

 

        }

 

        private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)

 

        {

 

            UnHook();

 

        }

 

 

 

8、运行

   

    输入 b , 发现 textbox 里面显示的是 a 了&#xff01;


推荐阅读
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Echarts图表重复加载、axis重复多次请求问题解决记录
    文章目录1.需求描述2.问题描述正常状态:问题状态:3.解决方法1.需求描述使用Echats实现了一个中国地图:通过选择查询周期&#x ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 网络请求模块选择——axios框架的基本使用和封装
    本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 本文介绍了lintcode(12)题目的要求和解题思路,以及给出了相应的代码实现。题目要求在给定的字符串source中找到包括所有目标字符串字母的最短子串,并且时间复杂度为O(n)。解题思路是使用滑动窗口的方法,通过维护一个unordered_map来记录目标字符串中每个字符的出现次数,并使用双指针来寻找最小子串。代码实现部分给出了具体的实现代码。 ... [详细]
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
author-avatar
全球不懂我_934
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有