如何shell到另一个应用程序并使其以delphi形式出现
在Delphi中,我多年来一直使用ShellExecute来启动(并可选地等待)其他应用程序。现在,我需要让这些应用程序中的一个出现在我的Delphi应用程序表单中。我已经尝试了下面的代码作为一个简单的测试来打开记事本(它可以)并在我的表单上的PAnel1中显示结果(它不能)。能找个好心人把我带上正轨吗? 谢谢如何shell到另一个应用程序并使其以delphi形式出现,delphi,shellexecute,setparent,Delphi,Shellexecute,Setparent,在Delphi中,我多年来一直使用ShellExecute来启动(并可选地等待)其他应用程序。现在,我需要让这些应用程序中的一个出现在我的Delphi应用程序表单中。我已经尝试了下面的代码作为一个简单的测试来打开记事本(它可以)并在我的表单上的PAnel1中显示结果(它不能)。能找个好心人把我带上正轨吗? 谢谢 如果可能的话,这将是一个棘手的问题 我见过一些适用于基于文本的应用程序的方法——它们通常在流程发生时捕获流程的标准输出,并将其放入文本控件中 但您所说的是一个成熟的图形应用程序(记事本,
如果可能的话,这将是一个棘手的问题 我见过一些适用于基于文本的应用程序的方法——它们通常在流程发生时捕获流程的标准输出,并将其放入文本控件中 但您所说的是一个成熟的图形应用程序(记事本,尽管它只处理文本、显示像素,而不是字符代码) 因此,除非记事本提供了一个界面,您可以:
- 请求缓冲区中的任意字符;及
- 向程序发送任意击键, 我得说你真倒霉
您是否想过使用专门为Delphi构建的编辑器控件(或可以嵌入的ActiveX编辑器)?这可能是一种更好的方法。省略所有错误检查,但这应该让您开始:
procedure TForm1.Button1Click(Sender: TObject);
var
Rec: TShellExecuteInfo;
const
AVerb = 'open';
AParams = '';
AFileName = 'Notepad.exe';
ADir = '';
begin
FillChar(Rec, SizeOf(Rec), #0);
Rec.cbSize := SizeOf(Rec);
Rec.fMask := SEE_MASK_NOCLOSEPROCESS;
Rec.lpVerb := PChar( AVerb );
Rec.lpFile := PChar( AfileName );
Rec.lpParameters := PChar( AParams );
Rec.lpDirectory := PChar( Adir );
Rec.nShow := SW_HIDE;
ShellExecuteEx(@Rec);
WaitForInputIdle(Rec.hProcess, 5000);
fNotepadHandle := Windows.FindWindow( 'Notepad', nil );
Windows.SetParent( fNotepadHandle, Handle );
Resize;
ShowWindow(fNotepadHandle, SW_SHOW);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
if IsWindow(fNotepadHandle) then begin
SetWindowPos(fNotepadHandle, 0, 0, 0, ClientWidth, ClientHeight,
SWP_ASYNCWINDOWPOS);
end;
end;
您肯定应该枚举新进程的窗口,而不是简单地使用FindWindow()返回的任何窗口句柄。您想对记事本的主菜单做什么?我认为记事本只是其他程序尝试此技术的占位符。虽然我同意你的一般看法,如果有其他方法的话,不要这样做,但简单地设置父HWND并进行定位并不难。ActiveX/OLE控件肯定会更好。但是,当然可以将另一个应用程序的窗口放在您的应用程序中。我在VB中做过类似的事情,但我想我使用了MDI表单。而且,通过子类化捕获击键并将其发送到另一个windows窗体应该相对容易。但我已经有将近十年没有处理过这种事情了。太棒了,谢谢。我只希望我能详细了解正在发生的事情。。。。。!现在关闭以删除一些位,看看会发生什么。再次感谢。BriI很好奇-这能处理最小化、最大化改变z顺序等问题吗?或者应该为此添加更多的TForm1.Form*函数吗?看起来不错。唯一的问题是记事本的标题栏按钮被保留了下来,所以人们仍然可以最小化、最大化或关闭记事本。为了获得合适的解决方案,可能应该删除整个标题栏。根据要求,可能需要更多,但问题中的问题通过上述代码解决。什么是
fNotepadHandle
和Windows
类型?@EASI:Windows是单元名称,是正确名称解析所必需的(表单具有相同名称、不同签名的方法)。另一个是HWND
,但是您可以自己在FindWindow()API函数的文档中查找它。
procedure TForm1.Button1Click(Sender: TObject);
var
Rec: TShellExecuteInfo;
const
AVerb = 'open';
AParams = '';
AFileName = 'Notepad.exe';
ADir = '';
begin
FillChar(Rec, SizeOf(Rec), #0);
Rec.cbSize := SizeOf(Rec);
Rec.fMask := SEE_MASK_NOCLOSEPROCESS;
Rec.lpVerb := PChar( AVerb );
Rec.lpFile := PChar( AfileName );
Rec.lpParameters := PChar( AParams );
Rec.lpDirectory := PChar( Adir );
Rec.nShow := SW_HIDE;
ShellExecuteEx(@Rec);
WaitForInputIdle(Rec.hProcess, 5000);
fNotepadHandle := Windows.FindWindow( 'Notepad', nil );
Windows.SetParent( fNotepadHandle, Handle );
Resize;
ShowWindow(fNotepadHandle, SW_SHOW);
end;
procedure TForm1.FormResize(Sender: TObject);
begin
if IsWindow(fNotepadHandle) then begin
SetWindowPos(fNotepadHandle, 0, 0, 0, ClientWidth, ClientHeight,
SWP_ASYNCWINDOWPOS);
end;
end;
var
URL: string;
begin
URL:= DBMemoURL.Text;
// ShellExecute(self.WindowHandle,'open', PChar(URL), nil, nil, SW_SHOW); //default browser
ShellExecute(self.WindowHandle,'open','chrome.exe', PChar(URL), nil, SW_SHOW);