Как создать оболочку для другого приложения, чтобы оно отображалось в форме Delphi - PullRequest
11 голосов
/ 28 апреля 2009

В 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;

Ответы [ 3 ]

16 голосов
/ 28 апреля 2009

Все проверки ошибок пропущены, но это должно помочь вам начать:

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 () возвращает.

2 голосов
/ 04 ноября 2011
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); 
0 голосов
/ 28 апреля 2009

Это будет сложно, если это вообще возможно.

Я видел подходы, которые будут работать для текстовых приложений - они обычно фиксируют стандартный вывод процесса, как это происходит, и помещают его в текстовый элемент управления.

Но вы говорите о полноценном графическом приложении (Блокнот, несмотря на работу с текстом, отображением пикселей, а не кодов символов).

Итак, если Блокнот не предоставляет интерфейс, где вы можете:

  • запрос произвольных символов в буфере; и
  • отправлять произвольные нажатия клавиш в программу, Я бы сказал, что тебе не повезло.

Это определенно клудж, но одним из вариантов является постоянный мониторинг окон Блокнота и обеспечение его постоянного наложения на область клиента форм. Это довольно ужасно, поскольку вам нужно остановить его перемещение, изменение размера, сворачивание и т. Д., и поддерживают свой z-порядок чуть выше ваших приложений. Я бы не пожелал этих требований для моего злейшего врага.

Задумывались ли вы об использовании элемента управления редактора, созданного специально для Delphi (или редактора ActiveX, который вы могли бы встроить)? Это может быть лучшим подходом.

...