Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Externes Programm in Panel laufen lassen (https://www.delphipraxis.net/52200-externes-programm-panel-laufen-lassen.html)

Jelly 25. Aug 2005 10:55


Externes Programm in Panel laufen lassen
 
Hallo,

In Bezug auf diesen Thread nutze ich folgenden Code, um aus einer Anwendung 1 eine 2. zu starten, die dann in einem Panel aus Anwendung 1 angezeigt werden soll:
Delphi-Quellcode:
       
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
        StartupInfo.cb         := SizeOf(StartupInfo);
        StartupInfo.dwFlags    := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
        StartupInfo.wShowWindow := SW_SHOWNORMAL ;
        if Command <> ''
        then StartName := format ('%s "%s"',[Filename,CommandText])
        else StartName := Filename ;
        FPID := 0 ;
        if CreateProcess(nil,@StartName[1],nil,nil,false,CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,nil,nil,StartupInfo,ProcessInfo) then begin
            FPID := Processinfo.dwProcessID ;

            //sleep(2000) ;

            t1 := now ;
            repeat
               if SearchMode = smByClassname
               then FItems.Owner.ChildHandle := FindWindow (PChar(ClassName),nil)
               else FItems.Owner.ChildHandle := FindWindow (nil,PChar(FormCaption)) ;
            until (FItems.Owner.ChildHandle <> 0) or (now-t1 > EncodeTime(0,0,5,0)) ;

            { Eventuell im Panel anzeigen }
            if RunInPanel then begin
                if (FItems.Owner.ChildHandle <> 0) and assigned(Panel) then begin
                    Windows.SetParent(FItems.Owner.ChildHandle, Panel.Handle);
                    ShowWindow(FItems.Owner.ChildHandle, SW_MAXIMIZE);
                end else begin
                    ShowMessage ('Panel Problem') ;
                end ;
            end ; { im Panel anzeigen }
        end else begin
            Showmessage ('konnte Programm nicht starten') ;
        end ;
Es taucht dabei ein skuriles Phänomen auf. Die 2. Anwendung wird gestartet, jedoch maximized im gesamten Desktop, statt im Panel. Lass ich eine Sleep(2000) Pause nach der Prozesserzeugung den Ablauf bremsen, so klappts einwandfrei... Nun ist diese Sleep-Lösung aber sicherlich nicht die feine englische Art.

Das Komische daran ist, dass ich vor
Delphi-Quellcode:
if RunInPanel then begin...
sowohl Handle als auch FPID habe. Warum funktioniert der Code nicht zum Anzeigen des Forms im Panel ?

SirThornberry 25. Aug 2005 11:41

Re: Externes Programm in Panel laufen lassen
 
durch das Sleep wird sichergestellt das die andere Anwendung fertig gerstartet ist und du somit das richtige Handle hast. Du schreibst zwar das du schon zuvor das richtige hast aber dem wird nicht so sein. Wenn die zweite Anwendung zum Beispiel mit Delphi erstellt wurde und der Style fsStayOnTop ist so wird an dieser Stelle wo das property gesetzt wird das Fenster neu erzeugt und somit ist das alte Handle nicht mehr gültig.
Zu deiner Sleep-Variante: Das ist eine ziemlich schlechte Lösung, denn wenn der Rechner ausgelastet ist kann es durchaus passieren das dein Sleep zu kurz ist..

teebee 25. Aug 2005 12:11

Re: Externes Programm in Panel laufen lassen
 
Zitat:

Zitat von MSDN
The WaitForInputIdle function enables a thread to suspend its execution until the specified process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronizing a parent process and a newly created child process. When a parent process creates a child process, the CreateProcess function returns without waiting for the child process to finish its initialization. Before trying to communicate with the child process, the parent process can use WaitForInputIdle to determine when the child's initialization has been completed. For example, the parent process should use WaitForInputIdle before trying to find a window associated with the child process.

Schau Dir mal MSDN-Library durchsuchenWaitForInputIdle an. Vielleicht ist das ja was für Dich.

Gruß, teebee

Jelly 25. Aug 2005 13:00

Re: Externes Programm in Panel laufen lassen
 
@SirThornberry:
Deine Erklärung leuchtet mir zwar ein, nur bringst mich nicht wirklich weiter. Ich weiss, dass Sleep schlecht ist, deshalb such ich ja nach einer anderen Lösung.

@teebee:
Hab mir mal deine Funktion angekuckt, scheint aber auch nicht zu klappen... Statt des sleep hab ich jetzt ml Folgendes eingebaut:
Delphi-Quellcode:
WaitForInputIdle (ProcessInfo.hProcess,50000) ;
Ohne Erfolg.

teebee 25. Aug 2005 15:23

Re: Externes Programm in Panel laufen lassen
 
So wie es aussieht, ist das eigentliche Problem nicht das Fensterhandle des erzeugten Prozesses, sonst bliebe der ja unsichtbar. Irgendwie scheint Panel.Handle Null zu sein, dann ist der Parent automatisch der Desktop. Wie das jetzt aber mit dem sleep zusammenhängt ist mir leider nicht klar.
Laut PSDK soll man übrigens noch den Fensterstil WS_CHILD des untergeordneten Fensters setzen und WS_POPUP löschen, bevor man SetParent aufruft, wenn der Parent nicht Null ist
Zitat:

Zitat von MSDN
For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, if hWndNewParent is NULL, you should also clear the WS_CHILD bit and set the WS_POPUP style after calling SetParent. Conversely, if hWndNewParent is not NULL and the window was previously a child of the desktop, you should clear the WS_POPUP style and set the WS_CHILD style before calling SetParent.

Gruß, teebee

Jelly 25. Aug 2005 15:38

Re: Externes Programm in Panel laufen lassen
 
Zitat:

Zitat von teebee
...bevor man SetParent aufruft, wenn der Parent nicht Null ist

Zitat:

Zitat von MSDN
...after calling SetParent.

Also wohl eher danach.

Aber wie mache ich das?

Wenn ich die Anwendung nicht im Panel starten lasse, hab ich das Handle des Hauptfensters. Läufts im Panel, scheint sich dieses Handle bei der Initialisierung wohl irgendwie zu ändern, da ein SetParent nichts mehr bewirkt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz