转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
Delphi中的消息钩子函数和Windows子类处理 入门篇         ★★★★

Delphi中的消息钩子函数和Windows子类处理 入门篇

作者:闵涛 文章来源:闵涛的学习笔记 点击数:2455 更新时间:2009/4/23 18:34:58

    首先感谢各位老鸟这么久以来对小弟那么多的指导,给小弟提供N多的帮助,所以才
能让我的第一篇技术文章可以这么快和大家见面!也趁今天是小弟20岁生日呵呵,没人给
我庆祝,所以写篇文章做个纪念,也祝我自己生日快乐! ^o^

    小弟我学习Delphi算起来也有半年时间,看到网上很多朋友对HOOK非常的感兴趣。
所以即兴写了一篇文章,在CSDN里小弟曾经发过一篇《Delphi的MU窗口代码》(惭愧啊)
由于那时候学的不久,所以有很多地方不是很完善,借此文章重新向大家详细介绍一下
Windows下的消息钩子函数的用法和Windows的子类处理,希望对你们有帮助。

    好了,废话了这么久,也该进入正题了,关于HOOK的介绍就不再此介绍了,以前有
很多例子和文章可以参考,实在不行google或者baidu一下!^_^

首先我们先看一下安装HOOK的函数:


HHOOK SetWindowsHookEx(
    int idHook,       //要安装的HOOK的类型
    HOOKPROC lpfn,    //HOOK的回调函数
    HINSTANCE hMod,   //进程
    DWORD dwThreadId  //程序的线程,如果为0则是全局HOOK
);

熟悉了SetWindowsHookEx函数,我们就能开始我们的工作,挂钩进程。
首先打开Delphi,创建一个DLL工程(DLL Wizard)。然后创建一个新的单元(Unit1)。
首先在单元的 interface 下面声明要用到的函数。


var
    OldHook:HHOOK;
    Histance:HISTANCE;
    OldProc:FARPROC;


我们的第一个函数是安装HOOK,让我们看一下代码:

Function SetHook:Boolean;stdcall;
begin
  OldHook:=SetWindowsHookEx(WH_KEYBOARD,@HookProc,Histance,0);
  if (OldHook=0) then exit else Result:=True;
end;

这样的话就安装一个全局的键盘HOOK,HOOK的方法还有很多,在此就不一一列举了。

下面介绍一下回调函数:


Function HookProc(nCode,wParam,lParam:Integer);Integer;stdcall;
begin
  Result:=CallNextHookEx(OldHook,nCode,wParam,lParam);
end;

这样的话就完成了对进程的挂钩。可是挂上钩我们的工作并没结束,相反,我们的工
作才刚刚开始。钩子的作用是帮我们把DLL注入到别人的进程空间。现在我们的DLL已
经在别人的进程空间内。所以,我们就可以做我们想做的事。


下面介绍一下Windows的子类化处理。

大家都知道,在windows里不管你做了什么事,都会向windows发送一条消息,然后由
Windows作出相应的处理后才会返回给传送消息的应用程序。
那大家会问:“HOOK不是已经拦截了windows消息了吗?”

是啊,那也要看是拦截了什么消息,就如上面我们写的WH_KEYBOARD,我们拦截了键盘
消息,我们可以在按下任何一个按键的时候做出处理。消息的种类有很多。
可是我们今天要讲的是windows的子类化处理,这又是一门新的技术。
不废话了,这就开始。^_^

相信大家都见过两这个API:GetWindowsLong 和 SetWindowLong;
可能你们会说,这些不是处理窗口消息的吗?对,这就是我们要用到的API。

接下来让我们看一下这些API的参数。
LONG GetWindowLong(
    HWND hWnd,    //窗体的句柄
    int nIndex    //欲取回的信息,可参照下表
);
 nIndex的值可以是下列任何一个
GWL_EXSTYLE 扩展窗口样式
GWL_STYLE 窗口样式
GWL_WNDPROC 该窗口的窗口函数的地址
GWL_HINSTANCE 拥有窗口的实例的句柄
GWL_HWNDPARENT 该窗口之父的句柄。不要用SetWindowWord来改变这个值
GWL_ID 对话框中一个子窗口的标识符
GWL_USERDATA 含义由应用程序规定
DWL_DLGPROC 这个窗口的对话框函数地址
DWL_MSGRESULT 在对话框函数中处理的一条消息返回的值
DWL_USER 含义由应用程序规定


也许大家会注意到 GWL_WNDPROC 这个参数。没错,我们子类处理就是要用到这个参数。
代码如下:
OldProc:=GetWindowLong(hWnd,GWL_WNDPROC);

这样我们的OldProc就指向窗体的窗口函数地址;
既然得到了窗口函数地址,那么就修改到我们自定义的消息处理地址里吧。
下面要用到SetWindowLong函数了。
LONG SetWindowLong(
    HWND hWnd,      //指定窗口句柄
    int nIndex,     //和GetWindowLong的nIndex一样
    LONG dwNewLong  //新的消息处理地址
);

代码如下:
SetWindowLong(hWnd,GWL_WNDPROC,Longint(@WinProc));

这样就把指定窗体的消息转到了我们的函数内执行;

回调函数如下:
Function WinProc(Hwnd,Msg,wParam,lParam:longint):LRESULT; stdcall;
begin
Result:=CallWindowProc(OldProc,Hwnd,Msg,wParam,lParam);
end;
这里的Msg就是窗口的消息,后面赋上消息表。

小节:文章写到这里,相信大家应该明白HOOK和子类是什么回事吧。下面再解释一下
为什么不在HOOK里处理消息。前面已经提到,HOOK是帮助我们把DLL注入别人的进程。
而windows子类处理只能在进程内处理消息,所以只有我们到了别人的进程空间内,才
能做出消息屏蔽的动作。这样说大家都能明白了吧。

    好了,就不废话了。下面赋上源代码。希望大家多多支持! ^_^
    (复制就可以用的哦)

##########################################################################
unit Unit1;

interface
uses windows;
var
    OldHook:HHOOK;        //用来保存HOOK的返回值
    OldProc:FARPROC;      //用来指向窗口消息


    Function SetHook:Boolean;stdcall;
    Function HookProc(nCode,wParam,lParam:Integer):Integer;stdcall;
    Function WinProc(Hwnd,Msg,wParam,lParam:longint):LRESULT; stdcall;
   
implementation
{###################################################################################}
//安装HOOK
Function SetHook:Boolean;stdcall;
var
    Histance:Cardinal;
begin
  //安装HOOK
  OldHook:=SetWindowsHookEx(WH_KEYBOARD,@HookProc,Histance,0);
  if (OldHook=0) then exit else Result:=True;
end;

{###################################################################################}
//HOOK回调函数
Function HookProc(nCode,wParam,lParam:Integer):Integer;stdcall;
var
WinStr:HWND;
begin
  //设置热键
  if (wParam=VK_F12) then
    begin
      WinStr:=FindWindow(nil,''''窗口的标题文字'''');
      OldProc:=FARPROC(GetWindowLong(WinStr,GWL_WNDPROC));
      SetWindowLong(WinStr,GWL_WNDPROC,Longint(@WinProc));
    end;
  //将HOOK传递给Windows处理
  Result:=CallNextHookEx(OldHook,nCode,wParam,lParam);
end;

{###################################################################################}
//自定义Windows消息处理函数
Function WinProc(Hwnd,Msg,wParam,lParam:longint):LRESULT; stdcall;
begin
{在这做出对消息的处理

  case Msg of
    WM_ACTIVATEAPP:exit;
    WM_ACTIVATE:exit;
    WM_KILLFOCUS:exit;
    WM_SETFOCUS:exit;
  end;
上面这些消息是窗口失去焦点和获得焦点的屏蔽
}
//将窗口消息传递给Windows处理
Result:=CallWindowProc(OldProc,Hwnd,Msg,wParam,lParam);
end;
end.

##########################################################################

 

附录:消息类型(搜集整理于互联网上)


##########################################################################

WM_NULL = $0000;
WM_CREATE = $0001;
应用程序创建一个窗口
WM_DESTROY = $0002;
一个窗口被销毁
WM_MOVE = $0003;
移动一个窗口
WM_SIZE = $0005;
改变一个窗口的大小
WM_ACTIVATE = $0006;
一个窗口被激活或失去激活状态;
WM_SETFOCUS = $0007;
获得焦点后
WM_KILLFOCUS = $0008;
失去焦点
WM_ENABLE = $000A;
改变enable状态
WM_SETREDRAW = $000B;
设置窗口是否能重画
WM_SETTEXT = $000C;
应用程序发送此消息来设置一个窗口的文本
WM_GETTEXT = $000D;
应用程序发送此消息来复制对应窗口的文本到缓冲区
WM_GETTEXTLENGTH = $000E;
得到与一个窗口有关的文本的长度(不包含空字符)
WM_PAINT = $000F;
要求一个窗口重画自己
WM_CLOSE = $0010;
当一个窗口或应用程序要关闭时发送一个信号
WM_QUERYENDSESSION = $0011;
当用户选择结束对话框或程序自己调用ExitWindows函数
WM_QUIT = $0012;
用来结束程序运行或当程序调用postquitmessage函数
WM_QUERYOPEN = $0013;
当用户窗口恢复以前的大小位置时,把此消息发送给某个图标
WM_ERASEBKGND = $0014;
当窗口背景必须被擦除时(例在窗口改变大小时)
WM_SYSCOLORCHANGE = $0015;
当系统颜色改变时,发送此消息给所有顶级窗口
WM_ENDSESSION = $0016;
当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,
通知它对话是否结束
WM_SYSTEMERROR = $0017;
WM_SHOWWINDOW = $0018;
当隐藏或显示窗口是发送此消息给这个窗口
WM_ACTIVATEAPP = $001C;
发此消息给应用程序哪个窗口是激活的,哪个是非激活的;
WM_FONTCHANGE = $001D;
当系统的字体资源库变化时发送此消息给所有顶级窗口
WM_TIMECHANGE = $001E;
当系统的时间变化时发送此消息给所有顶级窗口
WM_CANCELMODE = $001F;
发送此消息来取消某种正在进行的摸态(操作)
WM_SETCURSOR = $0020;
如果鼠标引起光标在某个窗口中移动且鼠标输入没有被捕获时,就发消息给某个窗口
WM_MOUSEACTIVATE = $0021;
当光标在某个非激活的窗口中而用户正按着鼠标的某个键发送此消息给当前窗口
WM_CHILDACTIVATE = $0022;
发送此消息给MDI子窗口当用户点击此窗口的标题栏,或当窗口被激活,移动,改变大小
WM_QUEUESYNC = $0023;
此消息由基于计算机的训练程序发送,通过WH_JOURNALPALYBACK

[1] [2] [3]  下一页


[系统软件]windows下Apache+php+mysql的安装与配置图解  [操作系统]在Windows中玩转Linux操作系统
[操作系统]死马还当活马医:6种方法挽救Windows系统  [聊天工具]四大更新 Windows Live Msn 8.1评测
[聊天工具]Windows Live Messenger最新0683版亮相_联络工具_…  [聊天工具]Windows Live Mail招人爱的N个理由_联络工具_Wind…
[聊天工具]Windows Live Mail Desktop多图欣赏_联络工具_Win…  [聊天工具]OE老了 微软开发新邮件客户端取而代之_联络工具
[聊天工具]Windows Live Messenger中文版试用报告(一)__天极…  [聊天工具]Windows Live Messenger 8 Beta1高清图赏__天极Ye…
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台