说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

用DELPHI编制Windows95下的钩子函数

HTML文档下载 WORD文档下载 PDF文档下载
用DELPHI编制Windows95下的钩子函数

Windows消息管理机构提供了能使应用程序访问控制消息流μ

'c4所谓的钩子(HOOK)机制。钩子有多种,分别用于捕获某一特定类型或某一范围的消息。如:键盘消息,鼠标消息等。我们这里仅以键盘钩子的使用为例,讨论在DELPHI下怎样编写DLL程序和怎样在自己的程序中安装使用键盘钩子函数,并讨论了不同程序使用同一DLL文件时怎样共享数据。

一、 钩子过滤函数的编写说明

由于钩子过滤函数必须在独立的模块中,也就是说我们必须首先生成一个DLL框架,然后再在其中加入钩子函数代码以及其他相关函数代码。我们这里以键盘钩子过滤函数的编写为例来说明。具体步骤如下:

1、先生成一个DLL筐2架

2、编写自己的键盘钩子过滤函数

钩子过滤函数必须是回调函数,其函数的 4稳缦拢o

function KeyHookProc(

iCode:Integer;

wParam:WPARAM;

lParam:LPARAM ) : LRESULT; stdcall ;export ;

在生成的DLL框架中加入自己的键盘钩子处理函数处理键盘消息。

代码如下:…

if(iCode>=0) then begin

Result:=0; //初始化返回值

// 在这里加入自己的代码

end else

begin

Result:=CallNextHook(hOldKeyHook

iCode

wParam

lParam);

// hOldKeyHook是保存的原键盘过滤函数 5刂·

end;

3、 安装键盘钩子过滤函数

为安装一个钩子筥fd滤函数应调用SetWindowsHookEx函数(适用于Windows3.0的SetWindowsHook钩子安装函数现在已经废弃不用)。该函数的原形如下:

HHOOK SetWindowsHookEx(

int idHook

// 安装的筥b3子类型

HOOKPROC lpfn

// 钩子过滤籂f数地址

HINSTANCE hMod

// 任务句柄

DWORD dwThreadId // 钩子用于的目的

);

需要说明的是:蚠a8常应该调用MakeProcInstance函数以获取一个输出函数的前导码的入口地址,再将此地址作为SetWindowsHookEx的第二个参数lpfn。但由于Delphi提供了"灵巧调用(smart callback)",使得MakeProcInstance可以省去,而直接将钩子过滤函数名用作入口地址。

这样当应用程序觃c3GetMessage或PeekMessage函数从消息队列中读消息或有按键消息(WM_KEYDOWN或WM_KEYUP)要处理时,系统就要调用钩子过滤函数KeyHookProc处理键盘消息。

4、 卸载钩子过滤函数。

当钩子函数不再需要时,应调用UnHookWindowsHookProc卸载安装的钩子以释放系统资源。

完整的程序清单如下ba

Library KEYHOOK;

uses Windows;

const BUFFER_SIZE=16*1024;

const HOOK_MEM_FILENAME='SAMPLE KEY_HOOK_MEM_FILE';

const HOOK_MUTEX_NAME ='SAMPLE KEY_HOOK_MUTEX_NAME';

type

TShared=record

Keys : array[0..BUFFER_SIZE] of Char;

KeyCount : Integer;

end;

PShared=^TShared;

var

MemFile

HookMutex : THandle;

hOldKeyHook : HHook;

ProcSaveExit : Pointer;

Shared : PShared;

//键盘钩子过滤函数

function KeyHookProc(iCode: Integer; wParam: WPARAM ; lParam: LPARAM):LRESULT

; stdcall; export;

const KeyPressMask = $80000000;

begin

if iCode < 0 then

Result := CallNextHookEx(hOldKeyHook

iCode

wParam

lParam)

else begin

if ((lParam and KeyPressMask)= 0) then // 键按下

begin

Shared^.Keys[Shared^.KeyCount]:=Char(wParam and $00ff);

Inc(Shared^.KeyCount);

if Shared^.KeyCount>=BUFFER_SIZE-1 then Shared^.KeyCount:=0;

end;

iCode:=-1;

Result := CallNextHookEx(hOldKeyHook

iCode

wParam

lParam);

end;

end;

// 设置钩子过滤函数

function EnableKeyHook : BOOL ; export;

begin

Shared^.KeyCount:=0; //初始化键盘指针

if hOldKeyHook=0 then begin

hOldKeyHook := SetWindowsHookEx(WH_KEYBOARD

KeyHookProc

HInstance

0);

end;

Result := (hOldKeyHook <> 0);

end;

//撤消钩子过滤函数

function DisableKeyHook: BOOL ; export;

begin

if hOldKeyHook<> 0 then

begin

UnHookWindowsHookEx(hOldKeyHook); // 解除 Keyboard Hook

hOldKeyHook:= 0;

Shared^.KeyCount:=0;

end;

Result := (hOldKeyHook = 0);

end;

//取得键盘缓冲区中击键的个数

function GetKeyCount :Integer ; export;

begin

Result:=Shared^.KeyCount;

end;

//取得键盘缓冲区的键

function GetKey(index:Integer) : Char ; export;

begin

Result:=Shared^.Keys[index];

end;

//清空键盘缓冲区

procedure ClearKeyString ; export;

begin

Shared^.KeyCount:=0;

end;

//DLL的退出处理过程

procedure KeyHookExit; far;

begin

if hOldKeyHook <> 0 then DisableKeyHook;

UnMapViewOfFile(Shared); // 释放内存映象文件

CloseHandle(MemFile); // 关闭映象文件

ExitProc := ProcSaveExit;

end;

exports // 定义输出函数

EnableKeyHook

DisableKeyHook

GetKeyCount

ClearKeyString

GetKey;

begin

// DLL 初始化部分

HookMutex:=CreateMutex(nil

True

HOOK_MUTEX_NAME);

// 通过建立内存映象文件以共享内存

MemFile:=OpenFileMapping(FILE_MAP_WRITE

False

HOOK_MEM_FILENAME);

if MemFile=0 then

MemFile:=CreateFileMapping($FFFFFFFF

nil

PAGE_READWRITE

0

SizeOf(TShared)

HOOK_MEM_FILENAME);

Shared:=MapViewOfFile(MemFile

File_MAP_WRITE

0

0

0);

ReleaseMutex(HookMutex);

CloseHandle(HookMutex);

ProcSaveExit := ExitProc; // 保存DLL的ExitProc

ExitProc := @KeyHookExit; // 设置DLL新的ExitProc

end.

// 源代码结束

二、 在自己的程序中使用编制好的键盘钩子过滤函数。

钩子函数编制好后,使用起来其实很简单:首先调用SetWindowsHookEx安装自己的钩子过滤函数,同时保存原先的钩子过滤函数地址。这时钩子函数就开始起作用了,它将按照你的要求处理键盘消息。程序运行完毕或不再需要监视键盘消息时,调用UnHookWindowsHookProc函数卸载所安装的钩子函数,同时恢复原来的钩子过滤函数地址。

下面就是使用在以上编制的钩子函数的例子:

unit Unit1;

interface

uses

Windows

Messages

SysUtils

Classes

Graphics

Controls

Forms

Dialogs

StdCtrls

ExtCtrls;

type

TForm1 = class(TForm)

Memo1: TMemo;

Panel1: TPanel;

bSetHook: TButton;

bCancelHook: TButton;

bReadKeys: TButton;

bClearKeys: TButton;

Panel2: TPanel;

procedure bSetHookClick(Sender: TObject);

procedure bCancelHookClick(Sender: TObject);

procedure bReadKeysClick(Sender: TObject);

procedure bClearKeysClick(Sender: TObject);

end;

var Form1: TForm1;

implementation

{$R *.DFM}

function EnableKeyHook : BOOL ; external 'KEYHOOK.DLL';

function DisableKeyHook : BOOL ; external 'KEYHOOK.DLL';

function GetKeyCount : Integer ; external 'KEYHOOK.DLL';

function GetKey(idx:Integer) : Char ; external 'KEYHOOK.DLL';

procedure ClearKeyString ; external 'KEYHOOK.DLL';

procedure TForm1.bSetHookClick(Sender: TObject); // 设置键盘钩 7ó

begin

EnableKeyHook;

bSetHook.Enabled :=False;

bCancelHook.Enabled:=True;

bReadKeys.Enabled :=True;

bClearKeys.Enabled :=True;

Panel2.Caption:=' 键盘钩子已经设置';

end;

procedure TForm1.bCancelHookClick(Sender: TObject); // 卸载键盘钩子

begin

DisableKeyHook;

bSetHook.Enabled :=True;

bCancelHook.Enabled:=False;

bReadKeys.Enabled :=False;

bClearKeys.Enabled :=False;

Panel2.Caption:=' 键盘钩子没有设置';

end;

procedure TForm1.bReadKeysClick(Sender: TObject); // 取得击键的历史记录

var i:Integer;

begin

Memo1.Lines.Clear; // 在Memo1中显示击键历史记录

for i:=0 to GetKeyCount-1 do

Memo1.Text:=Memo1.Text+GetKey(i);

end;

procedure TForm1.bClearKeysClick(Sender: TObject); // 清除击键历史记录

begin

Memo1.Clear;

ClearKeyString;

end;

end.

// 源代码结束

三、 Windows95下DLL中实现共享内存

在上面的钩子函数所在的DLL文件中,需要使用共享内存,即,所有击键的记录存储在同一个数据段中。为什么要这样做呢?这是因为Windows95的DLL调用方法与Windows3.X的方法不同。每个进(线)程在登录某动态连接库时都会为该动态连接库传入一个新的实例句柄(即DLL数据段的句柄)。这使得DLL各个实例之间互不干扰,但是这对那些所有DLL实例共享一组变量带来一些困难。为了解决这个问题,我们在这儿通过建立内存映射文件的方法来解决。即使用Windows的OpenFileMapping、CreateFileMapping和

MapViewOfFile三个函数来实现。使用方法如下:

MemFile是THandle类型,Shared是指针类型,HOOK_MEM_FILENAME是一常量串

MemFile:=OpenFileMapping(FILE_MAP_WRITE

False

HOOK_MEM_FILENAME); //打开内存映射文件

if MemFile=0 then //打开失败则衉c2建内存映射文件

MemFile:=CreateFileMapping($FFFFFFFF

nil

PAGE_READWRITE

0

SizeOf(TShared)

HOOK_MEM_FILENAME);

//映射文件到变量

Shared:=MapViewOfFile(MemFile

File_MAP_WRITE

0

0

0);

到此为止,你已经知道用Delphi编制钩子函数有多么容易。最后不得不提醒大家:钩子函数虽然功能比较强,但如果使用不当将会严重影响系统的效率,所以要尽量避免使用系统钩子。非要使用不可时也应该格外小心,应使之尽可能小地影响系统的运行。

Windows 8和IE 10:如何保障视频播放? 云计算大会讲师秀之13:梁家恩,12年积累,构建永久免费的语音云平台 众望所归:智能手机芯片将为服务器所用 没有学位,他通过以下四步进入Google 谈谈Google Polymer以及Web UI框架的未来 保密入髓:前苹果员工揭示公司是如此善于保守秘密 调查显示:软件开发公司出现“人才荒” 三星拟6月20日在伦敦召开新品发布会 推手机新品Galaxy和ATIV 历届中国云计算大会PPT集萃(五):数据安全隐患解析与应对 搞趣网创始人:做不了阳春白雪 就做下里巴人 CMDN Club 28期:创业公司一定不要浪费资源 浅谈Lean UX:我们到底该怎么设计? 张艺谋今日正式加盟乐视 作品专区落户超级电视 WebKit华丽转身:欧朋浏览器8.0新鲜出炉 分析师称应出售Bing?除非微软倒闭,否则不可能卖Bing Go Mobile沙龙第二期:软硬整合与创客精神 专访西电黄宝林:《基于GPU的并行NMF网络聚类算法》获奖背后故事 友友姚宏宇:用C,C++和Java实现自主研发之后,放开心态迎“高朋” 新技术对传统学科的颠覆:系谱网使用大数据寻亲问祖 IDC:2015年全球平板电脑出货量将超PC Web开发者的福利 30段超实用CSS代码 库克出席D11科技大会:苹果公司没有陷入麻烦 千兆的带宽是不够的,最新研究将我们带入400G时代! 告诉你一个事实:移动互联网依然不大 一切才刚刚开始 戴尔的10亿美元云扩建计划到底是什么? iOS vs. Android,应用设计该如何对症下药? 扁平化设计五大原则 16种折磨开发者的方式 2013年度中国优秀开源项目征集活动正式启动 技术趋势:产品设计向“钱”看 服务器领域:旧时代已过 新时代正在降临 寻找与CSDN类似的社区软件 谁有SCJP SL-275的原版电子版教材? 标准C程序中调用类的编译错误 access的mdb数据库如何编程知道里面含有那几个表? 谁有瑞星的升级程序,或是授权ID什么的?现在瑞星升级很烦啊!又是注册,又是授权的。 好象很少有人讨论日志文件的,能介绍点好的website吧(国内外均可)谢了先 Ghost之后,20G只剩下一个2G的C:!!!如何恢复,请指教,多谢!!! 我是初学者,问一个比较傻的问题:既然JAVA是一种纯面向对象的语言,那么为什么int i=new int()或int i=new int(1)不能通过编译?谢谢。 哪位能讲解一下,WEB服务器启动一个PHP 脚本的过程? 哪位朋友有没有做过让asp自动生成 Access数据库中的一张表 现想做一模块,主要是对股票数据在网络(包括公司内部网或是INTERNET)进行实时的发送; 关于DcomConnection的一个问题:连接局域网其他机器的应用程序服务器时“拒绝访问” 在VisData中正常通过,但在程序中不能通过,为什么 图像的小波分解和重构,模极大值算法。 师傅不在QQ,在这里吗?有个问题.//小新的徒弟. 老千,上次的那个rose下载网站,你还记得吗?偶忘了,搜索了几遍野没找到//牛虻 在VisData中正常通过但在程序中不能通过,为什么 向各位高手请教两句:tab_1.post selecttab(3) 的作用是不是向tab发送消息,消息内容是selecttab(3)?yield()是不是从消息中查找是否有相同消息,如果有则将它拿出执行? 我很莱,谁能给我简单的解释一下线程是什么?脱壳是什么? 图象资料,轻而易举30分! 和大家交流一下泛型化编程 文件拷贝的简单问题, 大家好:请问:access的mdb数据库如何编程知道里面含有那几个表? 怎样将mysql驱动加到jbuilder中,让Database pilot能认得出,高分相送 高分求教:关于ADO实现数据库!!!!!!!!!!谢谢 请问如何一次删除数据库中的所有数据? 怎么使label框透明!帮帮我! TNMUDP问题:怎样才能知道RemoteHost连接失败??? 谁有CuteFTP Pro2.0注册码?谢谢 如何进行DropDownList绑定,谢谢! 请问一个CString的问题 那个168查分台太可恶了 WIN98与WIN2000共享一个OFFICE??? 网络连接怎么检测 能把IE浏览器最大吗?俺指的是把右上最大按钮最大化? 怎么判断表单传送的整数中不能有字符,谢谢!!! 如何把我写好的说明书放到我VC++应用程序的帮助文件中? 求最容易理解,最容易上手的数据库书籍,各位老大请指教,谢谢!! 快!快快!!来拿分呀!!!!!!!!一个简单问题。 WIN98与WIN2000共享一个OFFICE 2000??? 在Servlet中如何使用JavaBean(调用其中的方法)?主要是格式!如果网上有这方面的资料也可以告诉我,我急用,不胜感激!40分送上!(只有这些了) 请问各位:怎样才能知道某一个进程所占用的cpu比例,mem大小? 请问在恢复sql 7.0一个数据库文件时,出现Error 3624:这是什么意思?? 关于程序员考试 哪位知道怎么一行一行地读取文本文件呀!!!! 谁知道的,来帮我一下——有关网页浏览计时的问题 如何将数字变为字符串格式化输出? Websphere下使用连接池的一些问题 TNMUDP问题:怎样才能知道RemoteHost连接失败 ? 算法请教,我要调整一副黑白数字图的浓度,我是用直方图的方法好呢,还是先转成HLS在转回来好?若都不对,应该怎么做? 如何 在ASP中用ping 12、甲、乙两站相距440千米,一辆大车和一辆小车从两站相对开出,大车每小时行35千米,小车每小时行45千米12、甲、乙两站相距440千米,一辆大车和一辆小车从两站相对开出,大车每小时行35千 汽车由哪几个基本部分组成? 汽车档位上的N,R,S,宝马550i上的当就这么写的, 小车和大车同时从甲乙两地相对开出,小车每小时行82千米,大车每小时行68千米,两车相遇时小车比大车多行35千米.相遇时两车行了多少小时?甲乙两站相距多少千米? 两地相距S千米,汽车走国道,速度为X千米/小时,改走高速公路,车速每小时提高40千米,可以提前几小时到达 汽车档位上的N,R,S, 检验硫酸根离子的最简单的方法是什么题目大致是“如何运用最贱方法检验溶液中有无硫酸根离子?如果有,应该如何去检验?”由此可知,第二问的答案是加氯化钡,第一问就不可能是了,可第一 汽车的构造的主要部分~ 现代汽车上的三元催化剂中的“三元”是何含义 若要检验无水氯化镁中不含氯化钠,最简单的操作方法是 SMC 电磁阀 型号SMC VK332-5DZ-01字母和数字分别代表什么意思?还有国产的什么型号能代替这个? 汽车s档是什么意思 如何运用最简单的方法检验so4 SMC 二位三通电磁阀功能问题个人理解二位三通电磁阀只能控制流体的通断或者换向功能.阀芯也应该是由电磁线圈的得电与失电控制其运动达到电磁阀功能的.但是今天一位老师傅跟我说得电 小车s档,在什么情况下使用? 如何运用最简便的方法检验粗盐溶液中的SO4 一辆小汽车有静止出发做匀加速直线运动,用10s时间通过一座长140m的平直桥,过桥后速度为16m/s.问1 它刚上桥是的速度有多大?2 桥头与出发点相距多远? 汽车轮胎规格185/60R14是什么意思?其中的185、60、R、14分别代表什么意思啊? 如何运用最简单的方法检验溶液中有无硫酸根离子 某小汽车质量为500kg,在1200N的牵引力作用下,从静止开始运动,经过10s速度可达到20m/s,若将小汽车的启动的过程,所受阻力恒定,求:(1)启动过程的加速度大小(2)所受阻力多大(3)启动后,经 汽车轮胎的型号185/65/14,185/65/14与185/60/14两种型号有何不同?请指教, 如何运用最简便的方法检测粗盐水中有无硫酸根离子 如果有 该如何除去硫酸根离子 一辆轿车从车站由静止出发做匀加速直线运动,经10s速度达到108km/h,它的加速度是——谢谢了, 缸径63-行程150的标准气缸,两端有调速阀,外接3位5通电磁阀,怎么控制? 能证明铝很活泼的实验有? 求推荐SMC电磁阀或者其他合适的电磁阀求推荐合适的电磁阀:三位五通,3/8接口管径,中封式.公司有一机械手,因为气缸带动的部件有一定重量,普通电磁阀容易出现:1、半空停顿时气缸缓慢下 请介绍一本带图解的汽车构造与原理的书 如何证明铝比锌活泼(实验!)急 汽车有几部分组成 我有一个气缸,我不加电磁阀直接接上气管,居然顶不动,然后我加上电磁阀就顶动了,这是为什么?气缸不就是一个进气一个出气就推,然后反过来就拉,我是一边直接加气管,另一边什么也不接,空 铝与稀盐酸反映的速率较快,原因是氯离子对反应有促进作用,设计个简单的试验验证说法正确?铝与稀硫酸较慢,原因是硫酸根离子对有抑制作用,也是设计个?随便问一下,谁有CS1.5版的下载网址 为什么匀速运动的小汽车前面有牵引力? 物理:为了安全,在公路上行驶的汽车间应保持必要的距离.已知某高速公路的最高限速v=72km/h.假设前方车辆突然停止,后面司机从发现这一情况,经操作刹车,到汽车开始减速所经历的时间(即 高速公路上,轿车超过了客车,此时客车的速度是轿车的() 汽车都有哪些部分组成? 为了安全,在公路上行驶的汽车之间应保持必要的距离.已知某高速公路的最高限速为120Km/h,假设前方车辆突然停止,后车司机发现此情况后立即刹车,这中间的反应时间为0.5s,刹车时汽车受到的 8个人乘速度相同的两辆小汽车同时赶往火车站.每辆车乘4人(不包括司机),其中一辆小汽车在距离火车站10千米的地方出现故障,此时距停止检票的时间还有28分钟,这时惟一可利用的交通工具 日本SMC电磁阀 VT307-5G-02-F这个表示什么意思?类似的还有其他的举例能不能介绍下. 高一物理题--------------------------------为了安全,在公路上行驶的汽车之间应保持必要的距离,已知某高速公路的最高限速为120km/h,假设前方车辆突然停止,后车司机从发现这一情况,经操纵刹车,到 什么是水质测试笔?怎么使用? 什么叫碳酸锰,什么叫半碳酸锰 自动档汽车的前进D档有几个档位 想测一下家里的水质,怎么弄 碳酸锰是什么颜色? 汽车分几部分组成?分别是什么? 怎么检测水质的好坏?怎样的水才可以饮用?我家的水塘里丢了一些喂鱼的草,鱼没吃完,结果水就有了一种气味,不知道还能不能饮用. 碳酸锰是干什么用的 关于可调行程气缸假如我有一个行程是200可调行程是50的气缸,那么这个气缸的实际应用的行程到底是多少?是0到200还是0到150还是150到200?气缸标注的行程跟可调行程之间的关系式什么? 有什么办法可以净化自来水的水质么?家里的水太难喝了.要求:使用生活中常用的东西. MnCO3=MnO+CO23MnCO3=Mn3O4+CO+2CO2请问碳酸锰热分解是哪一个方程式?谢谢!那么与第二个方程式类似的反应是哪个呢? SMC有伸缩式行程1.2米载重半吨气缸吗?价格和型号是多少? 在高速公路上,一辆长4米,速度为110千米/时的轿车准备超越一辆长12米,速度为100千米/时的卡车,则轿车从开始追尾到超越卡车,需要花费的时间大约是多少秒 如何由废旧电池制备碳酸锰 小车前进中挂了倒档怎么办 普通农村用户可以用什么基本方法检测井水水质? 小型轿车在高速公路上最高和最底时速是多少? 如果汽车高速行驶,从前进档直接挂倒档会怎么样? 如何进行水质检测,居家水质测定的方法 一辆客车从A地出发经过1小时到B地,再从B地行使2小时到C地.客车在国道上行使的平均速度是高速公路上的3分之2.已知该客车从A地道C地行使总路程是272Km.客车在国道上平均每小时行多少Km 汽车由哪几部分组成
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn