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 ...
随机推荐
- 资源汇集:nginx教程从入门到精通
http://linux.cn/article-4279-1.html
- html5笔记
出处:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html HTML5 LocalStorage 本地存储 HTML5 ...
- python pil 安装
Ubuntu下 sudo pip install pil 安装PIL可能会出现问题,例如安装完成时显示JPEG support not available 或者 ZLIB (PNG/ZIP) supp ...
- VC6配置OpenCV1.0
懒得写字,故扫描:
- centos6.5安装配置zabbix3.0.3
1.首先要准备LAMP环境. (1)安装php Zabbix 3.0对PHP的要求最低为5.4,而CentOS6默认为5.3.3,完全不满足要求,故需要利用第三方源,将PHP升级到5.4以上 rpm ...
- qml自定义标题栏
要实现自定义的标题栏只需在原来的窗口的基础上创建一个Rectangle并将其定位在窗口顶部即可,实现代码如下: ApplicationWindow { id: mainWindow visible: ...
- C#定时器
在C#里关于定时器类就有3个 1.定义在System.Windows.Forms里 2.定义在System.Threading.Timer类里 3.定义在System.Timers.Timer类里 S ...
- jquery 点击查看,收起特效
<div class="all"> <p><a href="javascript:;" id="onvk"&g ...
- Redis 与 数据库处理数据的两种模式(转)
Redis 是一个高性能的key-value数据库. redis的出现,很大程度补偿了memcached这类key-value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用.它提供了Pyt ...
- NGINX+UWSGI 莫名发生Nginx 502 Bad Gateway错误的排查过程
自己有个阿里云UBUNTU运行的Django站,使用NGINX+UWSGI驱动,今天登陆系统后台更新内容出现了几个大字:Nginx 502 Bad Gateway,一看情况不好,这是要糟糕啊. 啊西八 ...