2012-09-05 17 views
5

Quiero iniciar una aplicación desde Delphi y obtener un control para que pueda incrustar la ventana principal de dicha aplicación en un marco de tipo TFrame. Hasta ahora he intentado:¿Cómo iniciar una aplicación y obtener un control con Delphi?

Function TFrmEmbeddedExe.StartNewApplication : Boolean; 
var 
    SEInfo: TShellExecuteInfo; 
    ExitCode : DWORD; 
begin 

    FillChar(SEInfo, SizeOf(SEInfo), 0) ; 
    SEInfo.cbSize := SizeOf(TShellExecuteInfo) ; 
    with SEInfo do 
    begin 
    fMask := SEE_MASK_NOCLOSEPROCESS; 
    Wnd := self.Handle; 
    lpFile := PChar(self.fexecuteFileName) ;// Example could be 'C:\Windows\Notepad.exe' 
    nShow := SW_SHOWNORMAL;//SW_HIDE; 
    end; 

    if ShellExecuteEx(@SEInfo) then 
    begin 
    sleep(1500); 
    self.fAppWnd := FindWindow(nil, PChar(self.fWindowCaption)); //Example : 'Untitled - Notepad' 
    if self.fAppWnd <> 0 then 
    begin 
     Windows.SetParent(self.fAppWnd, SEInfo.Wnd); 
     ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); 
     result := true; 
    end 
    else 
     result := false; 

    end 

    else 
    result := false; 
end ; 

El código anterior funciona realmente, pero FINDWINDOW encontrará ningún instans dadas de la aplicación empecé. Quiero incrustar las instans exactas que Shellexecuted. Si el Bloc de notas se ha iniciado un par de veces, no hay forma de que pueda obtener el correcto utilizando FindWindow.

que he intentado:

Function TfrmEmbeddedExe.CreateProcessNewApplication : Boolean; 
var 
zAppName: array[0..512] of char; 
StartupInfo: TStartupInfo; 
ProcessInfo: TProcessInformation; 
Res : DWORD; 
DoWait : Boolean; 
begin 
    DoWait := False; 
    StrPCopy(zAppName, self.fexecuteFileName); //'C:\Windows\Notepad.exe' 
    FillChar(StartupInfo, Sizeof(StartupInfo), #0); 
    StartupInfo.cb := Sizeof(StartupInfo); 
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW; 
    StartupInfo.wShowWindow := SW_SHOWNORMAL; 

    if CreateProcess (zAppName, 
    nil, { pointer to command line string } 
    nil, { pointer to process security attributes } 
    nil, { pointer to thread security attributes } 
    false, { handle inheritance flag } 
    CREATE_NEW_CONSOLE or { creation flags } 
    NORMAL_PRIORITY_CLASS, 
    nil, { pointer to new environment block } 
    nil, { pointer to current directory name } 
    StartupInfo, { pointer to STARTUPINFO } 
    ProcessInfo) then { pointer to PROCESS_INF } 
    begin 
    if DoWait then //just set it to false... so it will never enter here 
    begin 
     WaitforSingleObject(ProcessInfo.hProcess, INFINITE); 
     GetExitCodeProcess(ProcessInfo.hProcess, Res); 
    end 
    else 
    begin 
     self.fAppWnd := ProcessInfo.hProcess; 

     Windows.SetParent(self.fAppWnd, self.Handle); 
     ShowWindow(self.fAppWnd, SW_SHOWMAXIMIZED); 
     CloseHandle(ProcessInfo.hProcess); 
     CloseHandle(ProcessInfo.hThread); 


    end; 

    result := true; 
    end 
    else begin 
    Result := false; 
    end; 
end; 

POR FAVOR NO CORRER ENCIMA DE CÓDIGO! Produce resultados extraños que implican elegir una ventana aparentemente aleatoria en todas las aplicaciones en ejecución e incrustar eso (incluso elementos de menú desde el menú de inicio de Windows ...)

Así que básicamente lo que necesito es cómo iniciar una aplicación, y agarrar un identificador a la ventana principal de las aplicaciones.

Cualquier ayuda es muy apreciada

Saludos

Jens Fudge

+5

Un identificador de proceso no es un identificador de ventana. Ver http://stackoverflow.com/questions/1888863/how-to-get-main-window-handle-from-process-id –

+0

Leyendo el título, estaba a punto de entrar e insistir en que esto * debe * ser un duplicar, pero después de ver que está integrando esta aplicación en la suya, eso lo diferencia. Gran pregunta –

+0

No agregue firmas a su publicación. [StackOverflow ya muestra uno para usted] (http://stackoverflow.com/faq#signatures). – Deanna

Respuesta

9

aquí está el esbozo de lo que tiene que hacer. Voy a dejar la codificación depende de usted:

  1. Comience su proceso, ya sea con o ShellExecuteExCreateProcess. Esto generará un identificador de proceso.
  2. Llame al WaitForInputIdle en la palanca de proceso. Esto le da al proceso la oportunidad de cargar e iniciar su ciclo de mensajes.
  3. Pase el identificador del proceso al GetProcessId para obtener el ID del proceso.
  4. Use EnumWindows para enumerar las ventanas de nivel superior.
  5. Pase cada una de estas ventanas a GetWindowThreadProcessId para comprobar si ha encontrado o no la ventana de nivel superior de su proceso de destino.
  6. Una vez que encuentre una ventana cuyo ID de proceso coincida con su proceso objetivo, ¡listo!

No olvide cerrar las asas de proceso una vez que haya terminado con ellas.

+0

David Heffernan, de hecho parece la manera de seguir adelante, y lo haré cuando tenga tiempo. Muchas gracias por explicarme. –

Cuestiones relacionadas