HOOK编程流程

Posted Autumn の Box

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HOOK编程流程相关的知识,希望对你有一定的参考价值。

一、安装钩子过程

  HHOOK SetWindowsHookEx(

      int idHook,       

      HOOKPROC lpfn,   

      HINSTANCE hMod,   

      DWORD dwThreadId  

  );

      idHook:指定将要安装的钩子过程的类型,包括:

        WH_CALLWNDPROC  --在操作系统将消息发送到目标窗口处理过程之前,对该消息进行监视

        WH_CALLWNDPROCRET  --对已被目标窗口过程处理过了的消息进行监视

        WH_CBT  --接受对CBT应用程序有用的消息

        WH_DEBUG  --对其他钩子过程进行调试

        WH_FOREGROUNDIDLE  --当应用程序的前台线程即将进入空闲状态时被调用,有助于在空闲时间内执行低优先级的任务

        WH_GETMESSAGE  --对发送到消息队列的消息进行监视

        WH_JOURNALPLAYBACK  --对此前由WH_JOURNALRECORD钩子过程记录的消息进行发送

        WH_JOURNALRECORD  --对发送到系统消息队列的输入消息进行记录

        WH_KEYBOARD  --对键盘按键消息进行监视

        WH_KEYBOARD_LL  --此钩子过程只能在WindowNT中安装,用来对底层的键盘输入事件进行监视

        WH_MOUSE  --对鼠标消息进行监视

        WH_MOUSE_LL  --此钩子过程只能在WindowNT中安装,用来对底层的鼠标输入事件进行监视

        WH_MSGFILTER  --监视由对话框、消息框、菜单条或滚动条中的输入事件引发的消息

        WH_SHELL  --接受对外壳应用程序有用的通知

        WH_SYSMSGFILTER  --监视由对话框、消息框、菜单条或滚动条中的输入事件引发的消息;该钩子过程对系统中所有应用程序的这类消息都进行监视

      lpfn:指向相应的钩子过程;如果参数dwThreadId为0或者指定了一个其他进程创建的线程之标识符,则参数lpfn必须指向一个位于某动态链接库中的钩子过程;否则参数lpfn可以指向当前进程相关的代码中定义的一个钩子过程;

      hMod:指定参数lpfn指向的钩子过程所在的DLL的句柄;如果参数dwThreadId指定的线程由当前进程创建,并且相应的钩子过程定义于与当前进程相关的代码中,则必须将参数hMod设为NULL;

      dwThreadId:指定与钩子过程相关的线程标识;如果为0,则安装的钩子过程将与桌面上运行的所有线程都相关;

  返回值:函数调用成功返回所安装的钩子过程的句柄,调用失败返回NULL;

二、安装鼠标钩子,监视鼠标消息

  LRESULT CALLBACK MouseProc(

      int nCode,     

      WPARAM wParam,

      LPARAM lParam  

  );

      nCode:确定钩子过程如何处理当前消息,包括:

        HC_ACTION  --表明参数wParam和lParam包含了关于鼠标消息的信息

        HC_NOREMOVE  --表明参数wParam和lParam包含了关于鼠标消息的信息,而且此鼠标消息尚未从消息队列中删除(程序调用了PeekMessage函数并设置了PM_NOREMOVE标志)

      wParam:指示鼠标消息的标识;

      lParam:指向MOUSEHOOKSTRUCT结构体指针;  

LRESULT CALLBACK MouseProc( int nCode, WPARAM wParam, LPARAM lParam)
{
    return 1;
}
.
.
.
HHOOK g_hMouse=NULL;
.
.
.
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());

三、安装键盘钩子

  LRESULT CALLBACK KeyboardProc(

      int code,      

      WPARAM wParam, 

      LPARAM lParam  

  );

      nCode:确定钩子过程如何处理当前消息,包括:

        HC_ACTION  --表明参数wParam和lParam包含了关于键盘消息的信息

        HC_NOREMOVE  --表明参数wParam和lParam包含了关于键盘消息的信息,而且此键盘消息尚未从消息队列中删除(程序调用了PeekMessage函数并设置了PM_NOREMOVE标志)

      wParam:产生当前按键消息的键盘按键的虚拟键代码(“VK_”开头,如VK_SPACE);

      lParam:一个32位的整数,用来指定按键重复的次数、扫描码、扩展键标记、上下文代码等标记,包括:

        0~15位:指示重复次数,此值记录了由于用户连续按键引发的按键重复次数

        16~23位:指示扫描码,此值依赖于键盘生产厂家

        第24位:指示当前按键是否是功能键或数字小键盘上的键;如果是,其值为1

        25~28位:保留未用

        第29位:上下文代码,如果Alt键被按下,其值为1,否则为0

        第30位:指示当前的键状态,如果在此消息被发送之前该键是按下的,其值为1,否则为0

        第31位:指示变化状态,如果此键正在被按下,则其值为0  

LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam)
{
    if(VK_F1==wParam){  //按F1程序退出
        ::SendMessage(g_hWnd,WM_CLOSE,0,0);
        UnhookWindowsHookEx(g_hKeyboard);  //从钩子链中移走已安装的钩子
        UnhookWindowsHookEx(g_hMouse);      
    }else if( VK_F4==wParam || (1==(lParam>>29 & 1))){
        return 1;  //屏蔽Alt+F4的功能
    }else{
        return CallNextHookEx(g_hKeyboard,code,wParam,lParam);
    }
}
.
.
.
HHOOK g_hKeyboard=NULL;
.
.
.
g_hKeyboard=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,NULL,GetCurrentThreadId());

四、把钩子信息传递给钩子链中下一个等待接收信息的钩子过程

  LRESULT CallNextHookEx(

      HHOOK hhk,     

      int nCode,     

      WPARAM wParam, 

      LPARAM lParam  

  );

      hhk:指定当前钩子过程句柄,即SetWindowsHookEx函数的返回值;

      nCode:确定钩子过程如何处理当前消息,包括:

        HC_ACTION

        HC_NOREMOVE

      wParam:指示消息的标识;

      lParam:指向结构体指针;

五、移除已安装的钩子过程

  BOOL UnhookWindowsHookEx( HHOOK hhk );

六、全局钩子

  如果要屏蔽当前正在运行的所有进程的鼠标消息和键盘消息,则安装钩子过程的SetWindowsHookEx函数代码必须放到动态链接库中实现,且将SetWindowsHookEx函数的第三个参数指定为安装钩子过程所在的DLL的句柄,将第四个参数设为0;

 

以上是关于HOOK编程流程的主要内容,如果未能解决你的问题,请参考以下文章

利用C++编程,将hook(钩子)加到程序每一个函数,其中hook后跳转到自己自定义函数代码,实现函数打印功能

C++ hook 问题

VSCode自定义代码片段——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

如何将 react-hook-form 用于嵌套数组