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的鼠标钩子函数的更多相关文章

  1. Delphi的windows剪切板操作函数

    1. Clipbrd函数 function Clipboard: TClipboard;:若应用程序从未使用过剪贴板,则调用该函数形成新的剪贴板:若之前使用过剪贴板则返回使用过的剪贴板. 属性: As ...

  2. HOOK API (一)——HOOK基础+一个鼠标钩子实例

    HOOK API (一)——HOOK基础+一个鼠标钩子实例 0x00 起因 最近在做毕业设计,有一个功能是需要实现对剪切板的监控和进程的防终止保护.原本想从内核层实现,但没有头绪.最后决定从调用层入手 ...

  3. VC6 鼠标钩子 最简单样例

    Windows系统是建立在事件驱动的机制上的,说穿了就是整个系统都是通过消息的传递来实现的.而钩子是Windows系统中非常重要的系统接口,用它能够截获并处理送给其它应用程序的消息,来完毕普通应用程序 ...

  4. 利用钩子函数来捕捉键盘响应的windows应用程序

    一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到 ...

  5. Delphi实现全局鼠标钩子

    其中涉及到的一些API,网上均能查到详细的解释,这里不再熬述.源码下载 因为是全局钩子,所以要用dll注入.用到的鼠标消息结构如下: PMouseHookStruct = ^TMouseHookStr ...

  6. DELPHI语法基础学习笔记-Windows 句柄、回调函数、函数重载等(Delphi中很少需要直接使用句柄,因为句柄藏在窗体、 位图及其他Delphi 对象的内部)

    函数重载重载的思想很简单:编译器允许你用同一名字定义多个函数或过程,只要它们所带的参数不同.实际上,编译器是通过检测参数来确定需要调用的例程.下面是从VCL 的数学单元(Math Unit)中摘录的一 ...

  7. windows钩子函数

    一 什么时候用到钩子?(when)Windows操作系统是建立在事件驱动的消息处理机制之上,系统各部分之间的沟通也都是通过消息的相互传递而实现的.通常情况下,应用程序只能处理当前进程的消息,如果需要对 ...

  8. QT实现鼠标钩子(使用SetWindowsHookEx安装mouseProc函数)

    HHOOK mouseHook=NULL; LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) { if(nCode ...

  9. php 钩子函数原理 解析

    目前对钩子的理解:<转载:http://www.cnblogs.com/del/archive/2008/02/25/1080825.html> 譬如我们用鼠标在某个窗口上双击了一次, 或 ...

随机推荐

  1. Unity的Cover flow的实现包(2个)

    苹果的mac机上预览图片,有一个所谓的cover flow的效果,这里收集到两个,两个实现效果略有不同. 1.老外的实现 https://github.com/rakkarage/Unity3D-Co ...

  2. D.6661 - Equal Sum Sets

    Equal Sum Sets Let us consider sets of positive integers less than or equal to n. Note that all elem ...

  3. 再见了acm

    2013年11月17日长沙区域赛我的最后一场区域赛. 忙碌了三年的acm要停下脚步,一时还无法接受. 这样一个结果有点无奈. 感谢队友,三年三支队伍五个队友,感谢你们.(每当写到这里时就总有点小忍不住 ...

  4. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...

  5. Codeforces Round #254 (Div. 2) DZY Loves Chemistry【并查集基础】

    一开始不知道题意是啥意思,迟放进去反应和后放进去反应有什么区别 对于第三组数据不是很懂,为啥312,132的组合是不行的 后来发现这是一道考察并查集的题目 QAQ 怒贴代码: #include < ...

  6. javascript 入门之简单换肤效果

    大家好,我是小强老师,这里简单入门 做一个换肤效果 效果如图所示: 这个案例思路分为两部分: 获取元素对象. var pic1 = document.getElementById('pic1'); v ...

  7. 基于SOAP的xml网络交互心得

    感谢小二同学将遇到的问题分享给我们,再此给以掌声.如果看不懂下面文章的建议查找一下HTTP协议的文艺,对HTTP协议要有个概念. XML网络交互心得 目录 一.     xml解析 1.根路径下 2. ...

  8. 动态规划——最长公共子序列(LCS)

    /** * @brief longest common subsequence(LCS) * @author An * @data 2013.8.26 **/ #include <iostrea ...

  9. 在C++中使用C#编写的类2

    在那篇<在C#中使用C++编写的类>中我介绍了如何在C#中使用C++编写的类.可是由于C#在用户界面设计.数据库存储和XML文件读取等方面的优势,有时候也会出现要在C++中使用C#编写的类 ...

  10. linux指令(目录类操作指令)

    pwd 显示当前所在的工作目录 cd 目标目录    例如cd  /boot/grub 从当前目录切换到某个目录 cd  切换到根目录 cd.. 切换到当前目录的上层目录 ls  显示当前目录下的内容 ...