• windows 编程钩子技术初尝(hook)


    最近在研究hook这个东西,作为一个windows菜鸟,研究这个还真花了点时间,下面分享下今天按照别人代码写出的两个鼠标钩子实例。

    第一个是针对线程的钩子

    几点需要说明的地方:
      (1) 如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。
      (2) 对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
      (3) 钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。

    第一个程序,用一个文档显示当前鼠标的位置,我们知道鼠标的位置信息是,移动鼠标形成鼠标中断--OS发送中断调用驱动--驱动将鼠标的移动信息发给OS--OS进行计算处理得到当前坐标--OS将坐标发给图形界面系统

    那么我们的钩子就是在最后OS将坐标发给gwes.exe(也就是图形系统进程的时候),先截取消息,处理完后再发给gwes.exe。

    首先我们新建工程MFC  基于单文档的exe

    编写钩子程序的步骤分为三步:定义钩子函数安装钩子卸载钩子

    1.定义钩子

    LRESULT CALLBACK HookProc(int nCode ,WPARAM wParam,LPARAM lParam) ;

    我们先在钩子函数中实现自定义的功能,然后调用函数 CallNextHookEx.把钩子信息传递给钩子链的下一个钩子函数。

    LRESULT CallNextHookEx( HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam )

    参数 hhk是钩子句柄。nCode、wParam和lParam 是钩子函数。 
    当然也可以通过直接返回TRUE来丢弃该消息,就阻止了该消息的传递。

    2.安装钩子
    在程序初始化的时候,调用函数SetWindowsHookEx安装钩子。
    其函数原型为: 
    HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId ) 
          参数idHook表示钩子类型,它是和钩子函数类型一一对应的。比如,WH_KEYBOARD表示安装的是键盘钩子,WH_MOUSE表示是鼠标钩子等等。
      Lpfn是钩子函数的地址。
      HMod是钩子函数所在的实例的句柄。对于线程钩子,该参数为NULL;对于系统钩子,该参数为钩子函数所在的DLL句柄。
      dwThreadId 指定钩子所监视的线程的线程号。对于全局钩子,该参数为NULL。
      SetWindowsHookEx返回所安装的钩子句柄。
      
     3.卸载钩子

    当不再使用钩子时,必须及时卸载。简单地调用函数 BOOL UnhookWindowsHookEx( HHOOK hhk)即可。

    值得注意的是线程钩子和系统钩子的钩子函数的位置有很大的差别。线程钩子一般在当前线程或者当前线程派生的线程内,而系统钩子必须放在独立的动态链接库中,实现起来要麻烦一些。

    代码:

    HHOOK hHook;//鼠标钩子句柄
    CPoint point;//鼠标位置信息
    CChildView *pView;//实例化

    CChildView::CChildView()
    {
     pView=this;//获得输出窗口指针
     hHook=SetWindowsHookEx(WH_MOUSE,MouseProc,0,GetCurrentThreadId());

    }//在构造函数中创建一个钩子函数

    CChildView::~CChildView()
    {
     if(hHook)
     UnhookWindowsHookEx(hHook);

    }//析构函数中释放钩子函数

    //下面是获取消息后的处理函数

    LRESULT CALLBACK MouseProc (int nCode, WPARAM wParam, LPARAM lParam)
    {//是鼠标移动消息
     if((wParam == WM_MOUSEMOVE)||(wParam == WM_NCMOUSEMOVE))
     {
      point=((MOUSEHOOKSTRUCT *)lParam)->pt;
      //取鼠标信息
      pView->Invalidate(); //窗口重画
     }
     return CallNextHookEx(hHook,nCode,wParam,lParam);
     //传递钩子信息 ,如果直接return true 那么消息就不会往下继续发送
    }

    这样一个简单的针对线程的钩子应用就OK,移动鼠标就可以看见鼠标的坐标参数。

    下面是针对系统的hook应用了:

     这时必须用扩展DLL的方式来实现,为什么呢,因为要对整个系统起作用,要对系统的每个进程起作用,就必须修改他们公用的库,

    而这个动态库是可以扩展的,我们可以把钩子的处理通过DLL加入进去。这样,鼠标的信息不管在哪都会通过扩展DLL截下来

    然后通过调用该扩展DLL来进行消息的处理。

    mark 一下,未完待续

    首先建立DLL工程:

    建立时选择 共享DLL

  • 相关阅读:
    李宏毅机器学习课程笔记-9.3RNN的应用
    李宏毅机器学习课程笔记-9.2如何训练RNN
    李宏毅机器学习课程笔记-9.1循环神经网络RNN入门
    李宏毅机器学习课程笔记-8.2图神经网络(Spatial-based Convolution)
    李宏毅机器学习课程笔记-7.4基于CNN和PyTorch的食物图片分类
    PyTorch入门:基于LeNet5和CIFAR10的图片分类
    PyTorch入门:使用PyTorch搭建神经网络LeNet5
    李宏毅机器学习课程笔记-8.1图神经网络入门
    李宏毅机器学习课程笔记-7.3CNN应用案例
    李宏毅机器学习课程笔记-7.2CNN学到了什么
  • 原文地址:https://www.cnblogs.com/lishiqi/p/2640110.html
Copyright © 2020-2023  润新知