Delphi 控制外部程序

最近做一个项目,需要从外部控制挰序,好比做一个外挂,要获取游戏里各个控件的句柄,然后对它进行操作。在网上查了查,这方面的例子无一例外都是C++的,找不到Delphi的,在几个网站上问了,回答的人都说不知道,并且推荐我用C++进行开发,难道Delphi真的不能对外部程序操作?

经过一天的努力,我证明了Delphi也是可以做到的,并且比C++做起来更方便,我把它做成一个控件,以便随时拖出来就用。

unit RaOuterControls;

interface

uses
SysUtils, Classes, Windows, TlHelp32;

type
TProcessInfo = record
    pHandle: Cardinal;
    pClassName: string;
    pText: string;
end;

type
TOnSendMessage = procedure(Sender: TObject; SndMsgResult: Cardinal) of object;
TOnWindowChange = procedure(Sender: TObject) of object;

type
TRaOuterControls = class(TComponent)
private
    fProcessHandle: THandle;
    fTextList: TStringList;
    fHandleList: TStringList;
    fClassList: TStringList;
    fWindowCaption: string;
    fSM: Cardinal;
    fSLP: Cardinal;
    fSWP: Cardinal;
    fSMH: THandle;
    fOnSendMessage: TOnSendMessage;
    fOnWindowChange: TOnWindowChange;
    procedure SetProcessHandle(const Value: THandle);
    procedure SetWindowCaption(const Value: string);
protected
    //function FindExeHandle(AExeName: string): THandle;
public
    constructor Create(AOwner: TComponent); override;
    function GetProcessControlInfo(index: Integer): TProcessInfo;
    procedure SendMessageToControl; overload;
    procedure SendMessageToControl(hWnd: THandle; Msg: Cardinal; WParam: Cardinal; LParam: Cardinal); overload;
published
    property OnSendMessage: TOnSendMessage read fOnSendMessage write fOnSendMessage;
    property OnWindowChange: TOnWindowChange read fOnWindowChange write fOnWindowChange;
    property SndMsgHandle: THandle read fSMH write fSMH;
    property SndMessage: Cardinal read fSM write fSM;
    property SndLParam: Cardinal read fSLP write fSLP;
    property SndWParam: Cardinal read fSWP write fSWP;
    property ProcessHandle: THandle read fProcessHandle write SetProcessHandle;
    property HandleList: TStringList read fHandleList;
    property ClassList: TStringList read fClassList;
    property TextList: TStringList read fTextList;
    property WindowCaption: string read fWindowCaption write SetWindowCaption;
end;

var
IHandleList: TStringList;
IClassList: TStringList;
ITextList: TStringList;

function EnumChildWndProc(AhWnd: LongInt; AlParam: LParam): boolean; stdcall;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Rarnu Components', [TRaOuterControls]);
end;

function EnumChildWndProc(AhWnd: LongInt;
AlParam: LParam): boolean; stdcall;
var
WndClassName: array[0..511] of Char;
WndCaption: array[0..511] of Char;
begin
GetClassName(AhWnd, WndClassName, 512); //获取控件名称
GetWindowText(AhWnd, WndCaption, 512); //获取控件标题
IHandleList.Add(IntToStr(AhWnd));
IClassList.Add(string(WndClassName));
ITextList.Add(string(WndCaption));
result := true;
end;

{ TRaOuterControls }

constructor TRaOuterControls.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fTextList := TStringList.Create;
fTextList.Clear;
fHandleList := TStringList.Create;
fHandleList.Clear;
fClassList := TStringList.Create;
fClassList.Clear;
IHandleList := TStringList.Create;
IHandleList.Clear;
IClassList := TStringList.Create;
IClassList.Clear;
ITextList := TStringList.Create;
ITextList.Clear;
end;

function TRaOuterControls.GetProcessControlInfo(
index: Integer): TProcessInfo;
var
piInfo: TProcessInfo;
begin
piInfo.pHandle := 0;
piInfo.pClassName := '';
piInfo.pText := '';
if fHandleList.Count - 1 < index then
begin
    result := piInfo;
    Exit;
end;
piInfo.pHandle := StrToInt(fHandleList.Strings[index]);
piInfo.pClassName := fClassList.Strings[index];
piInfo.pText := fTextList.Strings[index];
result := piInfo;
end;

procedure TRaOuterControls.SendMessageToControl;
var
SndResult: Cardinal;
begin
SndResult := SendMessage(fSMH, fSM, fSWP, fSLP);
if Assigned(OnSendMessage) then
    OnSendMessage(self, SndResult);
end;

procedure TRaOuterControls.SendMessageToControl(hWnd: THandle; Msg, WParam,
LParam: Cardinal);
var
SndResult: Cardinal;
begin
SndResult := SendMessage(hWnd, Msg, WParam, LParam);
if Assigned(OnSendMessage) then
    OnSendMessage(self, SndResult);
end;

procedure TRaOuterControls.SetProcessHandle(const Value: THandle);
begin
fProcessHandle := Value;
IHandleList.Clear;
IClassList.Clear;
ITextList.Clear;
if fProcessHandle <> 0 then EnumChildWindows(fProcessHandle, @EnumChildWndProc, 0);
fTextList := ITextList;
fHandleList := IHandleList;
fClassList := IClassList;
if Assigned(OnWindowChange) then
    OnWindowChange(self);
end;

procedure TRaOuterControls.SetWindowCaption(const Value: string);
begin
fWindowCaption := Value;
ProcessHandle := FindWindow(nil, PChar(fWindowCaption));
end;

end.









相信你一定看明白了,EnumChildWndProc其实是一个回调函数,它本身就拥有递归的性质,result:=true表明它可以继续回调,直到条件不成立为止。利用内置API可以方便的完成类名和控件标题的获取,而用C++的话,此时必须先对记录进行声明,这个声明将花费大量的代码。

控件做完后,就开始做一个实例,很简单,我想把我输入在Memo里面的文本直接移动到记事本里,实现代码如下:

unit Unit1;

interface

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

type
TForm1 = class(TForm)
    RaOuterControls1: TRaOuterControls;
    Label1: TLabel;
    Timer1: TTimer;
    Label2: TLabel;
    Memo1: TMemo;
    Button1: TButton;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
private
    { Private declarations }
public
    { Public declarations }
end;

var
Form1: TForm1;
NotePadHandle:THandle;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
begin
NotePadHandle:=FindWindow(nil,'无标题 - 记事本');
if NotePadHandle<>0 then
    self.Label1.Caption:='新记事本已打开'
else
    self.Label1.Caption:='请打开一个空的记事本';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
self.Timer1Timer(self);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
if NotePadHandle=0 then
begin
    ShowMessage('请打开一个新的记事本');
    Exit;
end;
self.RaOuterControls1.ProcessHandle:=NotePadHandle;
//self.ListBox1.Items:=self.RaOuterControls1.ClassList;
for i:=0 to self.RaOuterControls1.ClassList.Count-1 do
begin
    if self.RaOuterControls1.ClassList.Strings[i]='Edit' then
    begin
      self.RaOuterControls1.SendMessageToControl
      (StrToInt(RaOuterControls1.HandleList.Strings[i]),WM_SETTEXT,
      0,Cardinal(PChar(memo1.Lines.Text)));
      Exit;
    end;
end;
end;

end.

除去大部分系统生成的代码外,几乎都是对控件的操作,这里提一下,虽然PCHAR保留过程返回的值是AnsiString,但是却可以用数值形转换,这里用Cardinal进行了转换,但是实际用中,个人认为还是用LongInt转换比较好,LongInt可以与其他开发平台兼容,而Cardinal仅局限于delphi中。它的原理是把文本转成整型数组的形式存到内存中,然后通过SendMessage函数进行发送。

在遍历中,由于事先知道控件的名称,所以直接用了判断,如果不知道的话还需进一步判断。我在这个控件中封装了GetProcessControlInfo函数,它返回选中的一个记录,使用起来会更加的方便。

测试一下做好的程序,果然,原来在窗体上的文本已经跑到记事本里面去了。

源码下载:http://rarnu.ys168.com/

Delphi技术目录内->外部程序操作.rar

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DELPHI专题文档-程序应用 更改Windows95的墙纸 类似于VB中的doevents功能 DELPHI下的多线程程序设计 用Delphi 3.0编制MP3音乐点歌台 用Delphi开发windows95屏幕保护预览程序 判断一个程序是否dos版本 Delphi自定义消息应用一例 显示密码编辑框中的密码 也谈Delphi中的日期输入 用修改文件时间的方法来加密文件 在DELPHI中处理时间 在Delphi中用拼音首字符序列来实现检索功能 用Delphi创建Internet快捷方式 用Delphi实现远程屏幕抓取 资源文件在DELPHI中的使用 在DELPHI应用程序中使用DLL 为DELPHI应用程序制作安装程序 用注册表对Delphi程序进行加密 在Delphi程序中操作注册表 鼠标和键盘控制 如何为Delphi程序添加事件和事件处理器 在Delphi应用程序中拖动控件 用DEPHI为应用软件建立注册机制 用Delphi创建临时文件 Delphi 5快速创建控制面板程序 Delphi经验技巧集锦 Microsoft Agent技术在Delphi中的应用 怎样建立简单的任务栏应用程序 判断一个程序是否dos版本 利用Delphi 5中调用Excel 97 利用Dll实现通用密码验证框 如何访问一个进程的内存空间 用Delphi 5.0编写OLE程序操纵Excel 用Delphi编写DLL实现动态改变分辨率 在delphi中使用flash控件 在Delphi中运用QuickReport实现多栏列印 控制INI文件几法 转让控制权 得到执行程序的目录 打开已注册文件 得到Windows用户名和序列号 关闭外部应用程序 查阅可视窗口标题 在Delphi编程中创建一个启动闪现窗口 如何用Delphi编ScreenSaver Delphi里如何计算日期 delphi怎样调用外部EXE文件 Win95/98下监控运行的其他程序 控制面板应用大全 避免一个程序二次运行 转换WINDOWS壁纸 改计算机名 为应用程序添加口令 启动屏幕保护 控制热启动 辨别显示分辨率 获得WINDOWS的临时路径 状态条插入可视控件 统计中英文字个数 获得Windows类型和版本 读INI文件 大小写金额转换 检测程序是否运行 用Delphi3编写"共享软件" 如何从任务栏上隐藏应用程序的按纽 如何在Delphi程序中支持文件拖放 如何运行一个程序直到它结束 用De1phi编制汉字录入能力测试软件 一个实用的Delphi屏幕拷贝程序的设计 如何做一个SYSTRAY程序 查阅可视窗口标题 屏蔽系统功能键 状态条插入可视控件 如何隐藏和显示Windows的任务条 如何将你的程序放在Windows启动中 获取当前程序的目录
DELPHI专题文档-程序应用 更改Windows95的墙纸 类似于VB中的doevents功能 DELPHI下的多线程程序设计 用Delphi 3.0编制MP3音乐点歌台 用Delphi开发windows95屏幕保护预览程序 判断一个程序是否dos版本 Delphi自定义消息应用一例 显示密码编辑框中的密码 也谈Delphi中的日期输入 用修改文件时间的方法来加密文件 在DELPHI中处理时间 在Delphi中用拼音首字符序列来实现检索功能 用Delphi创建Internet快捷方式 用Delphi实现远程屏幕抓取 资源文件在DELPHI中的使用 在DELPHI应用程序中使用DLL 为DELPHI应用程序制作安装程序 用注册表对Delphi程序进行加密 在Delphi程序中操作注册表 鼠标和键盘控制 如何为Delphi程序添加事件和事件处理器 在Delphi应用程序中拖动控件 用DEPHI为应用软件建立注册机制 用Delphi创建临时文件 Delphi 5快速创建控制面板程序 Delphi经验技巧集锦 Microsoft Agent技术在Delphi中的应用 怎样建立简单的任务栏应用程序 判断一个程序是否dos版本 利用Delphi 5中调用Excel 97 利用Dll实现通用密码验证框 如何访问一个进程的内存空间 用Delphi 5.0编写OLE程序操纵Excel 用Delphi编写DLL实现动态改变分辨率 在delphi中使用flash控件 在Delphi中运用QuickReport实现多栏列印 控制INI文件几法 转让控制权 得到执行程序的目录 打开已注册文件 得到Windows用户名和序列号 关闭外部应用程序 查阅可视窗口标题 在Delphi编程中创建一个启动闪现窗口 如何用Delphi编ScreenSaver Delphi里如何计算日期 delphi怎样调用外部EXE文件 Win95/98下监控运行的其他程序 控制面板应用大全 避免一个程序二次运行 转换WINDOWS壁纸 改计算机名 为应用程序添加口令 启动屏幕保护 控制热启动 辨别显示分辨率 获得WINDOWS的临时路径 状态条插入可视控件 统计中英文字个数 获得Windows类型和版本 读INI文件 大小写金额转换 检测程序是否运行 用Delphi3编写"共享软件" 如何从任务栏上隐藏应用程序的按纽 如何在Delphi程序中支持文件拖放 如何运行一个程序直到它结束 用De1phi编制汉字录入能力测试软件 一个实用的Delphi屏幕拷贝程序的设计 如何做一个SYSTRAY程序 查阅可视窗口标题 屏蔽系统功能键 状态条插入可视控件 如何隐藏和显示Windows的任务条 如何将你的程序放在Windows启动中 获取当前程序的目录
Delphi启动程序内嵌到自身是指在Delphi程序中调用另一个程序,并将其嵌入到当前程序的界面中显示和操作。 在Delphi中,可以使用ShellExecute函数来启动一个外部程序。该函数接受多个参数,包括程序路径、命令行参数、工作目录和显示方式等。通过调用ShellExecute函数,并传入需要启动的程序路径,就可以在Delphi程序中启动该程序。 在启动程序后,可以使用窗口句柄来获取外部程序的进程,并使用Windows API函数来操作和控制它。可以使用FindWindow、SetWindowPos等函数来获取和设置窗口的句柄、位置和大小等。 通过获取外部程序的窗口句柄后,可以将其嵌入到Delphi程序的界面中。可以使用SetParent函数将外部程序的窗口句柄设置为Delphi程序的一个控件的子窗口,使外部程序的界面显示在当前程序的界面中。同时,还可以根据需要调整外部程序的位置和大小,以使其适应Delphi程序的界面布局。 除了嵌入外部程序的界面,还可以通过消息传递方式与外部程序进行交互。可以使用SendMessage函数向外部程序发送消息,并接收其返回的消息。通过消息传递,可以实现与外部程序的数据交换、状态同步等功能。 需要注意的是,嵌入外部程序可能会引起一些兼容性和稳定性问题。所以在进行嵌入操作之前,最好进行充分的测试和验证,确保整个系统的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值