Как скопировать в другое приложение и отобразить его в форме delphi

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

Ответы

Ответ 1

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

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

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

Ответ 3

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

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

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

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

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

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

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