关于拦截编辑框中EM_REPLACESEL消息的HOOK问题

qq32822848 2006-10-10 08:54:53
现在,有一个程序中有一个EDIT编辑框,而我想自己编一个程序,利用Hook函数拦截该Edit编辑框中的EM_REPLACESEL消息并获取该消息中的值。程序用Delphi编写。


首先安装Hook
SetWindowsHookEx(int idHook,HOOKPROC lpfn, INSTANCE hMod,DWORD dwThreadId)
  这里,idHook应该给什么消息类型

然后,写钩子子程
HookProc(int nCode ,WPARAM wParam,LPARAM lParam)
  这里的代码中如何拦截EM_REPLACESEL消息和获取EM_REPLACESEL中的值

该程序中使用的钩子是全局的钩子,然后拦截指定的程序中的消息

我在网上找过很多关于钩子的资料,但全部都是关于键盘和鼠标的例子,本人刚学Delphi不久,因突发奇想,想把单位中的一个设备的终端程序修改,但又不清楚该程序COM口的协议,所以只能拦截该程序中编辑框返回的信息,而我用SPY查看过,该程序中每次有返回信息时,都是出现EM_REPLACESEL消息,如果有人知道,可否给我一点提示,主要的是HookProc中的代码该如果写,谢谢大家了。
...全文
554 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq32822848 2006-10-12
  • 打赏
  • 举报
回复

3:这个是我自己写的,上两条是文中的源代码,没有DLL模块,所以只能自己添加
library hook;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
SysUtils,
Classes,
wdSpyCommon in 'wdSpyCommon.pas',
wdMsgSpy in 'wdMsgSpy.pas';

{$R *.res}

exports
StartSpyMessage,
StopSpyMessage;

begin
end.

然后,生成DLL文件Hook.dll

接着,我做了一个工程文件,调用Hook.dll的两个函数,
其中窗体中有一个Edit控件,两个button控件,

第一个button控件执行代码为
  if StartSpyMessage(监视窗口的句柄,把消息发送到窗口的句柄)then
.....

  \\监视窗口的句柄:在代码中用代码获得我要监视的窗口句柄并将值做为参数传递给
           hook.dll中的执行代码
  \\把消息发送到窗口的句柄:就是本程序中的Edit的句柄

第二个button控件执行代码为
  StopSpyMessage


执行通过,并提示Hook安装成功,可就是没能够拦截任何消息
qq32822848 2006-10-12
  • 打赏
  • 举报
回复
2:
unit wdSpyCommon;
{*******************************************
* brief: 消息Spy用到的数据结构等的声明文件
* autor: linzhenqun
* date: 2005-9-25
* email: linzhengqun@163.com
* blog: http://blog.csdn.net/linzhengqun
********************************************}
interface
uses
Windows, Messages;
resourcestring
err_ProcInvalid = 'the Message spy procedure are invalid.';
err_ShareMem = 'could not create share memory.';
const
Msg_Null_Value = 0;
Msg_Type_Sent = 1;
Msg_Type_Post = 2;
Msg_Type_Return = 3;
type
{ 受监察的消息结构 }
PMsgInfo = ^TMsgInfo;
TMsgInfo = packed record
hwnd: HWND;
message: UINT;
wParam: WPARAM;
lParam: LPARAM;
time: DWORD;
pt: TPoint;
lResult: LRESULT;
MsgType: UINT;
end;
implementation
end.
qq32822848 2006-10-12
  • 打赏
  • 举报
回复
好不容易,找到一个用Delphi写的SPY程序,虽然是文字,没有源代码,我自己修改了一下,却还是没成功,文中介绍说该代码可以拦截消息,和C++里的SPY++功能差不多,DLL文件也正常编译成功了,而且调用该DLL时也通过了,可就是拦截不了消息,下面我把该程序贴出来

首先是DLL文件,
1:
unit wdMsgSpy;
{*******************************************
* brief: 消息Spy的SDK
* autor: linzhenqun
* date: 2005-9-24
* email: linzhengqun@163.com
* blog: http://blog.csdn.net/linzhengqun
********************************************}
interface
uses
Messages, Windows, Classes, SysUtils, wdSpyCommon;
const
MApingFile_Name = 'MsgSpy_FC819A73-2718-47E2-BF78-6810562CDA65';
type
//共享内存
PShareMem = ^TShareMem;
TShareMem = record
HRevWnd: THandle; //存放接收消息的窗口句柄
HWndSpy: THandle; //被监察的窗口句柄
end;
{ 开始监察消息,AHSpyWnd为受监察的窗口,AHRevWnd为接收监察到的消息的窗口 }
function StartSpyMessage(AHSpyWnd, AHRevWnd: THandle): Boolean; stdcall;
{ 停止监察消息 }
procedure StopSpyMessage; stdcall;
var
HMsgProc, HWndProc, HWndRetProc: THandle; //相应钩子的句柄
PSMem: PShareMem; //共享内存块
hMApFile: THandle; //内存映射文件的句柄。
implementation

//将截获的消息结构发送到目标窗口
procedure SendData(AMsgInfo: PMsgInfo); stdcall;
var
pcds: PCopyDataStruct;
begin
New(pcds);
pcds^.cbData := SizeOf(TMsgInfo);
pcds^.lpData := AMsgInfo;
SendMessage(PSMem^.HRevWnd, WM_COPYDATA, 0, LongInt(pcds));
Dispose(pcds);
end;
{ WH_GETMESSAGE的钩子过程 }
function GetMsgProc(code: Integer; wP: WPARAM; lP: LPARAM): LRESULT; stdcall;
var
LMsgInfo: PMsgInfo;
begin
{只有截获的消息的窗口句柄等于被监察的窗口句柄,才进行下一步,
接着,当被监察的窗口不是接收消息的窗口时执行下一步操作;或者当被监察窗口
就是接收消息的窗口时,截获的消息不是WM_CopyData,执行下一步。
这么做是为了避免进入发送消息与截获消息的死循环}
if code = HC_ACTION then
if (PMsg(lp)^.hwnd = PSMem^.HWndSpy) then
if ((PSMem^.HWndSpy = PSMem^.HRevWnd) and (PMsg(lp)^.message <> WM_COPYDATA))
or (PSMem^.HWndSpy <> PSMem^.HRevWnd) then
begin
New(LMsgInfo);
LMsgInfo.hwnd := PMsg(lp)^.hwnd;
LMsgInfo.message := PMsg(lp)^.message;
LMsgInfo.wParam := PMsg(lp)^.wParam;
LMsgInfo.lParam := PMsg(lp)^.lParam;
LMsgInfo.pt := PMsg(lp)^.pt;
LMsgInfo.time := PMsg(lp)^.time;
LMsgInfo.lResult := Msg_Null_Value;
LMsgInfo.MsgType := Msg_Type_Post;
SendData(LMsgInfo);
Dispose(LMsgInfo);
end;
Result := CallNextHookEx(HMsgProc, code, wP, lP);
end;

{ WH_CALLWNDPROC的钩子过程 }
function CallWndProc(code: Integer; wP: WPARAM; lP: LPARAM): LRESULT; stdcall;
var
LMsgInfo: PMsgInfo;
begin
if code = HC_ACTION then
if (PCWPStruct(lp)^.hwnd = PSMem^.HWndSpy) then
if ((PSMem^.HWndSpy = PSMem^.HRevWnd) and (PCWPStruct(lp)^.message <> WM_COPYDATA))
or (PSMem^.HWndSpy <> PSMem^.HRevWnd) then
begin
New(LMsgInfo);
LMsgInfo^.hwnd := PCWPStruct(lp)^.hwnd;
LMsgInfo^.message := PCWPStruct(lp)^.message;
LMsgInfo^.wParam := PCWPStruct(lp)^.wParam;
LMsgInfo^.lParam := PCWPStruct(lp)^.lParam;
LMsgInfo^.pt := Point(0, 0);
LMsgInfo^.time := Msg_Null_Value;
LMsgInfo^.lResult := Msg_Null_Value;
LMsgInfo^.MsgType := Msg_Type_Sent;
SendData(LMsgInfo);
Dispose(LMsgInfo);
end;
Result := CallNextHookEx(HWndProc, code, wP, lP);
end;

{ WH_CALLWNDPROCRET的钩子过程 }
function CallWndRetProc(code: Integer; wP: WPARAM; lP: LPARAM): LRESULT; stdcall;
var
LMsgInfo: PMsgInfo;
begin
if code = HC_ACTION then
if (PCWPRetStruct(lp)^.hwnd = PSMem^.HWndSpy) then
if ((PSMem^.HWndSpy = PSMem^.HRevWnd) and (PCWPRetStruct(lp)^.message <> WM_COPYDATA))
or (PSMem^.HWndSpy <> PSMem^.HRevWnd) then
begin
New(LMsgInfo);
LMsgInfo^.hwnd := PCWPRetStruct(lp)^.hwnd;
LMsgInfo^.message := PCWPRetStruct(lp)^.message;
LMsgInfo^.wParam := PCWPRetStruct(lp)^.wParam;
LMsgInfo^.lParam := PCWPRetStruct(lp)^.lParam;
LMsgInfo^.pt := Point(0, 0);
LMsgInfo^.time := Msg_Null_Value;
LMsgInfo^.lResult := PCWPRetStruct(lp)^.lResult;
LMsgInfo^.MsgType := Msg_Type_Return;
SendData(LMsgInfo);
Dispose(LMsgInfo);
end;
Result := CallNextHookEx(HWndRetProc, code, wP, lP);
end;

function StartSpyMessage(AHSpyWnd, AHRevWnd: THandle): Boolean;
begin
Result := False;
try
if (HMsgProc <> 0) or (HWndProc <> 0) or (HWndRetProc <> 0) then
Exit;
PSMem^.HWndSpy := AHSpyWnd;
PSMem^.HRevWnd := AHRevWnd;
HMsgProc := SetWindowsHookEx(WH_GETMESSAGE, @GetMsgProc, HInstance, 0);
HWndProc := SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc, HInstance, 0);
HWndRetProc := SetWindowsHookEx(WH_CALLWNDPROCRET, @CallWndRetProc, HInstance, 0);
if (HMsgProc = 0) or (HWndProc = 0) or (HWndRetProc = 0) then
begin
StopSpyMessage;
Exit;
end;
except
Exception.Create(err_ProcInvalid);
end;
Result := True;
end;

procedure StopSpyMessage;
begin
UnhookWindowsHookEx(HMsgProc);
UnhookWindowsHookEx(HWndProc);
UnhookWindowsHookEx(HWndRetProc);
HMsgProc := 0;
HWndProc := 0;
HWndRetProc := 0;
end;

initialization
//创建共享内存块
hMApFile := OpenFileMApping(FILE_MAP_ALL_ACCESS, False, MApingFile_Name);
if hMApFile = 0 then
hMApFile := CreateFileMApping($FFFFFFFF, nil, PAGE_READWRITE, 0,
SizeOf(TShareMem), MApingFile_Name);
PSMem := MApViewOfFile(hMApFile, FILE_MAP_WRITE or FILE_MAP_READ, 0, 0, 0);
if PSMem = nil then
begin
CloseHandle(hMApFile);
Exception.Create(err_ShareMem);
end;

finalization
//释放共享内存块
UnMApViewOfFile(PSMem);
CloseHandle(hMApFile);
end.
光明山人 2006-10-12
  • 打赏
  • 举报
回复
SetWindowLong(wnd, GWL_WNDPROC, Integer(@HeaderProc)) 不能跨进程。

Remarks
The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.

楼主的问题只能用Hook DLL,不过我自己没实践过,只希望楼主继续努力。

--
http://www.agui.googlepages.com
mailto: agui.cn(a)gmail.com
xzhifei 2006-10-11
  • 打赏
  • 举报
回复
Wnd1:=FindWindow(PChar(FormName), PChar(FormCaption));
Wnd1:=FindWindowEx(Wnd1,Hdl,'TEdit', nil);

------------------------------------------------------- 本回复由大傻的破玩意儿【CSDN's forum Explorer】完成! 大傻的破玩意儿,今天你用了木有 !! 软件功能强大,速度超快!!支持中... 软件下载地址:http://CoolSlob.ys168.com
qq32822848 2006-10-10
  • 打赏
  • 举报
回复
不是一个进程,是两个进程,我是想拦截其他程序中的EM_REPLACESEL消息
不过,同一个进程好象是可以拦截的,我在资料里看到过,
里面写着,如果是拦截全局的消息,必须写在Dll中,如果是同一进程,就可以不用Dll
ly_liuyang 2006-10-10
  • 打赏
  • 举报
回复
不同进程是Hook不了的
需要进程注入
xzhifei 2006-10-10
  • 打赏
  • 举报
回复
应该是可以的,我做了一个测试,可以HOOK到,方法就是替换它的消息处理事件,如下:

function HeaderProc(wnd: HWND; Msg: Cardinal; wParam: wParam; lParam: lParam): Longint;
stdcall;
begin

Result := CallWindowProc(Pointer(GetWindowLong(wnd, GWL_USERDATA)),
wnd, Msg, wParam, lParam);
if Msg = WM_USER + 47360 {EM_REPLACESEL} then
begin
Form1.Memo1.Lines.Add('Edit框更改...');
end;
// Form1.Memo1.Lines.Add(Format('MSG: %d', [Msg]));

end;


procedure TForm1.Button1Click(Sender: TObject);
var
wnd: HWND;
buffer: array[0..80] of Char;
oldProc: Integer;
begin
wnd := Edit1.Handle;
if wnd <> 0 then
begin
begin
Memo1.Lines.Add('');
oldproc := GetWIndowLong(wnd, GWL_WNDPROC);
if GetWindowLong(wnd, GWL_USERDATA) <> 0 then
raise Exception.Create('Cannot sublcass header, USERDATA already in use');
SetWIndowLong(wnd, GWL_USERDATA, oldproc);
SetWindowLong(wnd, GWL_WNDPROC, Integer(@HeaderProc));
end;
end;


end;


------------------------------------------------------- 本回复由大傻的破玩意儿【CSDN's forum Explorer】完成! 大傻的破玩意儿,今天你用了木有 !! 软件功能强大,速度超快!!支持中... 软件下载地址:http://CoolSlob.ys168.com

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧