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

Delphi Discussion :

Mettre une fenêtre externe au premier plan


Sujet :

Delphi

  1. #1
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut Mettre une fenêtre externe au premier plan
    Bonjour à tous,
    J'ai une application qui ouvre une deuxième Form en mode modal.
    Pendant l'ouverture de cette deuxième Form, je lance lance l'ouverture d'un fichier texte et je souhaite que ce fichier s'affiche à un endroit précis sur mon écran
    Voici mon code :
    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
    procedure TForm2.FormShow(Sender: TObject);
    var Hdl:Thandle;
        TitreFenetre:string;
        X,Y:integer;
        i:integer;
     
    begin
      CentrerFichesurFicheAvecOffet(Form2,Form1,0,0); //procedure pour centrer une fiche par rapport à une autre avec offsets (ici offsets nuls)
     // Affichage du fichier texte externe
     ShellExecute(Handle,'open',PChar(Nom_Fichier),nil,nil,SW_SHOW); 
     
     // Position de la fenêtre de notepad     
     X:=Form2.left-320;
     Y:=Form1.Top;
     
     TitreFenetre := ExtractFileName(Nom_Fichier)+#160'- Bloc-notes'; // indispensable de mettre #160 sinon on ne retrouve par la fenêtre
     Hdl := FindWindow('NotePad', Pchar(TitreFenetre));
     
     SetWindowPos(hdl,HWND_TOPMOST,X,Y,300,500,0);  // Pour forcer le placement de la fenêtre notepad à gauche de Form2
     
    end;
    Ca ne fonctionne pas , ma fenêtre Notepad ne change pas de place

    Mais si je fais ceci, la fenêtre s'affiche à la position voulue :

    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
    procedure TForm2.FormShow(Sender: TObject);
    var Hdl:Thandle;
        TitreFenetre:string;
        X,Y:integer;
        i:integer;
    
    begin
      CentrerFichesurFicheAvecOffet(Form2,Form1,0,0); //procedure pour centrer une fiche par rapport à une autre avec offsets (ici offsets nuls)
     // Affichage du fichier texte externe
     ShellExecute(Handle,'open',PChar(Nom_Fichier),nil,nil,SW_SHOW); // laisser ici
    
    showmessage(''); // ligne rajoutée   Si on met Form1.repaint à la place , ca ne marche pas non plus 
    
     // Position de la fenêtre de notepad     
     X:=Form2.left-320;
     Y:=Form1.Top;
    
     TitreFenetre := ExtractFileName(Nom_Fichier)+#160'- Bloc-notes'; // indispensable de mettre #160 sinon on ne retrouve par la fenêtre
     Hdl := FindWindow('NotePad', Pchar(TitreFenetre));
     
     SetWindowPos(hdl,HWND_TOPMOST,X,Y,300,500,0);  // Pour forcer le placement de la fenêtre notepad à gauche de Form2
    
    end;
    Avez-vous une idée ?

    Merci de vos réponses
    Jean-Louis

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 454
    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 454
    Points : 24 866
    Points
    24 866
    Par défaut
    Je joue avec SetForegroundWindow pour ce genre de chose
    Attention, en DEBUG sous Delphi, le comportement n'est pas le même que si tu lances l'EXE en autonome

    ShellExecuteEx renvoie un handle exploitable pour récupérer les fenêtres du module autrement que FindWindow
    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

  3. #3
    Membre expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Points : 3 611
    Points
    3 611
    Par défaut
    En fait il faut tout simplement prendre en compte le délai de lancement du programme qu'on exécute.

    Le showmessage() est bloquant, il laisse le temps à l'OS de faire son job, au notepad de s'exécuter, donc quand on sort du showmessage() le reste a bien un programme à trouver.

    Une boucle avec un délai permettrait de vérifier si le notepad s'est ouvert avant de lui envoyer des modifs. En revanche penser à une condition de sortie de boucle au bout d'un temps X ou d'un nombre d'occurrences car si le programme ne se lance pas, on bloque tout et c'est TRES mal.

  4. #4
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Je joue avec SetForegroundWindow pour ce genre de chose
    Attention, en DEBUG sous Delphi, le comportement n'est pas le même que si tu lances l'EXE en autonome

    ShellExecuteEx renvoie un handle exploitable pour récupérer les fenêtres du module autrement que FindWindow
    Je ne vois pas comment récupérer le Handle avec ShellExecute.

    D'autre par, SetForeGroundWindow ne marche pas car FindWindow, dans mon cas, me renvoie toujours "0" sauf si je mets la ligne "showmessage()".

    JL

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 454
    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 454
    Points : 24 866
    Points
    24 866
    Par défaut
    Et cela peut prendre du temps selon l'application, Notepad, c'est surement qu'exemple car un TMemo Lines LoadFromFile ferait très bien le job

    il faut attendre que l'application en face soit prête, j'avais bricolé un échange de message entre application, sans devoir me taper du DDE

    code compler de TSLTShellExecuteWrapper

    Voici la partie expliquée par pprem spécifique à mon système de message
    je fais une boucle à du type repeat Sleep(100) ProcessMessages until FindWindow > 0pour éviter que cela soit trop long, je plafonne à 5s d'attente, la boucle est abandonée
    Sleep, comme le pprem, on sait qu'un autre programme doit bosser, on lui laisse du temps
    ProcessMessages, si l'autre programme est long à démarrer, on évite que notre application semble figé ("Pas de réponse")
    FindWindow, tu connais

    comme je ne lance que mes propres applis, j'ai fait un truc à ma sauce
    sinon, c'est du OLE Excel, le problème de chargement du process est géré implicitement.
    ou encore, c'est des BAT, alors tout est basé sur les Pipes,
    je n'ai pas lancé de programme tiers via l'extension de fichier via ShellExecute depuis une bonne dizaine d'année, je préfère CreateProcess et WaitForSingleObject

    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
    //------------------------------------------------------------------------------
    function TSLTShellExecuteWrapper.WaitResponse(): Boolean;
    var
      SleepCount: Cardinal;
      Msg: TMsg;
    begin
      SleepCount := 0;
     
      // Attend que le programme appelant fournisse les identifiants
      repeat
        if SleepCount < 5000 then
        begin
          Sleep(1); // Environ 1.995 ms dont au plus 10s d'attente
          Inc(SleepCount);
          if PeekMessage(Msg, FWindowHandle, WM_COPYDATA, WM_COPYDATA, PM_REMOVE) then
          begin
            TranslateMessage(Msg);
            DispatchMessage(Msg); // -> WndProc
          end;
        end
        else
          FAborted := True;
     
      until FReady or FAborted;
     
      Result := FReady;
    end;



    Sinon, je parlais de ShellExecuteEx, cette version renvoie un handle hProcess du processus, qui permet de faire un EnumWindows, Get Windows GW_CHILD
    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

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 454
    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 454
    Points : 24 866
    Points
    24 866
    Par défaut
    Je l'avais encore, bon c'est du D7, cela a plus de 10 ans, je ne l'ai pas tester mais c'est l'idée la boucle à faire

    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
    procedure TFormTest.BtnExplorerClick(Sender: TObject);
    var
       HandleEx: Cardinal;
       Dir: string;
       CountTest: Integer;
    begin
       Dir := InputBox('Dossier à Visualiser', 'Saisissez le Répertoire', ExtractFileDir(Application.ExeName));
       HandleEx := ShellExecute(Self.Handle, 'open', PChar(Dir), nil, nil, SW_HIDE);
       Sleep(100);
       HandleByClass := 0;
       CountTest := 0;
       while (HandleByClass = 0) and (CountTest < 1000) do
       begin
          HandleByClass := FindWindow('CabinetWClass', PChar(Dir));
          Inc(CountTest);
          Sleep(1);
       end;
     
       HandleChild := FoundChild(HandleByClass, 'SysListView32', 'FolderView');
        // HandleChild := FoundChild(HandleByClass, 'SHELLDLL_DefView', '');
       if HandleChild > 0 then
       begin
          HandleOld := SetParentEx(HandleChild, PanelDialog.Handle)
       end;
     
       ShowMessageFmt('Ex %d, Class %d, Child %d, Old %d', [HandleEx, HandleByClass, HandleChild, HandleOld]);
    end;
     
    procedure TFormTest.BtnExplorerShImgVwClick(Sender: TObject);
    var
       HandleByClass: Cardinal;
       Path: string;
       CountTest: Integer;
       Box: TScrollBox;
       Panel: TPanel;
    begin
       Path := InputBox('Fichier à Visualiser', 'Saisissez le Fichier', ExtractFilePath(Application.ExeName));
       ShellExecute(Self.Handle, 'open', 'rundll32.exe', PChar('C:\WINDOWS\System32\shimgvw.dll,ImageView_Fullscreen ' + Path), nil, SW_NORMAL);
       Sleep(100);
       HandleByClass := 0;
       CountTest := 0;
       while (HandleByClass = 0) and (CountTest < 1000) do
       begin
          HandleByClass := FindWindow('ShImgVw:CPreviewWnd', nil);
          Inc(CountTest);
          Sleep(1);
       end;
     
       if HandleByClass > 0 then
       begin
          ShowWindow(HandleByClass, SW_RESTORE);
          SetWindowPos(HandleByClass, 0, Application.MainForm.Left + Application.MainForm.Width, Application.MainForm.Top, Screen.WorkAreaWidth - (Application.MainForm.Left + Application.MainForm.Width), Application.MainForm.Height, SWP_SHOWWINDOW);
       end;
     
    //   ShowMessageFmt('Ex %d, Class %d, Child %d, Old %d', [HandleEx, HandleByClass, HandleChild, HandleOld]);
    end;
    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

  7. #7
    Membre régulier
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2010
    Messages
    104
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2010
    Messages : 104
    Points : 85
    Points
    85
    Par défaut
    Merci de vos réponses.
    Voici ce que j'ai fait et qui marche (d'après une réponse faite sur ce même forum juste avant de prendre connaissance de vos réponses !!!)
    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
    procedure TForm2.FormShow(Sender: TObject);
    var Hdl:Thandle;
        TitreFenetre:string;
        X,Y:integer;
        i:integer;
     
    begin
      CentrerFichesurFicheAvecOffet(Form2,Form1,0,0); //procedure pour centrer une fiche par rapport à une autre avec offsets (ici offsets nuls)
     // Affichage du fichier texte externe
     ShellExecute(Handle,'open',PChar(Nom_Fichier),nil,nil,SW_SHOW); 
     
     // Position voulue de la fenêtre de notepad     
     X:=Form2.left-320;
     Y:=Form1.Top;
     
     TitreFenetre := ExtractFileName(Nom_Fichier)+#160'- Bloc-notes'; // indispensable de mettre #160 sinon on ne retrouve pas la fenêtre
     
     // Boucle d'attente pour laisser le temps à notepad de s'afficher
     for i := 1 to 40 do begin
       Hdl := FindWindow('NotePad', Pchar(TitreFenetre));
       if Hdl <> 0 then Break;
       Sleep( 50 );
      end;
     
     SetWindowPos(hdl,HWND_TOPMOST,X,Y,300,500,0);  // Pour forcer le placement de la fenêtre notepad à gauche de Form2
     
    end;
    Merci encore de votre aide

    JL

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

Discussions similaires

  1. Mettre une fenêtre popup au premier plan quand on clique sur le lien
    Par metabaron81 dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 28/03/2011, 16h58
  2. Mettre une fenêtre réduite au premier plan
    Par mioux dans le forum Général VBA
    Réponses: 1
    Dernier message: 27/05/2010, 11h57
  3. Mettre une application Access au premier plan
    Par funkyjul dans le forum VBA Access
    Réponses: 6
    Dernier message: 20/05/2008, 15h58
  4. Forcer une fenêtre à rester en premier plan
    Par ValyGator dans le forum Windows
    Réponses: 2
    Dernier message: 20/01/2008, 11h11
  5. Réponses: 12
    Dernier message: 05/09/2007, 14h46

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