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

2020-04-15 00:39

首先我们先看一下安装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;


Delphi 中的消息钩子函数和Windows子类处理.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:“三元悖论”视角下的中国汇率制度选择 - 图文

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: