Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Abrir un Programa Externo dentro de una Ventana de una Aplicación (https://www.clubdelphi.com/foros/showthread.php?t=88469)

albelg 10-06-2015 15:26:54

Abrir un Programa Externo dentro de una Ventana de una Aplicación
 
Hola a todos los colegas el club. necesito hacer un programita que de desde delphi me abra una aplicacion.exe y que esta ultima abra dentro de la ventana de mi programita.
lo que tengo es lo siguiente. gracias de antemano

Código Delphi [-]
procedure tform1.buttonclick(sender:tobject); 
var
 operacion,nombre,parametro,path:string;
begin     
  operacion:='open'; 
  nombre:='MMLCM.exe';
  parametro:='C:\WINDOWS\WIN.INI'; 
  path:='C:\Program Files\DIAX-OM\PROGRAM';
  shellexecute(handle,pchar(operacion),pchar(nombre),pchar(parametro),pchar(path),sw_shownormal);   
end;

duilioisola 10-06-2015 16:03:36

Quizás esto te sirva: http://www.clubdelphi.com/foros/showthread.php?t=50300

duilioisola 10-06-2015 16:09:36

Aquí hay otra opción http://stackoverflow.com/questions/7...-a-delphi-form

Código Delphi [-]
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;

albelg 10-06-2015 17:11:39

gracias hermano por responder pero me da error en la linea:
Código Delphi [-]
  fNotepadHandle := Windows.findwindow('notepad',nil);
?que tipo de variable es fnotepadhandle?

Casimiro Notevi 10-06-2015 17:15:46

Recuerda poner los tags al código fuente, ejemplo:



Gracias :)

aposi 10-06-2015 17:44:35

Cita:

Empezado por albelg (Mensaje 493125)
gracias hermano por responder pero me da error en la linea:

fNotepadHandle:=Windows.findwindow('notepad',nil);

?que tipo de variable es fnotepadhandle?

Código Delphi [-]
  fNotepadHandle : HWND;

albelg 10-06-2015 18:17:41

ya me corrio el programa, pero lo que necesito es que el .exe me abra dentro de mi formulario y no de manera independiente. gracias de antemano

duilioisola 10-06-2015 18:51:00

1 Archivos Adjunto(s)
A mi si que me funciona correctamete:
Temas a tener en cuenta:
fNotepadHandle es del tipo HWND y debe ser global al formulario en el que se trabaja.
En mi caso
Código Delphi [-]
type
  TFMPruebas = class(TG2KForm)
    ...
  private
     { Private declarations }
     fNotepadHandle : HWND;
  public
     { Public declarations }
  end;

Yo he creado un botón y un panel en donde tiene que estar el Notepad.

El botón tiene el código que enivé y rellena la variable fNotepadHandle.
El panel tiene e código de OnResize que utiliza la variable global fNotepadHandle.

albelg 10-06-2015 21:01:00

disculpa si mi pregunta es de novato pero como tu creas el panel para montar el notepad. gracias y por favor no pierda la paciencia conmigo

ecfisa 10-06-2015 21:43:56

Hola abelg.
Cita:

Empezado por albelg (Mensaje 493140)
disculpa si mi pregunta es de novato pero como tu creas el panel para montar el notepad. gracias y por favor no pierda la paciencia conmigo

Solo agrega uno en el formulario en tiempo de diseño, del mismo modo que lo haces con un botón o un edit, etc.

Saludos :)

duilioisola 11-06-2015 09:24:09

Si quieres crear el Panel de forma dinámica puedes hacerlo así:

Código Delphi [-]
type
  TFMPruebas = class(TForm)
...
     procedure PNLEjecutarNotepadResize(Sender: TObject);
  private
     { Private declarations }
     fNotepadHandle : HWND;
...
  public
     { Public declarations }
...
  end;

procedure TFMPruebas.BEjecutarNotepadClick(Sender: TObject);
var
  Rec: TShellExecuteInfo;
  Panel : TPanel;
const
  AVerb = 'open';
  AParams = '';
  AFileName = 'Notepad.exe';
  ADir = '';
begin
  // Crear panel en forma dinamica
  Panel := TPanel.Create(Self);
  with Panel do
  begin
     // Debe estar sobre el Tabsheet
     Parent := TabSheet1;
     // Alineado al total del espacio disponible
     Align := alClient;
     // Cuando cambie de tamaño debe ejecutar esto para ajustar el tamaño del programa ejecutado dentro
     OnResize := PNLEjecutarNotepadResize;
  end;

  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, Panel.Handle );

  // Put the focus on notepad
  Windows.SetFocus( fNotepadHandle );

  Resize;
  ShowWindow(fNotepadHandle, SW_SHOW);
end;

procedure TFMPruebas.PNLEjecutarNotepadResize(Sender: TObject);
begin
  if IsWindow(fNotepadHandle) then begin
    SetWindowPos(fNotepadHandle, 0, 0, 0, TPanel(Sender).ClientWidth, TPanel(Sender).ClientHeight,
      SWP_ASYNCWINDOWPOS);
  end;
end;

albelg 11-06-2015 14:29:11

muchas gracias hermano, me sirvio de mucho y te lo agradezco nuevamente y puedes estar seguro que en mi proyecto daré tus creditos

escafandra 12-06-2015 13:41:51

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.


La franja horaria es GMT +2. Ahora son las 07:42:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi