用Delphi实现Windows的鼠标钩子函数
Delphi是基于PASCAL语言的Windows编程工具,功能十分强大。然而在Delphi的帮助
文件中,对Windows API函数的说明沿袭了 VC 的格式,和VC一样,对很多API函数的用法
没有举例子详细说明,对一些深入系统内部的API函数更是语焉不详,给编程者带来不便。
笔者仅就在Windows编程中鼠标钩子函数(HOOK)的实现,举例作一说明。
鼠标钩子函数也可叫做鼠标消息过滤器,是一种回调(CALLBACK)函数,归
系统调用。如果用SetWindowsHook或SetWindowsHookEx安装了鼠标钩子函数的地址, 每
当在屏幕上移动鼠标时,系统便将控制权交给鼠标钩子函数,这样便使我们能够有机会在
鼠标钩子函数内部截获各种鼠标消息,在这些消息还没有送达应用程序队列之前,显示它
们,改变它们或直接传给下一个缺省鼠标钩子函数。注意,鼠标钩子函数截获的是系统级
消息,而不是单个应用程序队列内的窗口消息;系统发给每个应用程序队列的鼠标消息都
可以用鼠标钩子函数来截获。
VC的Spy和Delphi的WinSpy均安装了钩子函数用来截获各种系统级的消息,其中就
包括鼠标钩子函数,键盘钩子函数,窗口钩子函数等。我们可以通过安装鼠标钩子函数来
仿制一个自己的SPY,当鼠标移动时,我们立即获得系统(包括非抢先的Windows3.1和
抢先Windows95)的控制权,在鼠标钩子函数内部实时地截获鼠标消息,显示鼠标的位置
和状态以及鼠标下窗口的局柄,标题栏,窗口类,窗口过程地址等。当然也可象“英汉通”
和“金山词霸”一样在鼠标钩子函数内调用InvalidateRect(),InvalidateRgn()来获得屏
幕上鼠标下的单词。(屏幕抓字的详情请见笔者的《深入Windows内部探险》中国计算机报
1998年第81期 )。
主程序SPY及其动态连接库MOUSEDLL的原代码和详细注释如下:
{*****************************************************
FILE : MOUSEDLL.DPR mafeitao@371.net 1998/11/18
〉DLL : MOUSEDLL.DLL
EXPORT: sethook 用来安装鼠标钩子函数 mouseproc
unhook 解除对鼠标钩子函数 mouseproc的安装
mouseproc 鼠标钩子函数本身
*****************************************************}
library Mousedll;
uses
Mousep in 'MOUSEP.PAS' {Form1};
exports
sethook,
unhook,
mouseproc;
{$R *.RES}
begin
end.
{*************************************************************
file:Mousep.pas mafeitao@371.net
实现 setHook unHook mouseProc 3个输出函数
*************************************************************}
unit Mousep;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
{在DLL中也可有FORM型的变量}
type
TForm1 = class(TForm)
Label1: TLabel; {显示wParam}
Label2: TLabel; {显示lParam}
Label3: TLabel; {显示x,y}
Label4: TLabel; {显示hwnd}
Label5: TLabel; {显示window text}
Label6: TLabel;
Label7: TLabel; {显示window class}
private
{ Private declarations }
public
{ Public declarations }
end;
function sethook:bool;export;
function unhook:bool;export;
function mouseProc(code:integer;w:integer;l:longint):bool;export;
var
Form1: TForm1;
idhook:longint;
formok:bool;
implementation
{*********************************************************************
声明安装函数setWindowsHookEx(),
在Delphi中如果用函数setWindowsHook()则不需声明。
微软说函数setWindowsHook已在Windows3.1中废弃,为与Windows3.0兼容仍保留。
实际上该函数setWindowsHook在Windows3.1和Windows95中仍可使用。
{*********************************************************************}
function setwindowsHookEx(id:integer;proc:tfarproc;hinst,htask:thandle):
longint;far;external 'user';
{$R *.DFM}
{安装鼠标钩子函数mouseProc}
function sethook:bool;
var
hinst:thandle; {该动态连接库自己的模块局柄}
proc:tfarproc; {鼠标钩子函数mouseProc的地址}
begin
{在动态连接库中创建form1}
if formok=false then form1:=tform1.create(application) else exit;
formok:=true;{安装form1 后,设置formok,不许再安装form1}
{动态连接库的application指:调用动态连接库的主程序}
form1.show;
{不让用系统菜单来双击关闭Form1}
form1.BorderIcons:=form1.BorderIcons-[biSystemMenu];
hinst:=getModuleHandle('mousedll');
{得到mousedll.dll的模块局柄,即该动态连接库自己的模块局柄}
proc:=getProcAddress(hinst,'mouseProc');
idhook:=setWindowsHookEx(WH_MOUSE,proc,hinst,0);
{用WH_MOUSE参数安装鼠标钩子后,移动鼠标时,系统自动调用mouseProc钩子}
if idhook =0 then sethook:=false else sethook:=true;
end;
{解除鼠标钩子函数mouseProc的安装}
function unhook:bool;
begin
if formok=true then form1.free else exit; {检查form1是否已经关闭}
formok:=false;{关闭了form1,设置formok=0}
if idhook=0 then exit;
unhookWindowsHookEx(idhook);
unhook:=true;
end;
{mouseProc不由应用程序调用,而是在鼠标移动后,由系统调用}
function mouseProc(code:integer;w:integer;l:longint):bool;
var
p:^TMouseHookStruct;
poff:word;
pseg:word;
pmemo:pchar;
begin
if code<0 then begin
mouseProc:=true;
CallNextHookEx(idhook,0,w,l);
end;
if code=HC_NOREMOVE then form1.caption:='HC_NOREMOVE';
form1.caption:='mouse hook';
mouseProc:=false;
{显示系统传来的wParam参数,w是各种鼠标消息的标识符 }
form1.label1.caption:='wParam='+intTostr(w);
{显示系统传来的lParam参数,l是MOUSEHOOKSTRUCT结构的地址}
form1.label2.caption:='lParam='+intTostr(l);
poff:=loword(l); {得到l的低16位}
pseg:=hiword(l); {得到l的高16位}
p:=ptr(pseg,poff); {合成指向MOUSEHOOKSTRUCT结构的指针}
{显示屏幕上鼠标的X,Y坐标}
form1.label3.caption:='pt.x='+intTostr(p^.pt.x)
+' pt.y='+intTostr(p^.pt.y);
{显示屏幕上鼠标下的窗口局柄}
form1.label4.caption:='hwnd='+intTostr(P^.hwnd);
pmemo:=stralloc(20);
getWindowText(p^.hwnd,pmemo,20-1);
{显示鼠标下窗口的标题栏}
form1.label5.caption:=strPas(pmemo);
getClassName(p^.hwnd,pmemo,20-1);
{显示鼠标下窗口的类}
form1.label6.caption:=strPas(pmemo);
strDispose(pmemo);
end;
end.
主程序原代码如下:
{*******************************************
MAINTRY.DPR mafeitao@371.net
******************************************}
program Maintry;
uses
Forms,
Tryp in 'TRYP.PAS' {Form1};
{$R *.RES}
begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
{*********************************************
TRYP.PAS mafeitao@371.net
********************************************}
unit Tryp;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton; { 安装setHook按钮}
Button2: TButton; { 解除 unHook按钮}
Label1: TLabel; {显示安装,解除是否成功}
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
function sethook:bool;far;external 'mousedll';
function unhook:bool;far;external 'mousedll';
{声明后自动加载模块mousedll.dll}
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
if sethook then label1.caption:='set hook ok'; {安装鼠标钩子函数}
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if unhook then label1.caption:='unhook ok'; {解除鼠标钩子函数}
end;
end.
http://blog.csdn.net/diligentcatrich/article/details/6934092
用Delphi实现Windows的鼠标钩子函数的更多相关文章
- Delphi的windows剪切板操作函数
1. Clipbrd函数 function Clipboard: TClipboard;:若应用程序从未使用过剪贴板,则调用该函数形成新的剪贴板:若之前使用过剪贴板则返回使用过的剪贴板. 属性: As ...
- HOOK API (一)——HOOK基础+一个鼠标钩子实例
HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...
- VC6 鼠标钩子 最简单样例
Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它能够截获并处理送给其它应用程序的消息,来完毕普通应用程序 ...
- 利用钩子函数来捕捉键盘响应的windows应用程序
一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到 ...
- Delphi实现全局鼠标钩子
其中涉及到的一些API,网上均能查到详细的解释,这里不再熬述.源码下载 因为是全局钩子,所以要用dll注入.用到的鼠标消息结构如下: PMouseHookStruct = ^TMouseHookStr ...
- DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)
函数重载重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同.实际上,编译器是通过检测参数来确定需要调用的例程.下面是从VCL 的数学单元(Math Unit)中摘录的一 ...
- windows钩子函数
一 什么时候用到钩子?(when)Windows操作系统是建立在事件驱动的消息处理机制之上,系统各部分之间的沟通也都是通过消息的相互传递而实现的.通常情况下,应用程序只能处理当前进程的消息,如果需要对 ...
- QT实现鼠标钩子(使用SetWindowsHookEx安装mouseProc函数)
HHOOK mouseHook=NULL; LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) { if(nCode ...
- php 钩子函数原理 解析
目前对钩子的理解:<转载:http://www.cnblogs.com/del/archive/2008/02/25/1080825.html> 譬如我们用鼠标在某个窗口上双击了一次, 或 ...
随机推荐
- 将string当字节流使
string是C++标准定义的字符串类,它不但支持文本,而且支持二进制字节流.给一个string变量赋值有多种方法: 1) 拷贝构造函数 2) 等号赋值函数 3) append成员函数 4) push ...
- [置顶] linux常用命令手册
前言:整理了一份linux常用命令手册,与大家分享.这是一些比较常用的命令. 我已经整理成一份PDF带书签的手册,可以到CSDN免费下载. 下载地址:http://download.csdn.net/ ...
- Swift编程语言学习2.1——基础运营商(在)
操作员正在检查,更改.归并值特殊符号或短语.例如,加+这两个数字相加(例如let i = 1 + 2). 算如更复杂的逻辑和操作的实施&&(例如if enteredDoorCode & ...
- Mysql 的一些基本用法
一.增加字段 COMMENT '是否导入基础信息平台 1 是导入'; 二.删除字段 alter table `provincestudentinfo` drop column NativePlace; ...
- POJ 1562(L - 暴力求解、DFS)
油田问题(L - 暴力求解.DFS) Description The GeoSurvComp geologic survey company is responsible for detecting ...
- [Swust OJ 404]--最小代价树(动态规划)
题目链接:http://acm.swust.edu.cn/problem/code/745255/ Time limit(ms): 1000 Memory limit(kb): 65535 Des ...
- jQuery带有定时器的tab栏切换
现在网上很多类似选项卡的切换,我们成为tab栏切换,比如下图: 新浪的tab栏切换 淘宝的tab栏切换 其中,新浪的tab栏鼠标放上去,可以快速的来回切换,但是如果采取ajax异步传输,不停去加载服务 ...
- 一步一步重写 CodeIgniter 框架 (12) —— 代码再重构,回归 CI
第一课中搭建的基本的 框架模型, 只有一个 index.php 作为执行文件,按这种方式最不稳定的因素就是路径的问题. 我们经常需要通过合适的参数,比如 load_class('output') 或 ...
- 一步一步重写 CodeIgniter 框架 (11) —— 使用 CodeIgniter 函数库
在完成了CI框架的类库扩展后,很自然我们就会想到函数库的扩展.函数库的扩展在 CI 中称为 helper 函数与类有不同的地方,它不能继承,只能覆盖或者添加新的函数,或者直接完全新定义的一组函数. 由 ...
- Hadoop伪分布式模式部署
Hadoop的安装有三种执行模式: 单机模式(Local (Standalone) Mode):Hadoop的默认模式,0配置.Hadoop执行在一个Java进程中.使用本地文件系统.不使用HDFS, ...