Запуск стороннего приложения на форме своего приложения
Модератор: Модераторы
Запуск стороннего приложения на форме своего приложения
Доброго времени суток.
Подскажите пожалуйста, как можно на форме своего приложения отображать окно стороннего приложения. К сожалению не могу найти достаточно информации для реализации задуманного.
Заранее спасибо всем откликнувшимся, не проходите мимо.
Подскажите пожалуйста, как можно на форме своего приложения отображать окно стороннего приложения. К сожалению не могу найти достаточно информации для реализации задуманного.
Заранее спасибо всем откликнувшимся, не проходите мимо.
- Снег Север
- долгожитель
- Сообщения: 3070
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
как-то, примерно, так:
Код: Выделить всё
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;Интересно, работает
Только пути всюду поправить на c:\windows\system32\
и задержу повысить до 150.
(Однако, обнаружил какое-то странное положение "окна внутри окна" Немного помогает ShowWindow(h,SW_SHOWMAXIMIZED); но только если нет ресайза окна ) ...
Только пути всюду поправить на c:\windows\system32\
и задержу повысить до 150.
(Однако, обнаружил какое-то странное положение "окна внутри окна" Немного помогает ShowWindow(h,SW_SHOWMAXIMIZED); но только если нет ресайза окна ) ...
- Ichthyander
- энтузиаст
- Сообщения: 701
- Зарегистрирован: 04.04.2007 08:32:43
- Откуда: Астрахань
- Контактная информация:
Снег Север писал(а):как-то, примерно, так:
Код: Выделить всё
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;
Вау
Я делал подобный прикол иначе ... Через вот такую рагулину.
Но через SetParent круче !
Зы
Если планируется изменение размера формы или панели
Нужно добавить вот такую заплатку....
Ну и при инициализации MoveWindow тоже предпочтительней чем
вызов ShowWindow(h,SW_SHOWMAXIMIZED);
Вообщем для интеграции разных утилит и плагинов внутрь своих приложений "то что доктор прописал"
Зы Зы
Интересно, а можно ли браузер таким же образом вызвать?
(А то мучать огромадный ХромАпи из за нужды показать одну страничку изрядно накладно )
Код: Выделить всё
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 круче !
Зы
Если планируется изменение размера формы или панели
Нужно добавить вот такую заплатку....
Код: Выделить всё
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);
Вообщем для интеграции разных утилит и плагинов внутрь своих приложений "то что доктор прописал"
Зы Зы
Интересно, а можно ли браузер таким же образом вызвать?
(А то мучать огромадный ХромАпи из за нужды показать одну страничку изрядно накладно )
- Снег Север
- долгожитель
- Сообщения: 3070
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Кушайте на здоровье! 
Спасибо !
Браузер запустился но работает немного странновато
( временами черный или белый "квадрат малевича" показывает при клике на него мышкой ).
( временами черный или белый "квадрат малевича" показывает при клике на него мышкой ).
Последний раз редактировалось Alex2013 25.12.2019 01:26:24, всего редактировалось 1 раз.
Небольшая проблема ! Пытался сделать тоже самое но без FindWindow (Потому что определить заголовок в окне современного браузера дело почти безнадежное )
Написал примерно вот такой код:
Но он не работает похоже что ExecInfo.hProcess это что угодно но не Handle окна ( хотя по идее он должен быть как-то с ним связан).
Но что я не делал получить хедел не получилось . Вопрос что я не так делаю ?
Написал примерно вот такой код:
Код: Выделить всё
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 писал(а):Вопрос что я не так делаю ?
Из WinAPI:
hProcess
Type: HANDLE
A handle to the newly started application.
Тут слово "окно" где-то есть?
- Снег Север
- долгожитель
- Сообщения: 3070
- Зарегистрирован: 27.11.2007 15:14:47
- Контактная информация:
Alex2013, тут придется повозиться. Общий путь примерно такой:
- по названию процесса получить его PID
- перечислить все окна десктопа, для каждого окна средствами GetWindowsThreadProcessID получить PID процесса-владельца, сравнить с искомым
- для найденного окна получить его "имя" - GetWindowText
- по названию процесса получить его PID
- перечислить все окна десктопа, для каждого окна средствами GetWindowsThreadProcessID получить PID процесса-владельца, сравнить с искомым
- для найденного окна получить его "имя" - GetWindowText
Vadim писал(а):Alex2013 писал(а):Вопрос что я не так делаю ?
Из WinAPI:hProcess
Type: HANDLE
A handle to the newly started application.
Тут слово "окно" где-то есть?
Уел !
Но что такое "handle недавно запущенного приложения" PID процесса что ли ?
Добавлено спустя 10 минут 36 секунд:
Снег Север писал(а):Alex2013, тут придется повозиться. Общий путь примерно такой:
- по названию процесса получить его PID
- перечислить все окна десктопа, для каждого окна средствами GetWindowsThreadProcessID получить PID процесса-владельца, сравнить с искомым
- для найденного окна получить его "имя" - GetWindowText
Ладно буду копать дальше!
Добавлено спустя 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; ...не работает.
Alex2013 писал(а):Но что такое "handle недавно запущенного приложения" PID процесса что ли ?
А бес его знает, но явно что-то полезное...
Вам Снег Север правильно написал. Все главные окна запускаемых приложений - "дети" десктопа. Поэтому нужен список окон, которые впиявились в десктоп и уж по списку проверять, принадлежит окно процессу или нет.
Можно ещё попробовать EnumThreadWindows(), но опять же, не специалист, может быть и не то...
Так работает но... "Ужасающий истина!"..
ничего кроме far.exe и прочих консольных приблуд не "удочеряет" ....
Код: Выделить всё
{$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;
