MFC线程钩子和全局钩子[HOOK DLL]
第一部分:API函数简介
1. SetWindowsHookEx函数
函数原型
HHOOK SetWindowsHookEx(
int idHook, // hook type
HOOKPROC lpfn, // hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // thread identifier
);
函数功能:该函数将一个应用程序定义的挂钩处理过程安装到挂钩链中去,您可以通过安装挂钩处理过程来对系统的某些类型事件进行监控,这些事件与某个特定的线程或系统中的所有事件相关.具体参数详见MSDN;
举例:
线程钩子:
HHOOK g_hMouse;//全局变量,保存钩子的句柄
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
//……
}
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());
2. CallNextHookEx函数
函数原型:
LRESULT CallNextHookEx(
HHOOK hhk, // handle to current hook
int nCode, // hook code passed to hook procedure
WPARAM wParam, // value passed to hook procedure
LPARAM lParam // value passed to hook procedure
);
函数功能:调用下一个钩子
3. UnhookWindowsHookEx
函数原型:
BOOL UnhookWindowsHookEx(
HHOOK hhk // handle to hook procedure
);
第二部分:HOOK与DLL
1.线程钩子的创建过程:
1. 声明一个全局的HHOOK类型的变量,用于保存创建钩子的句柄,如:
HHOOK g_hMouse;//全局变量,保存钩子的句柄
2. 在应用程序的初始化函数中,安装钩子;注意SetWindowsHookEx的参数!
g_hMouse=SetWindowsHookEx(WH_MOUSE,MouseProc,NULL,GetCurrentThreadId());
3. 编写处理钩子消息的回调函数:
LRESULT CALLBACK MouseProc(
int nCode, // hook code
WPARAM wParam, // message identifier
LPARAM lParam // mouse coordinates
)
{
//编写需要处理的部分
return 1;
//不需要处理的部分,调用
return CallNextHookEx(g_hMouse, nCode, wParam, lParam);
}
4. 卸载钩子函数
UnhookWindowsHookEx(g_hMouse);
2.系统钩子的创建过程:
运行机制:DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。也就是说每个进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。#pragma data_seg预处理指令用于设置共享数据段。例如:
#pragma data_seg("SharedDataName")
HHOOK hHook=NULL;
#pragma data_seg()
在#pragma data_seg("SharedDataName")和#pragma data_seg()之间的所有变量将被访问该Dll的所有进程看到和共享。再加上一条指令
#pragma comment(linker,"/section:.SharedDataName,rws")
那么这个数据节中的数据可以在所有DLL的实例之间共享。所有对这些数据的操作都针对同一个实例的,而不是在每个进程的地址空间中都有一份。
系统钩子的创建需要将钩子的放在DLL中,因此其重建构成需要两部分:1.编写程序,生成Dll;2.编写应用程序调用Dll中的函数
2.1 DLL中的代码的编写
方案 1:源代码:http://download.csdn.net/detail/nuptboyzhb/4202102
1. 新建一个扩展MFC类型DLL工程;
2. 将DLL的句柄参数和要安装钩子的句柄声明为共享数据:
#pragma data_seg("Titlename") //名称任意起
HHOOK glhHook=NULL; //安装的鼠标钩子句柄
HINSTANCE glhInstance=NULL;//DLL实例句柄
#pragma data_seg()
注意:共享数据必须初始化,否则微软编译器会把没有初始化的数据放到.BSS段中,从而导致多个进程之间的共享行为失败。
3. 新建一个CMouseHook的导出类,用于实现钩子的安装和卸载
class AFX_EXT_CLASS CMouseHook:public CObject //AFX_EXT_CLASS宏声明类为导出类
{
public:
CMouseHook();//钩子类的构造函数
~CMouseHook();//钩子类的析构函数
BOOL StartHook(HWND hWnd);//安装钩子函数
BOOL StopHook();//卸载钩子函数
};
注意:AFX_EXT_CLASS用于声明该类为导出类;
4. 编写安装钩子,卸载钩子,钩子过程的函数
安装钩子:glhHook=SetWindowsHookEx(WH_MOUSE,MouseProc,glhInstance,0);
卸载钩子:UnhookWindowsHookEx(glhHook);
钩子过程:
//鼠标钩子函数的实现
LRESULT CALLBACK MouseProc(int nCode,WPARAM wparam,LPARAM lparam)
{
LPMOUSEHOOKSTRUCT pMouseHook=(MOUSEHOOKSTRUCT FAR *) lparam;
if (nCode>=0)
{
//处理过程的代码…..
}
return CallNextHookEx(glhHook,nCode,wparam,lparam); //继续传递消息
}
2.2 主程序的调用
新建一个应用程序,将上述生成的.dll文件和.lib文件及类声明的文件.h拷贝到当前目录中,并在头文件中包含生成的类声明.h文件;静态方式加载动态链接库
#pragma comment(lib,"MousehookDll.lib") //隐式链接DLL
然后就可以声明一个由DLL文件导出的类CMouseHook的一个变量;然后在应用程序的初始化函数中调用该变量的StartHook函数安装钩子;在需要取消钩子的地方,调用StopHook()函数;
附录:钩子过程函数参数详解
从上面的步骤中可以看到,钩子的安装和卸载是一个较为固定格式和步骤;真正关键的是:不同的钩子类型,回调函数的参数意义不同,那我们就一一介绍各个参数的意义吧!
a. MouseProc(int nCode,WPARAM wparam,LPARAM lparam)WH_MOUSE
1.nCode 跟所有其他钩子处理函数一样,只要记得当 nCode小于0时:调用CallNextHookEx()就可以了。
HC_ACTION 当nCode等于HC_ACTION时,wParam和lParam 包含鼠标信息 HC_NOREMOVE 当nCode等于HC_NOREMOVE时,wParam和lParam 包含鼠标信息,并且鼠标消息没有从消息队列里移除
2. wParam 指定鼠标消息ID
3. lParam 一个MOUSEHOOKSTRUCT 结构的指针
typedef struct tagMOUSEHOOKSTRUCT {
POINT pt; //保存鼠标在屏幕上的x,y坐标
HWND hwnd; //接收到鼠标消息的窗口的句柄
UINT wHitTestCode; //详细描述参见WM_NCHITTEST消息
ULONG_PTR dwExtraInfo; //指定与本消息联系的额外消息
} MOUSEHOOKSTRUCT, *PMOUSEHOOKSTRUCT;
b. KeyboardProc(int nCode,WPARAM wparam,LPARAM lparam) WH_KEYBOARD
2.wParam:按键的虚拟键值消息,例如:VK_F1 VK_F2 等;
3. lParam:32位内存,内容描述包括:指定扩展键值,扫描码,上下文,重复次数。
0-15位:描述:按下键盘次数。
16-23位:指定扫描码. 依赖于OEM
24位:当24位为1时候:表示按键是扩展键;当24位为0时候:表示按键是数字键盘按键
25-28位:保留位
29位:上下文键:为1时: ALT按下,其他情况为0
30位:如果是按键按下后发送的消息,30位为0,如果是按键抬起后30位为1;
31位:指定转变状态;31位为0时候,按键正在被按下,为1时候,按键正在被释放
c. GetMsgProc(int nCode,WPARAM wparam,LPARAM lparam) WH_GETMESSAGE
2.wParam:标明消息是否从消息对列中取出,它有如下两个值:
PM_NOREMOVE:未从消息队列中取出
PM_REMOVE:已经从消息队列中取出
3. lParam: 它是指向MSG结构体的一个指针
typedef struct tagMSG {
HWND hwnd; //接收消息的窗口句柄
UINT message; //消息的标识,如WM_CLOSE等
WPARAM wParam;// 指定消息的附加信息
LPARAM lParam; // 不同的消息不一样;
DWORD time; //消息投递到消息队列中的时间
POINT pt; //消息投递到消息队列中时的鼠标位置(屏幕坐标)
} MSG, *PMSG;
d. 未完待续…
MFC线程钩子和全局钩子[HOOK DLL]的更多相关文章
- git自定义项目钩子和全局钩子
钩子介绍 自定义钩子分为:项目钩子和全局钩子 自定义全局钩子: 全局钩子目录结构: (注意:excludes目录结构是我们自定义的目录,规则逻辑在update.d/update.py脚本里实现的,非g ...
- Django12-ModelForm中创建局部钩子和全局钩子
一.局部钩子 命名规则为clean_对象名称,例如上面定义了username.pwd对象,那么可以定义clean_username.clean_pwd的局部钩子进行规则校验 1.例子:定义一个手机号校 ...
- form表单钩子,局部钩子和全局钩子
form表单源码解析: 局部钩子: 全局钩子:
- Django学习笔记(14)——AJAX与Form组件知识补充(局部钩子和全局钩子详解)
我在之前做了一个关于AJAX和form组件的笔记,可以参考:Django学习笔记(8)——前后台数据交互实战(AJAX):Django学习笔记(6)——Form表单 我觉得自己在写Django笔记(8 ...
- Django框架(十四)-- forms组件、局部钩子、全局钩子
一.什么是forms组件 forms组件就是一个类,可以检测前端传来的数据,是否合法. 例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等 二.forms组件的使用 1.使用语 ...
- Django框架(十五)—— forms组件、局部钩子、全局钩子
目录 forms组件.局部钩子.全局钩子 一.什么是forms组件 二.forms组件的使用 1.使用语法 2.组件的参数 3.注意点 三.渲染模板 四.渲染错误信息 五.局部钩子 1.什么是局部钩子 ...
- django----利用Form 实现两次密码输入是否一样 ( 局部钩子和全局钩子 )
from django import forms # 导入表单模块 from django.core.exceptions import ValidationError class RegisterF ...
- ModelForm错误验证自定义钩子和全局钩子
当需要对model_class中字段作进一步验证,作进一步的约束时,需要使用到钩子,即claan_xxx和clean方法.其返回的errors有点不是那么好处理.看示例. 1.Model_clas ...
- Django学习笔记之form组件的局部钩子和全局钩子
本文通过注册页面的form组件,查看其中使用的全局钩子和局部钩子. # Create your views here. class RegForm(forms.Form): username = fo ...
随机推荐
- jQuery 自定义事件的学习笔记
jquery中提供了两种方法可以绑定自定义事件: bind()和one()而绑定的自定义事件的触发,必须得用jquery中的trigger()方法才能触发. 我们先来看on事件 代码如下 复制代码 ...
- 第五十篇、OC中常用的第三插件
1.UIViewController-Swizzled 当你接手一个新项目的时候,使用该插件,可以看到控制器的走向,当前控制是哪个,下一个跳转到哪里 2. 一个Xcode小插件,将Json直接转成模型 ...
- (转)Ehcache作为分布式缓存的研究
ehcache支持两种拓扑结构,一种是Distributed Caching,另一种是Replicated Caching Distributed Caching 这和一般意义上的分布式缓存非常类似, ...
- PHP中常量
PHP中常量 常量就是一种特殊的变量,PHP中的常量值一旦定义,在程序运行过程中不可更改,常量本身也不允许删除. 程序是用于解决现实问题,由两部分组成:代码,数据 常量的定义: 语法1: define ...
- C语言 SDK编程之通用控件的使用--ListView
一.ListView控件属于通用控件CONTROL中的一种,在SDK编程方式时要使用通用控件 必须包含comctl32.dll,所以代码中要有头文件: commctrl.h 导入库:comctl32. ...
- iOS 非ARC基本内存管理系列 4-autorelease方法和@autoreleasepool
1.autorelease 基本用法 对象执行autorelease方法时会将对象添加到自动释放池中 当自动释放池销毁时自动释放池中所有对象作release操作 对象执行autorelease方法后自 ...
- SVN全量备份+增量备份脚本
一.全量备份 环境:一台主SVN,一台备SVN(主要提供备份功能),后续可通过钩子脚本进行实时备份,后续发给大家. 工作原理:通过svn的hotcopy命令过行热备份,并进行一系列的检查,备份后通过r ...
- Stimulsoft Reports报表工具
关于第三方的报表工具,网上的种类有很多,一些专门做报表工具的公司,还针对不同平台语言做了分别处理.总之功能都很强大,比较流行和使用广泛的貌似还是国外的产品,版本收费和中文资料匮乏,这都是不可避免的问题 ...
- Web性能压力测试工具之Siege详解
PS:Siege是一款开源的压力测试工具,设计用于评估WEB应用在压力下的承受能力.可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进 ...
- ZENCART 打开/关闭日志文件
优秀的php开源程序很多都只带生成日志文件的功能,这类功能的开发可以帮助到站长在调试网站的时候及时的改正网站存在的错误,但是这类错误日志由来并非网站出现什么严重不可挽救的错误,大部分是一些未定义变量这 ...