(Solved) Set proprietario e setparent di eseguibile esterno

di il
6 risposte

(Solved) Set proprietario e setparent di eseguibile esterno

Buonasera, mi rivolgo a voi per chiedere un aiuto.

Su una macchina Windows 11 64 bit dotata di Delphi 11 sto cercando una soluzione a questo problema.

Ho una applicazione VCL WIN32 con il form principale di nome Form1 che contiene un panel di nome Pnl1
L'applicazione viene eseguita come modale ma se necessario posso cercare il modo di eseguirla non modale.
La mia necessità è quella di contenere su Pnl1 la finestra di esecuzione di un eseguibile esterno. L'eseguibile esterno è un'altra procedura scritta con Delphi che viene avviata in modo non modale e che ha come nome del form principale Form11 e come nome dell'applicazione scm22_11.exe.
Ho una variabile di tipo Handle di nome myHandle dichiarata in questo modo

Var
MyHandle: THandle;

di seguito le righe con cui lancio l'eseguibile e ricavo il suo Handle

ShellExecute(application.handle, 'Open', 'E:\release\scm22_11.exe', nil, nil, SW_SHOW);
sleep(1000);
myHandle := FindWindow('Form11', nil);

Fatto questo (il programma parte e funziona benissimo anche se ostinatamente totalmente svincolato dal pannello in cui invece io vorrei che vivesse), credo che dovrei dire:

a Form1 che la finestra dell'eseguibile esterno è di sua proprietà,
a Pnl1 che è il genitore della finestra dell'eseguibile esterno
e alla finestra dell'eseguibile esterno che è figlia di Pnl1.

Solo che tutti i miei tentativi di fare queste operazioni non hanno portato a nulla. L'eseguibile esterno va benissimo quando viene avviato ma ostinatamente svincolato dalla panel a cui vorrei fosse ancorato.

Qualcuno potrebbe aiutarmi a risolvere il problema? Grazie

6 Risposte

  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    Polaris ha scritto:


    Ho una applicazione VCL WIN32 con il form principale di nome Form1 che contiene un panel di nome Pnl1
    L'applicazione viene eseguita come modale ma se necessario posso cercare il modo di eseguirla non modale.
    Innanzitutto, non è chiaro cosa intendi per "modale" riferendoti all'applicazione: la caratteristica di essere o meno "modale" è applicata a un Form, generalmente un Form secondario che è quindi "modale" rispetto a quello che lo ha aperto, ossia che deve essere chiuso prima che il controllo della UI possa tornare alla finestra chiamante.

    Polaris ha scritto:


    La mia necessità è quella di contenere su Pnl1 la finestra di esecuzione di un eseguibile esterno.
    Questo temo non sia possibile, a meno di non prevedere una specifica integrazione tra le due applicazioni unendole in un unico processo, in quanto ciascun eseguibile ha vita a sé stante: la memoria allocata da ciascun processo così come gli oggetti e tutto il resto, tralasciando quelli creati ma esplicitamente appartenenti al sistema operativo (ad esempio, un mutex), sono a uso esclusivo del processo che gira in isolamento dagli altri.

    Devi quindi accontentarti del modo in cui attualmente richiami il programma, o prevedere una integrazione esplicita e specifica tra i due (e nel caso è possibile valutare diverse soluzioni in base all'intento, ma l'eseguibile sarà comunque uno solo).

    Ciao!
  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    Alka grazie della risposta.

    Modale perchè avviata con self.showModal in onCreate e chiusa con closeModal (ci sono alcuni motivi legati alla corretta funzionalità di alcuni controlli in win 11 che per ora fino al trovare altra soluzione mi hanno portato a questa soluzione per farli funzionare correttamente).

    Non un unico eseguibile, perdonami ma non ho accennato nulla di simile. Ho chiesto come posso fare a fare in modo che una applicazione esterna funzioni ancorata al panel form1.pnl1 come si fa comunemente per esempio in molte applicazioni Delphi con notepad o con pdfreader che vengono eseguite ovviamente in processo separato ma la loro finestra viene ancorata sulla superfice del panel.
  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    Polaris ha scritto:


    Modale perchè avviata con self.showModal in onCreate e chiusa con closeModal (ci sono alcuni motivi legati alla corretta funzionalità di alcuni controlli in win 11 che per ora fino al trovare altra soluzione mi hanno portato a questa soluzione per farli funzionare correttamente).
    Se parliamo del MainForm, che sia modale o non modale non cambia nulla, ma non avendo dettagli né codice né riferimenti riguardo quello di cui si sta parlando, non mi è possibile esprimere altro (se non che "modale" per il Form principale, se si tratta di quello, continua a non aver senso).

    Polaris ha scritto:


    Non un unico eseguibile, perdonami ma non ho accennato nulla di simile.
    Io ti perdono, ma l'ho accennato io perché senza un unico eseguibile, quanto chiedi non si può fare.

    Polaris ha scritto:


    Ho chiesto come posso fare a fare in modo che una applicazione esterna funzioni ancorata al panel form1.pnl1 come si fa comunemente per esempio in molte applicazioni Delphi con notepad o con pdfreader che vengono eseguite ovviamente in processo separato ma la loro finestra viene ancorata sulla superfice del panel.
    Partendo dall'equivoco di "modale", anche qui è necessario intenderci sui termini e assicurarci che stiamo dicendo la stessa cosa: negli scenari di cui stai parlando, le applicazioni non vengono eseguite in un processo separato, ma fanno parte del medesimo processo.

    Se per PDF Reader ti riferisci al controllo ActiveX di Acrobat Reader, quello è appunto un controllo ActiveX: appartiene a una tecnologia che consente di integrare un controllo visuale (esposto tramite tecnologia COM/ActiveX, appunto) all'interno di un'apposita superficie di host, ma occorre utilizzare COM/ActiveX come "bridge" tra i due elementi per poter integrare l'interfaccia all'interno dell'applicazione, e ciò avviene con regole ben precise.

    OItre a questo approccio vi sono diverse alternative per la comunicazione intraprocesso, ma per "ospitare" qualcosa di un'applicazione all'interno di un'altra applicazione, non è sufficiente dire all'una che deve visualizzarsi nell'altra: occorre implementare uno degli standard di comunicazione intra/infra processi e sfruttarlo in entrambi i progetti affinché "parlino la stessa lingua" per poter poi eseguire l'integrazione vera e propria.

    Questi bridge esistono proprio perché, in tutti gli altri casi e in loro assenza, ciascun processo è isolato.

    Per far cooperare i processi condividendo logica e addirittura elementi dell'interfaccia utente, è necessario adottare tecnologie specifiche come quelle suindicate.

    Spero di aver chiarito i dubbi.

    Ciao!
  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    La questione funzionando da sempre negli SO precedenti a Win 11 doveva funzionare anche in win 11 e infatti così è stato. L'inserimento della Unit Windows nello Uses con il nome attuale di Winapi.Windows ha generato il problema ma una volta verificato che la attuale Winapi.Windows.pas è rentrocompatibile con le vecchia Windows.pas il tutto si è risolto da se. Il frammento di codice utile ad ancorare un eseguibile esterno a un panel della form è il seguente (Magari la cosa può essere utile ad altri);

    procedure testExeInPanel;
    var
    MyHandle: THandle;
    begin
    ShellExecute(form1.handle, 'Open', 'E:\release\scm22_11.exe', nil, nil, 0);
    sleep(1000);
    myHandle := winapi.windows.FindWindow('TForm11', nil); // Form11 è la mainForm di scm22_11.exe
    winapi.Windows.SetParent(myHandle, form1.pnl1.Handle);
    SetWindowPos(myHandle, 0, 5, 3, 1578, 155, SWP_ASYNCWINDOWPOS);
    ShowWindow(myHandle, SW_SHOW);
    end;

    Form1 avvia l'eseguibile tramite ShellExecute che ha l'ultimo parametro a 0 per evitare che la finestra del
    exe chiamato, si apra in una posizione a casaccio.
    lo sleep di un secondo da il tempo all'exe di avviarsi in modo che poi findwindow ne trovi l'handle assegnandolo a myhandle.
    SetParent assegna l'handle dell'applicazione come figlio di pnl1, setWindowPos ne definisce la posizione sul
    panel e showWindow lo visualizza appunto ancorato sulla superfice del panel.
    Tutto questo avviene in modo semplice e ovvio e non ha bisogno di alcuna alchimia strana ma è altamente
    sconsigliabile incapsulare nel panel le fiestre di applicazioni di cui non si conosce perfettamento il comportamento.

    Ringrazio comunque tutti dell'attenzione.
  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    Polaris ha scritto:


    La questione funzionando da sempre negli SO precedenti a Win 11 doveva funzionare anche in win 11 e infatti così è stato.
    [...]
    Ho fatto una prova del codice che hai postato giusto per assicurarmi quali sono le cose che non ho compreso dello scenario presentato (visto che hai detto che funziona, e quindi evidentemente non ho compreso a fondo cosa intendevi).

    Ho creato un prototipo di applicazione "host" e una "guest", visualizzando nella prima una finestra della seconda, con un risultato simile al seguente: Al netto dell'aspetto "grezzo" e ad alcune feature probabilmente indesiderate (tipo il fatto di poter spostare la finestra), effettivamente si ottiene la visualizzazione della finestra all'interno del pannello.

    Occorre però tenere presente che, come anticipato, il processo esterno non è propriamente "del tutto esterno" (questo per spiegare a cosa mi stavo riferendo nei messaggi precedenti); infatti nel Task Manager appare così: Il processo secondario è quindi incorporato come "figlio" del primario e la vita del primo è strettamente correlata al secondo. Non è quindi solo una questione di visualizzazione, ma esiste una condivisione di spazi tra i due, che in questo caso potrebbe anche risultare utile, ma è giusto precisare che i processi non sono indipendenti, o almeno non come io l'avevo inteso dall'inizio, da cui il resto delle incomprensioni.

    Detto questo, esiste tutta una gamma di effetti collaterali legati alla vita dell'applicazione Delphi in sé, il passaggio di messaggi tra componenti e controlli (che è un aspetto particolare di Delphi) e altri meccanismi che cessano di funzionare in questo contesto.

    Voglio dire, gli esempi che sono stati presi a campione - vedi Wordpad o il controllo PDF Reader - sono ben altra cosa rispetto a questo tipo di implementazione, e io a queste facevo riferimento.

    Per riassumerla in due parole, al di là del "reparenting" della finestra dell'applicazione esterna all'interno di un altra finestra presente nel sistema, con tutta la serie di effetti collaterali che ne conseguono, non c'è un'altra forma reale di integrazione tra le due parti e la cosa non funziona globalmente se non per un'applicazione appositamente progettata per essere utilizzata in questo modo, con tutta una serie (indefinita) di limitazioni e restrizioni, o di accorgimenti da prendere affinché il gioco funzioni, con la possibilità che un domani poi cessi di farlo (non concordo sull'affermazione "ciò che funziona in W10 funziona anche in W11 e successive, intesa in termini globali, tant'è che - ad esempio - sul supporto MDI e su altre API molte cose sono cambiate da versione a versione). Io lo chiamo "accrocchio", e in ogni caso a un mio cliente non lo proporrei.

    Però se questo era il risultato che si voleva raggiungere comunque, buono a sapersi perché onestamente non pensavo si potesse nemmeno realizzare (per i motivi indicati sopra), mentre evidentemente Windows "chiude un occhio" e lo tollera.

    Grazie quindi per l'approfondimento e il chiarimento doveroso: ho scoperto una cosa in più.
  • Re: (Solved) Set proprietario e setparent di eseguibile esterno

    Ciao AIka.
    Sono API di windows che lo permettono in modo nativo. Come hai notato il risultato esclude completamente la personalizzazzione della GUI, volendo la si può customizzare ma l'impresa non vale la spesa di tempo e impegno per farlo. Questa implementazione è puramente di scopo e va utilizzata con molta attenzione. Uno dei modi in cui è stata negli anni utilizzata è stata quella di incorporare notepad, avendo così disponibile nel programma un comodo editor di testo già bello e pronto senza doversi preoccupare di altro perchè la chiamata a notepad si può fare indicandogli anche il documento che deve aprire. Io lo uso in questo caso per una cosa molto diversa. il multitasking gestito direttamente da Windows è molto più efficente di quello gestito da programma e permette inoltre di avere una GUI per ogni task (cosa comoda in più di una circostanza), invece di far girare solo procedure in background. Volendo si può condividere anche l'ambiente usando puntatori alla memoria fisica e un sistema di semafori ma è una cosa che io eviterei di fare.

    Un Caro saluto.
Devi accedere o registrarti per scrivere nel forum
6 risposte