gpt4 book ai didi

delphi - 启动程序并与现有程序对接 Delphi 2010

转载 作者:行者123 更新时间:2023-12-03 15:47:16 26 4
gpt4 key购买 nike

Delphi 2010 中是否有一种方法可以使用 ShellExecute 启动应用程序,然后将该应用程序停靠在另一个应用程序中?

即用Delphi编写的程序A包含1个表格。当表单显示时,用 C# 编写的程序 B 启动并将客户端停靠到程序 A 的表单中?

保罗

最佳答案

是的,你可以做到这一点。您需要在另一个进程中获取主窗体的窗口句柄(调用 EnumWindows )。然后调用SetParent使该窗口成为您窗口的子窗口。

您可能想要修改窗口样式、位置等。也可以调用 WaitForInputIdle在尝试在新进程中查找窗口句柄之前。您必须给新流程一个开始的机会。

你现在拥有的是一只非常奇怪的野兽。在一个容器内有两个进程。每个进程都有自己的 UI 线程。您可以同时显示两个模式对话框并与之交互。您真的可以从中获得无穷无尽的乐趣!

<小时/>

编辑

只是为了一点乐趣,我尝试编写一个简单的 Delphi 应用程序来执行此操作。它相当脆弱,似乎只适用于非常基本的应用程序。我认为你可能会花费很长时间试图让这项工作顺利进行,但最终仍然会得到不令人满意的结果。如果我是您,我会寻找其他解决方案,特别是当您拥有此 C# 应用程序的源代码时。您当然可以将其功能公开为 ActiveX 吗?

无论如何,为了您的娱乐,我提供以下极其未经修饰的代码:

program AppHost;

uses
Windows, Messages, SysUtils, Forms, Controls, ComCtrls;

{$R *.res}

procedure ResizePage(Page: TTabSheet);
var
hwnd: Windows.HWND;
Rect: TRect;
begin
hwnd := Page.Tag;
Rect := Page.ClientRect;
MoveWindow(hwnd, Rect.Left, Rect.Top, Rect.Right-Rect.Left, Rect.Bottom-Rect.Top, True);
end;

type
PEnumData = ^TEnumData;
TEnumData = record
ProcessID: DWORD;
hwnd: HWND;
end;

function EnumWindowsProc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
ProcessId: DWORD;
EnumData: PEnumData;
begin
EnumData := PEnumData(lParam);
GetWindowThreadProcessId(hwnd, ProcessId);
if EnumData.ProcessID=ProcessID then begin
EnumData.hwnd := hwnd;
Result := False;
exit;
end;
Result := True;
end;

procedure Absorb(PageControl: TPageControl; const App: string; StartupInfo: TStartupInfo);
var
Page: TTabSheet;
ProcessInformation: TProcessInformation;
EnumData: TEnumData;
begin
Page := TTabSheet.Create(PageControl);
Page.PageControl := PageControl;
Page.Caption := ChangeFileExt(ExtractFileName(App), '');
CreateProcess(PChar(App), nil, nil, nil, False, 0, nil, nil, StartupInfo, ProcessInformation);
WaitForInputIdle(ProcessInformation.hProcess, INFINITE);
EnumData.ProcessID := ProcessInformation.dwProcessId;
EnumData.hwnd := 0;
EnumWindows(@EnumWindowsProc, LPARAM(@EnumData));
Page.Tag := Integer(EnumData.hwnd);
SetParent(HWND(Page.Tag), Page.Handle);
ResizePage(Page);
end;

type
TEventProvider = class
private
FForm: TForm;
FPageControl: TPageControl;
procedure FormResize(Sender: TObject);
public
constructor Create(Form: TForm; PageControl: TPageControl);
end;

{ TEventProvider }

constructor TEventProvider.Create(Form: TForm; PageControl: TPageControl);
begin
inherited Create;
FForm := Form;
FPageControl := PageControl;
FForm.OnResize := FormResize;
end;

procedure TEventProvider.FormResize(Sender: TObject);
var
i: Integer;
begin
for i := 0 to FPageControl.PageCount-1 do begin
ResizePage(FPageControl.Pages[i]);
end;
end;

procedure Main(Form: TForm);
var
StartupInfo: TStartupInfo;
PageControl: TPageControl;
begin
Form.ClientHeight := 600;
Form.ClientWidth := 800;
Form.Caption := 'All your processes are belong to us';
PageControl := TPageControl.Create(Form);
PageControl.Parent := Form;
PageControl.Align := alClient;
StartupInfo.cb := SizeOf(StartupInfo);
GetStartupInfo(StartupInfo);
Absorb(PageControl, 'C:\Windows\Notepad.exe', StartupInfo);
Absorb(PageControl, 'C:\Program Files\CommandLine\depends.exe', StartupInfo);
TEventProvider.Create(Form, PageControl);
end;

var
Form: TForm;

begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, Form);
Main(Form);
Application.Run;
Form.Free;
end.

关于delphi - 启动程序并与现有程序对接 Delphi 2010,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5216860/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com