困惑:如何调用另一个程序,并控制它 Delphi / Windows SDK/APIhttp://www.delphi2007.net/DelphiAPI/html/delphi_20061113000418245.html
我现在想调用B(也是delphi)程序,我用的是
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellExecute(0,'open',projectB.exe'),nil,nil,SW_ShowNormal);
end;
启动后出现B程序的登陆界面,界面上有登陆框
问题是:如何向里面传进用户名和密码
并能实现自动点击登陆按钮的操作?
有好多方法实现。我给你一个我的实例(看门狗WatchDog)
var
Dir: string;
begin
...
Dir := ExtractFileDir(Application.ExeName);
Winexec(Pchar(Dir+'\SMSEVALUATE.EXE 00001 11111),1);
//SMSEVALUATE.EXE是我的程序名称与WatchDog在同一目录下
用户代码:00001 用户密码:11111(你不一定这样设置,只要区分有没有参数就可以了)
...
在SMSEVALUATE的Project中这样写:
Application.Initialize;
Application.Title := '我的系统;
with TFormLogin.Create(Application) do
begin
if ParamCount = 0 then //重要点,
//如果没有参数就正常显示登陆窗口,
//如果有参数就不显示,
//在FormLogin中要加入带参数运行时的处理代码
ShowModal;
if ModalResult = 1 then
...
楼主碰到的情况可能是B程序用不了参数的吧,要给他的文本框里发信息
//
楼主碰到的情况可能是B程序用不了参数的吧,要给他的文本框里发信息
//
任何程序都可以带参数运行,就看你程序内部如何处理参数啦。所以不用给他的文本框里发信息
//
给他的文本框里发信息
//
太僵硬的思路啦
呵呵,谢谢两位:)
补充一下:B程序里的代码改动不了
只能往B的文本框里传信息
这种情况怎么处理?
先启动B这个进程,然后用FindWindow/FindWindowEx/GetWindow等API查找目标程序主窗口上的文本框和按钮(这个过程可能要试好几次才能准确找到),成功得到文本框句柄后,用SetWindowText或WM_SETTEXT给文本框赋值,再向按钮发送BM_CLICK消息,例如:
SendMessage(hButton, BM_CLICK, 0, 0);
对对,这种实现方法很适合我的情况
就是能不能给点 代码demo之类的,如上面的sanmaotuo(老冯)兄弟那样
感激ing...
那都是些API应用,还需要详细代码?
这样吧,你去www.ccrun.com/spy4win下载spy4win,可以自动产生一些简单的查找窗口的代码)for C++,Delphi,VB),看看你就明白了。
经指点后,我写了以下一段代码
但是还有一个问题:如下,
procedure TForm1.Button3Click(Sender: TObject);
var
FHwnd : THandle;
t1Hwnd:THandle;
t2Hwnd: THandle;
BHwnd: THandle;
begin
WinExec(PChar('project1.exe'),SW_HIDE) ;
FHwnd:=FindWindow(nil,'form1');
if fHwnd>0 then
begin
t1Hwnd:=FindWindowEx(fHwnd,0,nil,'edit1');
t2Hwnd:=FindWindowEx(fHwnd,0,nil,'edit2');
//这样成功取到edit1句柄的前提是edit1的text必须有值
但是当edit1的text属性为空的时候就取不到句柄,这可咋整??
BHwnd:=FindWindowEx(fHwnd,0,nil,'button1');
if t1Hwnd>0 then PostMessage(t1Hwnd,WM_IME_CHAR,ord('a'),0) ;
if t2Hwnd>0 then PostMessage(t2Hwnd,WM_IME_CHAR,ord('b'),0) ;
if BHwnd>0 then PostMessage(BHwnd,WM_KEYDOWN,VK_RETURN ,0) ;
end;
//PostMessage(FHwnd,WM_KEYDOWN,VK_RETURN ,0)
//SendMessage(FHwnd, BM_CLICK, 0, 0);
end;
还望指点!
查找Edit时,先用FindWindowEx找到第一个文本框,第四个参数可为空,直接查找类名就可以。成功后用GetWnidow再查找下一个兄弟窗口。
可以参考一下这个:
自动填写序列号演示
AutoFillSnDemo,安装Office2003时自动填写序列号工具源码,ccrun(老妖)编写。读者可自己扩展一下,成为一个通用的序列号填写工具。
http://www.ccrun.com/view.asp?id=349
在主模块调用子模块时(主模块与子模块是独立的程序),用DLL或DDE即可!
ccrun(老妖)已经说得很清楚了, 我来把老妖的精神Coding一下。很认真做的哦,不是说笑哈。
type
TSAppForm = class(TForm)
Button: TButton;
procedure ButtonClick(Sender: TObject);
private
function FindControlByNumber(hApp: HWND; ControlClassName: string; ControlNumber: Integer): HWND;
procedure SetEditText(hApp: HWND; EditClassName, AText: string; EditNumber: Integer);
procedure SetButtonActive(hApp: HWND; ButtonClassName: string; ButtonNumber: Integer);
public
{ Public declarations }
end;
var
SAppForm: TSAppForm;
implementation
{$R *.dfm}
{ TSAppForm }
function TSAppForm.FindControlByNumber(hApp: HWND;
ControlClassName: string; ControlNumber: Integer): HWND;
var
i: Word;
hControl: HWND;
begin
Result := 0;
hControl := 0;
if IsWindow(hApp) then
begin
hControl := 0;
for i := 0 to Pred(ControlNumber) do
begin
hControl := FindWindowEx(hApp, hControl, PChar(ControlClassName), nil);
if hControl = 0 then
Exit;
end;
end;
Result := hControl;
end;
procedure TSAppForm.SetEditText(hApp: HWND; EditClassName, AText: string;
EditNumber: Integer);
var
hEdit: HWND;
begin
hEdit := FindControlByNumber(hApp, EditClassName, EditNumber);
if hEdit <> 0 then
SendMessage(hEdit, WM_SETTEXT, 0, Integer(PChar(AText)));
end;
procedure TSAppForm.ButtonClick(Sender: TObject);
var
hApp: HWND;
begin
hApp := FindWindow(nil, 'RAppForm');
if hApp > 0 then
begin
SetEditText(hApp, 'TEdit', 'Cock', 1);
SetEditText(hApp, 'TEdit', 'Pussy', 2);
SetButtonActive(hApp, 'TButton', 1);
end;
end;
procedure TSAppForm.SetButtonActive(hApp: HWND; ButtonClassName: string;
ButtonNumber: Integer);
var
hButton: HWND;
begin
hButton := FindControlByNumber(hApp, ButtonClassName, ButtonNumber);
if hButton > 0 then
SendMessage(hButton, WM_KEYDOWN, VK_RETURN, 0);
end;
end.
-------------------------------
type
TRAppForm = class(TForm)
Button: TButton;
Edit1: TEdit;
Edit2: TEdit;
procedure ButtonKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
private
{ Private declarations }
public
{ Public declarations }
end;
var
RAppForm: TRAppForm;
implementation
{$R *.dfm}
procedure TRAppForm.ButtonKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if Key = VK_Return then
ShowMessage(Edit1.Text+'\'+Edit2.Text);
end;
经过你两多次指点,问题解决
非常感谢,好人啊!
献上我的拙码给其他需要的人:
(B程序上为 两个edit和一个button)
procedure TForm1.Button1Click(Sender: TObject);
var
FHwnd : THandle;
t1Hwnd:THandle;
t2Hwnd: THandle;
BHwnd: THandle;
begin
WinExec(PChar('projectB.exe'),SW_HIDE) ;
FHwnd:=FindWindow(nil,'form1');
if fHwnd>0 then
begin
t1Hwnd:=FindWindowEx(FHwnd,0,'TEdit',nil);
if t1Hwnd<>0 then
t2Hwnd:=GetWindow(t1Hwnd, GW_HWNDNEXT);
BHwnd:=FindWindowEx(FHwnd,0,'TButton',nil);
if t1Hwnd>0 then
SendMessage(t1Hwnd, WM_SETTEXT, 0, Integer(PChar('user')));
if t2Hwnd>0 then
SendMessage(t2Hwnd, WM_SETTEXT, 0, Integer(PChar('pwd')));
if BHwnd>0 then
PostMessage(BHwnd,WM_KEYDOWN,VK_RETURN ,0) ;
end;
end;