IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants VCL Delphi Discussion :

Fenêtre applicative incluse dans un TTabSheet


Sujet :

Composants VCL Delphi

  1. #1
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut Fenêtre applicative incluse dans un TTabSheet
    Bonjour,

    Je travaille sur une reprise d'application actuellement composée de plusieurs EXE (Delphi)
    Dans l'immédiat je voudrais que l'EXE principal ouvre dans un onglet d'un classeur un EXE correspondant à un des EXE composant l'application actuelle

    Cela fonctionne avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       newtabsheet:=TTabSheet.Create(ClasseurOnglet);
       newtabsheet.pagecontrol:=ClasseurOnglet;
       ShellExecute(Application.Handle,'Open', PChar(LC_ProvisoireEXE), PChar(LC_ProvisoireParam), nil,SW_SHOWDEFAULT);
       while LO_ProvisoireHandle = 0 do LO_ProvisoireHandle := FindWindow(nil, PChar(LC_Caption));
       Windows.SetParent(LO_ProvisoireHandle, newtabsheet.Handle);
       Windows.ShowWindow(LO_ProvisoireHandle, SW_SHOWMAXIMIZED);
    Mon problème intervient si l'utilisateur ferme l'EXE appelé par la croix de fermeture Windows.
    Dans ce cas la fenêtre se ferme mais l'onglet apparaît vide dans l'application principale.

    Je cherche l'evènement déclenché dans l'EXE principal sur lequel je pourrais mettre un code genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseurOnglet.ActivePage.Close;
    Il me reste la possibilité d'un Timer qui exploire régulièrement les onglets vides mais cela ne me branche pas trop

    Merci de vos idées

  2. #2
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    utilise les méthodes onshow et onhide du TTabSheet
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  3. #3
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Je viens d 'ajouter l'évenement OnShow au moment ou je créé l'onglet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     newtabsheet.OnShow  := TabSheet1Show;
    Pas de problème il se déclenche bien au moment où l'onglet vient d'être créé et quand la fenetre contenant l'EXE s'affiche
    Par contre quand la fenêtre se ferme l'évènement n'est pas appelé

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Utilise sinon un SendMessage
    Si tu peux modifier le code des deux applications,
    lorsque le sous-exe appelé par shellexecute ferme sa fenêtre,
    cela envoi un SendMessage à l'application principale
    le Handle du l'application principale peut être passé en comme paramètre dans le ShellExecute par exemple

    tu peux utiliser RegisterWindowMessage pour obtenir un numéro de message commun entre l'appelant et l'appelé identifier par une chaine
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Merci.

    Je voudrais ne pas modifier le code actuel des applications appelées.
    Pour des raisons contractuelles surtout.

    Je sais c'est pénible.

  6. #6
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 418
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 418
    Points : 5 816
    Points
    5 816
    Par défaut
    salut

    ton problème n'est pas simple, si le programme principale n'as pas de moyen de savoir que le sous programme se ferme.

    il va falloir que tu crée un boucle de surveillance avec la fonction IsWindowVisible
    si ce n'est pas le cas tu ferme le tabsheet
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  7. #7
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    C'est un peu l'idée du TTimer que j'évoquais en commençant ?
    Ca ne me fait pas sauter de joie mais si le TTabShhet contenant une TForm ne reçoit pas d'information quand elle se ferme je n'ai pas d'autres solution
    D'autant que c'est temporaire, juste le temps de réécrire le tout.

    Merci à vous

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 447
    Points : 24 849
    Points
    24 849
    Par défaut
    IsWindowVisible est une bonne idée
    Avec le FindWindow, cherche la fenêtre parent et cache là
    soit par une position inaccessible par exemple,
    soit par un SetVisible(FALSE) comme tu changes le parent, tes composants ne devraient pas être impacté (la disparation du composant ancrée est lié à la gestion mémoire de Delphi sur Controls[] et Components[])

    Faudrait voir aussi un CreateProcess au lieu d'un ShellExecute
    Avec CreateProcess dans un TThread, tu pourrais via WaitForSingleObjet surveiller la présence de l'exe, si l'exe disparait, ton onglet aussi
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Si le seul soucis est ce bouton de fermeture, autant supprimer la barre de titre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    setWindowLong(Wnd, GWL_STYLE, WS_SIZEBOX);
    A placer avant SetParent.


    Citation Envoyé par ShaiLeTroll Voir le message
    Avec CreateProcess dans un TThread, tu pourrais via WaitForSingleObjet surveiller la présence de l'exe, si l'exe disparait, ton onglet aussi
    C'est le mieux L'arrêt brutal par le gestionnaire de tâches est ainsi aussi supporté
    Mais je préfère ShellExecuteEx qui permet aussi de supprimer cette boucle sur FindWindow en spécifiant SEE_MASK_WAITFORINPUTIDLE. Ce flag indique d'attendre la fin du démarrage du thread principal avant de continuer, la fiche principale est "normalement" créée au retour de ShellExecuteEx (sinon au moins mettre un sleep dans la boucle).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    type
      TWaitProcessThread = class(TThread)
      private
        Process: THandle;
      protected
        procedure Execute; override;
      public
        constructor Create(aProcess :THandle; aOnTerminate :TNotifyEvent);
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      public
        procedure OnTerminate(Sender :TObject);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    uses ShellAPI;
     
    {$R *.dfm}
     
    { TWaitProcessThread }
     
    constructor TWaitProcessThread.Create(aProcess: THandle; aOnTerminate: TNotifyEvent);
    begin
      inherited Create;
     
      Process         := aProcess;
      OnTerminate     := aOnTerminate;
      FreeOnTerminate := TRUE;
    end;
     
    procedure TWaitProcessThread.Execute;
    begin
      WaitForSingleObject(Process, INFINITE);
      CloseHandle(Process);
    end;
     
    { TForm6 }
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      Info :TShellExecuteInfo;
      Wnd  :hWnd;
    begin
      ZeroMemory(@Info, SizeOf(Info));
      Info.cbSize := SizeOf(TShellExecuteInfo);
      Info.fMask  := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_WAITFORINPUTIDLE;
      Info.lpFile := 'notepad.exe';
     
      if ShellExecuteEx(@Info) then
      begin
        Wnd := FindWindow(nil, 'Sans titre - Bloc-notes');
     
        setWindowLong(Wnd, GWL_STYLE, WS_SIZEBOX);
        Windows.SetParent(Wnd, Handle);
        ShowWindow(Wnd, SW_SHOWMAXIMIZED);
     
        TWaitProcessThread.Create(Info.hProcess, OnTerminate);
      end;
    end;
     
    procedure TForm1.OnTerminate(Sender: TObject);
    begin
      Caption := 'Terminé';
    end;

  10. #10
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Merci

    Je ne parviens pas à faire fonctionner l'exemple.
    J'ai créé un projet de test.
    La ligne setWindowLong(Wnd, GWL_STYLE, WS_SIZEBOX) empèche de retrouver l'handle et donc ne positionne pas l'EXE correctement. Compte tenu que cela sert à cacher la barre de titre je ne sais pas si on peut la laisser ou non

    Par contre quand je ferme l'EXE appelé on ne rentre pas dans l'évènement onTerminate.



    Voici le code. J'ai fait juste un copier/coller
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ShellAPI, ExtCtrls;
     
    type
      TWaitProcessThread = class(TThread)
      private
        Process: THandle;
      protected
        procedure Execute; override;
      public
        constructor Create(aProcess :THandle; aOnTerminate :TNotifyEvent);
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        Panel1: TPanel;
        procedure Button1Click(Sender: TObject);
      public
        procedure OnTerminate(Sender :TObject);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
     
    {$R *.dfm}
     
    { TWaitProcessThread }
     
    constructor TWaitProcessThread.Create(aProcess: THandle; aOnTerminate: TNotifyEvent);
    begin
      inherited Create(true);
     
      Process         := aProcess;
      OnTerminate     := aOnTerminate;
      FreeOnTerminate := TRUE;
    end;
     
    procedure TWaitProcessThread.Execute;
    begin
      WaitForSingleObject(Process, INFINITE);
      CloseHandle(Process);
    end;
     
    { TForm6 }
     
    procedure TForm1.Button1Click(Sender: TObject);
    const
    SEE_MASK_WAITFORINPUTIDLE =$2000000;
    var
      Info :TShellExecuteInfo;
      Wnd  :hWnd;
     
    begin
      ZeroMemory(@Info, SizeOf(Info));
      Info.cbSize := SizeOf(TShellExecuteInfo);
      Info.fMask  := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_WAITFORINPUTIDLE;
      Info.lpFile := 'C:\Developpements\Test_Delphi\TransfertMails\TransMail.exe';
     
      if ShellExecuteEx(@Info) then begin
        Wnd := 0;
        Sleep(100);
        Application.ProcessMessages;
        Sleep(100);
        Wnd := FindWindow(nil, PChar('TransMail'));
     
      //  setWindowLong(Wnd, GWL_STYLE, WS_SIZEBOX);
        Windows.SetParent(Wnd, Panel1.Handle);
        Windows.ShowWindow(Wnd, SW_SHOWMAXIMIZED);
     
        TWaitProcessThread.Create(Info.hProcess, OnTerminate);
      end;
    end;
     
    procedure TForm1.OnTerminate(Sender: TObject);
    begin
      showmessage( 'Terminé');
    end;
    end.

  11. #11
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Citation Envoyé par Delphi-ne Voir le message
    La ligne setWindowLong(Wnd, GWL_STYLE, WS_SIZEBOX) empèche de retrouver l'handle et donc ne positionne pas l'EXE correctement.
    Ça n'a normalement aucun rapport. Peut-être un problème de repeinture

    Citation Envoyé par Delphi-ne Voir le message
    Par contre quand je ferme l'EXE appelé on ne rentre pas dans l'évènement onTerminate.
    Ça ne risque pas puisque tu ne démarres pas le thread

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    constructor TWaitProcessThread.Create(aProcess: THandle; aOnTerminate: TNotifyEvent);
    begin
      inherited Create(FALSE);

  12. #12
    Membre confirmé

    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 184
    Points : 619
    Points
    619
    Par défaut
    Merci

    Maintenant cela fonctionne et c'est exactement ce que je voulais proposer au client

    Pour le paramètre à inherited Create c'est moi qui l'ai ajouté.
    Il n'était pas dans l'exemple et cela me provoquait une erreur de compilation
    J'ai valorisé au hazard sans comprendre l'utilité

    Vraiment merci beaucoup

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. fenêtre toujours active dans toute application
    Par Ruyneau dans le forum Tkinter
    Réponses: 2
    Dernier message: 19/12/2011, 19h42
  2. Lancer une application Swing dans une fenêtre SWT
    Par Zlika_ese dans le forum Eclipse Platform
    Réponses: 2
    Dernier message: 08/05/2010, 14h17
  3. Application (EXE) dans une fenêtre du front panel
    Par kastillio dans le forum LabVIEW
    Réponses: 3
    Dernier message: 30/11/2009, 15h49
  4. lancer une application externe dans une fenêtre
    Par lilivounet dans le forum Windows
    Réponses: 0
    Dernier message: 29/07/2007, 16h03
  5. [XSLT]pb application template feuille XSL incluse dans XSL
    Par snoop dans le forum XSL/XSLT/XPATH
    Réponses: 11
    Dernier message: 26/06/2006, 16h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo