能否向其它的.exe执行程序发消息,控制其运行?(80分)

  • 主题发起人 主题发起人 victor
  • 开始时间 开始时间
V

victor

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在有其它人写的.exe程序,
而且只有运行程序,无原代码。
假设.exe程序在95/98下运行,我能编程控制
它的一些运行行为吗?比如说由我的程序
来缴获键盘或鼠标输入,再由我的程序有选择的
将输入传给该.exe程序?
 
你可以用keybd_event函数来模拟键盘输入,例如:

keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), 0 , 0 ); // down arrow key down

keybd_event( VK_DOWN, MapVirtualKey( VK_DOWN, 0 ), KEYEVENTF_KEYUP , 0 ); // down arrow key up
注意:每一个 Key Down 事件都应该跟有相应的 Key Up

事件。否则将会搞乱了按键状态数组)
 
用你的程序替换它的WndProc来处理消息

TWndProc = Function( Handle: hWnd; Msg: word;
wParam: word; lParam: Longint ) : Longint;

//如果已经找到他人程序的WndHandle, 可以替换他的WndProc
Procedure TForm1.OverrideWndProc;
Begin
OldWndProc := Pointer ( GetWindowLong ( fEditForm.Handle, GWL_WNDPROC ) ); //将他人的WndProc保存到OldWndProc
SetWindowLong ( WndHandle, GWL_WNDPROC, Longint ( @MyWndProc ) ); //替换成你的
InvalidateRect ( WndHandle, Nil, True );
End;
//恢复他人的WndProc
Procedure TForm1.RestoreFormWndProc;
Begin
SetWindowLong ( WndHandle, GWL_WNDPROC, Longint ( OldWndProc ) );
InvalidateRect ( WndHandle, Nil, True );
End;
//在你的WndProc中只对于你感兴趣的消息进行处理, 其他的消息可以用下面的
//CallWindowProc方法调用他原有的消息处理
Function MyWndProc( Handle : hWnd; Msg : Word; wParam : Word;
lParam : LongInt ) : LongInt; stdcall;
begin
case Msg of
WM_LButtonDown:
WM_RButtomDown:
WM_MouseMove:
.....
else
Result := CallWindowProc(OldWndProc, Handle, Msg, wParam, lParam );
end;
end;
 
用DLL中的HOOK可能是比较理想的方法了.加一个系统范围的键盘HOOK,然后在
HOOK函数中判断输入焦点是否在需要监视的应用程序,如果是,就处理之.

替换窗口函数的方法可能有问题,因为不在一个进程空间,安装的窗口函数可能
不能运行.我曾经在Win32s上试过替换其它进程的窗口函数,但是没有成功.不
知现在的Win32如何.

BTW:系统范围的HOOK必须在DLL中!
 
谢谢各位的解答!

是这样的:
1。对于HuiZhang的建议,我只知道该EXE程序的名字与功能,
不知道其WndHandle, 我应该如何办?有什么办法能
获取吗?

2。SendKey,keybd_event能把鼠标/键盘输入传给某个exe程序吗?
 
1.可以用vc(bc中有没有我就不知道了)等提供的工具,可以察看窗口的类名和标题
2.sendmessage 可以向该窗口发送任何消息.
 
给你一个简单的例子:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
form1.Timer1.Enabled:=true;

end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
keybd_event( byte('A'), MapVirtualKey( byte('A'), 0 ), 0 , 0 ); // 'A' down

keybd_event( byte('A'), MapVirtualKey( byte('A'), 0 ), KEYEVENTF_KEYUP , 0 ); // 'A' up
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
form1.Timer1.Enabled:=false;
end;

end.

按下BUTTON1 后,你可以把键盘焦点置于任何一个需要键盘输入的应用程序窗体上,就可以看到结果了,鼠标输入同此理.
 
现在是这样的,我用BC4.5中的work shop把那个.exe程序
进行了分析,把它中间的一下菜单命令解析了出来,
比如说: 菜单项的ID,等, 按理说我只要用
sendmessage命令向该.exe发送于菜单项ID对应的
message就行了, 但没有用?
有谁知道为什么吗?

谢谢!!!

(我猜该.exe程序是用BC或VC写的)
 
应该向所有的窗口发送WM_COMMAND(用NULL句柄)。
当然,这可能引发问题,但是可以完成任务(我就这么做过)。
 
最安全,最可靠的方法:用Journal Playback Windows钩子
将鼠标和键盘输入受到应用的任意窗口。
为什么不能仅用SendMessage函数来达到同样的目的呢?
这是因为,Windows的消息队列是一个有限的资源,在任意时刻只能处理一定数目
的信息。因此每一次往消息队列里增加一个消息,都有可能使该缓冲溢出。正确的
方法是创建一个Journal Playback Windows钩子,让Windows来决定什么时候允
许发送新的消息。

以上文字载自《Delphi3开发使用手册》755页,附例子一个,有六页16开的纸,
太长了,晓茶不好敲进去。
 
对于菜单项的消息要发送WM_Command消息
WM_COMMAND
wNotifyCode = HIWORD(wParam); // notification code
wID = LOWORD(wParam); // item, control, or accelerator identifier
hwndCtl = (HWND) lParam; // handle of control

也可以直接用SendKey函数发送菜单项的快捷键.
 
茶叶蛋:《Delphi3开发使用手册》是本什么样的书啊?
给介绍一下
 
to yifeng:
>《Delphi3开发使用手册》是本什么样的书啊?给介绍一下
是一本手册类型的书,用作参考很不错,如果想拿来入门或者进阶恐怕
不是很好。

不好意思,前些天没有看见。 :-)
 
victor啊,这个问题是不是该结束了呢?
 
victor:

这个问题已经很长时间没有人参加讨论,为保持版面
整洁,节约网友时间,请提问者采取必要处理措施。
关于本版管理细则,请参见<a href="http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=111927">这个</a>问题。如两天
内提问者没有响应,我将采取强制措施。

如有管理建议,请到<a href="http://www.gislab.ecnu.edu.cn/delphibbs/DispQ.asp?LID=111927">这里</a>提出。谢谢!
 
多人接受答案了。
 
后退
顶部