Ver Mensaje Individual
  #13  
Antiguo 12-06-2015
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Reputación: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Me permito decir que la API FindWindow tiene las desventaja de tener que conocer el nombre de la clase de ventana o el Caption (este último puede ser cambiante). Lo ideal es poder conocer el Handle de la ventana de un proceso desde su pid.

En ese sentido propongo complicar el código:
Código Delphi [-]
function GetWindowFromPId(PId: DWORD): THandle;
type
  TWinParam = record
    Handle: THandle;
    PId: DWORD;
  end;
  PWinParam = ^TWinParam;
var
  WinParam: TWinParam;

  function EnumWindowsProc(Handle: Thandle; lParam: LPARAM): BOOL; stdcall;
  var
    PId: DWORD;
  begin
    Result:= true;
    PId:= 0;
    GetWindowThreadProcessId(Handle, PId);
    if PWinParam(lParam).PId = PId then
    begin
      PWinParam(lParam).Handle:= Handle;
      Result:= false;
    end;
  end;

begin
  WinParam.Handle:= 0;
  WinParam.PId:= PId;
  EnumWindows(@EnumWindowsProc, LPARAM(@WinParam));
  repeat
    Result:= WinParam.Handle;
    WinParam.Handle:= Windows.GetParent(Result);
  until WinParam.Handle = 0;
end;

// Handle es el de la ventana donde queremos incluir el ejecutable.
function ExecuteAsChild(CommandLine: String; Handle: THandle): THandle;
var
  SI: TStartupInfo;
  PI: TProcessInformation;
  CR: TRect;
begin
  ZeroMemory(@SI, sizeof(TStartupInfo));
  SI.cb:= sizeof(SI);
  Result:= 0;
  if CreateProcess(nil, PCHAR(CommandLine), nil, nil, false, 0, nil, nil, SI, PI) then
  begin
    WaitForInputIdle(PI.hProcess, 10000);
    Result:= GetWindowFromPId(PI.dwProcessId);
    Windows.SetParent(Result, Handle);
    GetClientRect(Handle, CR);
    SetWindowPos(Result, 0, 0, 0, CR.Right-CR.Left, CR.Bottom-CR.Top, SWP_SHOWWINDOW);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end;
end;

Si quisiéramos usar la versión propuesta por duilioisola con ShellExecuteEx en lugar de con CreateProcess, también podemos:

Código Delphi [-]
type
function GetProcessId(hProcess: THANDLE): DWORD; stdcall;  external  Kernel32;

function ExecuteAsChild2(ExeFile: String; Handle: THandle): THandle;
var
  RI: TShellExecuteInfo;
  CR: TRect;
begin
  FillChar(RI, SizeOf(RI), #0);

  RI.cbSize       := SizeOf(RI);
  RI.fMask        := SEE_MASK_NOCLOSEPROCESS;
  RI.lpVerb       := 'Open';
  RI.lpFile       := PChar(ExeFile);
  RI.lpParameters := PChar('');
  RI.lpDirectory  := PChar('');

  Result:= 0;
  if ShellExecuteEx(@RI) then
  begin
    WaitForInputIdle(Ri.hProcess, 5000);
    Result:= GetWindowFromPId(GetProcessId(Ri.hProcess));
    Windows.SetParent(Result, Handle );
    Windows.GetClientRect(Handle, CR);
    SetWindowPos(Result, 0, 0, 0, CR.Right-CR.Left, CR.Bottom-CR.Top, SWP_SHOWWINDOW);
    CloseHandle(RI.hProcess);
  end;
end;


Saludos.

Última edición por escafandra fecha: 12-06-2015 a las 13:48:32.
Responder Con Cita