11

在 Delphi 中,我多年来一直使用 ShellExecute 来启动(并可选择等待)其他应用程序。但现在,我需要让这些应用程序之一出现在我的 Delphi 应用程序表单之一中。我已经尝试将下面的代码作为一个简单的测试来打开记事本(它确实如此)并在我的表单上的 PAnel1 中显示结果(它没有)。某个好心人可以让我走上正轨吗?谢谢

var
  Rec          : TShellExecuteInfo;
  wnd : HWnd;
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_Show;

  ShellExecuteEx(@Rec);

  wnd := Windows.FindWindow( 'Notepad', nil );
  Windows.SetParent( Wnd, PAnel1.Handle );

end;
4

3 回答 3

16

省略了所有错误检查,但这应该可以帮助您入门:

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()返回的任何窗口句柄。

于 2009-04-28T09:06:06.660 回答
1
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); 
于 2011-11-04T16:05:18.160 回答
0

如果可能的话,这将是一个棘手的问题。

我见过适用于基于文本的应用程序的方法——它们通常会在过程发生时捕获标准输出并将其放入文本控件中。

但是您所说的是一个完全成熟的图形应用程序(记事本,尽管处理文本,显示像素,而不是字符代码)。

因此,除非记事本提供了一个界面,您可以:

  • 请求缓冲区中的任意字符;和
  • 向程序发送任意击键,我会说你完全不走运。

绝对是一个杂物,但一种选择是持续监视记事本窗口并确保它始终叠加在您的表单客户区域上。这非常可怕,因为您必须阻止它移动、调整大小、最小化等等,保持它的 z 顺序刚好在您的应用程序之上。我不希望对我最大的敌人提出这些要求。

您是否考虑过使用专门为 Delphi 构建的编辑器控件(或您可以嵌入的 ActiveX 编辑器)?这可能是一个更好的方法。

于 2009-04-28T09:05:18.487 回答