Запуск стороннего приложения на форме своего приложения

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Запуск стороннего приложения на форме своего приложения

Сообщение ivanlex » 18.12.2019 13:46:27

Доброго времени суток.

Подскажите пожалуйста, как можно на форме своего приложения отображать окно стороннего приложения. К сожалению не могу найти достаточно информации для реализации задуманного.

Заранее спасибо всем откликнувшимся, не проходите мимо.
ivanlex
незнакомец
 
Сообщения: 1
Зарегистрирован: 18.12.2019 13:36:33

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Снег Север » 21.12.2019 18:39:42

как-то, примерно, так:

Код: Выделить всё
procedure TForm1.FormClick(Sender: TObject); //при клике на форме
var h:hwnd;     //указатель на окно
begin
//запускаем стандартную "командную строку"
  ShellExecute(form1.Handle,'open','cmd.exe',nil,'c:\\windows\system32\',SW_SHOW);
  sleep(10); //ждём, пока окно не появится
  //находим окно по заголовку
  h:=findwindow(nil, 'c:\\windows\system32\cmd.exe');
  //если нашли, присваиваем ему статус дочернего от нашего окошка
  if h<>0 then windows.SetParent(h,form1.Handle);
end;
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Sharfik » 22.12.2019 01:20:06

:shock: "А что так можно было?"
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 759
Зарегистрирован: 20.07.2013 01:04:30

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 22.12.2019 05:05:12

Интересно, работает
Только пути всюду поправить на c:\windows\system32\
и задержу повысить до 150.
(Однако, обнаружил какое-то странное положение "окна внутри окна" Немного помогает ShowWindow(h,SW_SHOWMAXIMIZED); но только если нет ресайза окна ) ...
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Ichthyander » 22.12.2019 11:38:01

Снег Север писал(а):как-то, примерно, так:

Код: Выделить всё
procedure TForm1.FormClick(Sender: TObject); //при клике на форме
var h:hwnd; //указатель на окно
begin
//запускаем стандартную "командную строку"
ShellExecute(form1.Handle,'open','cmd.exe',nil,'c:\\windows\system32\',SW_SHOW);
sleep(10); //ждём, пока окно не появится
//находим окно по заголовку
h:=findwindow(nil, 'c:\\windows\system32\cmd.exe');
//если нашли, присваиваем ему статус дочернего от нашего окошка
if h<>0 then windows.SetParent(h,form1.Handle);
end;



Вау :shock:
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 668
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 22.12.2019 14:52:54

Я делал подобный прикол иначе ... Через вот такую рагулину.
Код: Выделить всё
function CreateSnapshot ( WindowHD : HWND ):TBitmap;
var
    wnd:HWND;
    dc:HDC;
    Bmp:TBitmap;
    r:TRect;

begin
     wnd :=WindowHD;
       if wnd = 0 then
        begin
         dc := GetDC(0);
         Bmp := TBitmap.Create;
         Bmp.SetSize (Screen.Width,Screen.Height);
        end
       else
        begin
        Bmp := TBitmap.Create;
        dc := GetWindowDC(wnd);
         GetWindowRect(wnd,r);
         Bmp.SetSize(r.Right-r.Left,r.Bottom-r.Top);
        end;
       BitBlt(Bmp.Canvas.Handle,0,0,Bmp.Width,Bmp.Height,DC,0,0,SRCCOPY);
       Result:= bmp;
      ReleaseDC(wnd,dc);
end;

Но через SetParent круче ! :idea:
Зы
Если планируется изменение размера формы или панели
Нужно добавить вот такую заплатку....
Код: Выделить всё
procedure TForm1.FormResize(Sender: TObject);
begin
if h<>0 then begin
  MoveWindow(h,0,0,Width,Height,true);
end;
end;

Ну и при инициализации MoveWindow тоже предпочтительней чем
вызов ShowWindow(h,SW_SHOWMAXIMIZED);
Вообщем для интеграции разных утилит и плагинов внутрь своих приложений "то что доктор прописал" :idea:
Зы Зы
Интересно, а можно ли браузер таким же образом вызвать? :roll:
(А то мучать огромадный ХромАпи из за нужды показать одну страничку изрядно накладно )
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Снег Север » 23.12.2019 17:59:36

Кушайте на здоровье! :D
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 24.12.2019 00:50:09

Спасибо ! :idea: Браузер запустился но работает немного странновато
( временами черный или белый "квадрат малевича" показывает при клике на него мышкой ).
Последний раз редактировалось Alex2013 25.12.2019 02:26:24, всего редактировалось 1 раз.
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 25.12.2019 02:19:41

Небольшая проблема ! Пытался сделать тоже самое но без FindWindow (Потому что определить заголовок в окне современного браузера дело почти безнадежное )
Написал примерно вот такой код:
Код: Выделить всё
uses
   Windows,ShellAPI,....

Const  h:hwnd =0;

procedure TForm1.Button1Click(Sender: TObject);
var
ExecInfo: TShellExecuteInfoA;
begin
FillChar(ExecInfo, SizeOf(TShellExecuteInfo), 0);
with ExecInfo do
begin
cbSize := SizeOf(TShellExecuteInfo);
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Handle;
  lpFile := PChar('CMD.exe');
nShow := SW_SHOWNORMAL;
end;
ShellExecuteExA(@ExecInfo);
   sleep(150); //ждём, пока окно не появится
   h:=ExecInfo.hProcess;
  if h<>0 then  begin
windows.SetParent(h, form1.Handle  );
   MoveWindow(h,0,0,Width,Height,true);
end;
end; 

Но он не работает похоже что ExecInfo.hProcess это что угодно но не Handle окна ( хотя по идее он должен быть как-то с ним связан).
Но что я не делал получить хедел не получилось . Вопрос что я не так делаю ?
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Vadim » 25.12.2019 03:23:57

Alex2013 писал(а):Вопрос что я не так делаю ?

Из WinAPI:
hProcess

Type: HANDLE

A handle to the newly started application.

Тут слово "окно" где-то есть? ;-)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Снег Север » 25.12.2019 10:59:23

Alex2013, тут придется повозиться. Общий путь примерно такой:
- по названию процесса получить его PID
- перечислить все окна десктопа, для каждого окна средствами GetWindowsThreadProcessID получить PID процесса-владельца, сравнить с искомым
- для найденного окна получить его "имя" - GetWindowText
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2993
Зарегистрирован: 27.11.2007 16:14:47

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 25.12.2019 12:58:14

Vadim писал(а):
Alex2013 писал(а):Вопрос что я не так делаю ?

Из WinAPI:
hProcess

Type: HANDLE

A handle to the newly started application.

Тут слово "окно" где-то есть? ;-)

Уел ! :oops:
Но что такое "handle недавно запущенного приложения" PID процесса что ли ?

Добавлено спустя 10 минут 36 секунд:
Снег Север писал(а):Alex2013, тут придется повозиться. Общий путь примерно такой:
- по названию процесса получить его PID
- перечислить все окна десктопа, для каждого окна средствами GetWindowsThreadProcessID получить PID процесса-владельца, сравнить с искомым
- для найденного окна получить его "имя" - GetWindowText

:roll: Спасибо, однако что-то такое я уже пытался сделать ... :idea:
Ладно буду копать дальше!

Добавлено спустя 1 час 51 минуту 5 секунд:
Вот мой вариант ...
Код: Выделить всё
uses
   Windows,ShellAPI,....

Const  h:hwnd =0;

function GetProcessID(AHandle: HANDLE): DWORD; stdcall; external 'kernel32.dll' name 'GetProcessId';

procedure TForm1.Button1Click(Sender: TObject);
var
ExecInfo: TShellExecuteInfoA;
S:String;
begin
FillChar(ExecInfo, SizeOf(TShellExecuteInfo), 0);
with ExecInfo do
begin
cbSize := SizeOf(TShellExecuteInfo);
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := Handle;
  lpFile := PChar('CMD.exe');
nShow := SW_SHOWNORMAL;
end;
ShellExecuteExA(@ExecInfo);
   sleep(150); //ждём, пока окно не появится
SetLength(s,512);
SetLength(s,GetWindowText(GetProcessID(ExecInfo.hProcess),@s[1],512));
//ShowMessage(s);
h:=findwindow(nil,@s[1]);

if h<>0 then  begin
windows.SetParent(h, form1.Handle  );
   MoveWindow(h,0,0,Width,Height,true);
end;
end;

...не работает. :roll:
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Vadim » 25.12.2019 16:40:34

Alex2013 писал(а):Но что такое "handle недавно запущенного приложения" PID процесса что ли ?

А бес его знает, но явно что-то полезное... :D Для PID'а возможно понадобится функция GetProcessId(хендл). Но могу ошибиться, не специалист в этом вопросе.
Вам Снег Север правильно написал. Все главные окна запускаемых приложений - "дети" десктопа. Поэтому нужен список окон, которые впиявились в десктоп и уж по списку проверять, принадлежит окно процессу или нет.
Можно ещё попробовать EnumThreadWindows(), но опять же, не специалист, может быть и не то...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Запуск стороннего приложения на форме своего приложения

Сообщение Alex2013 » 25.12.2019 17:13:02

Так работает но... "Ужасающий истина!".. :wink: ничего кроме far.exe и прочих консольных приблуд не "удочеряет" .... :cry:
Код: Выделить всё
{$mode delphi}  {$H+} 
uses
   Windows,ShellAPI....   

Const  h:hwnd =0;
       SearchHandle:hwnd =0;

function EnumProc(h:HWND; lParam:DWord):boolean; stdcall;
var
ProcessId, z:cardinal;
begin
Result:=True;
GetWindowThreadProcessId(h, ProcessId);
If ProcessId=lParam then
begin
SearchHandle:=h;
Result:=False;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
ExecInfo: TShellExecuteInfoA;
var
si:STARTUPINFO;
pi:PROCESS_INFORMATION;
buf:array[1..100] of char;

S:String;
P:Pointer;
begin
  ZeroMemory(@si, sizeof(si));
  si.cb:=SizeOf(si);
  P:=@EnumProc;
{  CreateProcess(nil, 'c:\windows\system32\cmd.exe', nil, nil, false,
  0, nil, nil, si, pi); }
  CreateProcess(nil, 'C:\Program Files\Far Manager\far.exe', nil, nil, false, 0, nil, nil, @si,@pi);
  SearchHandle:=0;
  sleep(150);
  While SearchHandle=0 do
  begin
  Windows.EnumWindows(@EnumProc,Lparam( pi.dwProcessId) );
  Application.ProcessMessages;
  end;
  H:=SearchHandle;
  if h<>0 then  begin
   windows.SetParent(h,form1.Handle);
   MoveWindow(h,0,0,Width,Height,true);
end;
end;
Alex2013
долгожитель
 
Сообщения: 2923
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 32

Рейтинг@Mail.ru