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 :

Parcourir l'intégralité des composants de l'application


Sujet :

Delphi

  1. #1
    Membre éprouvé
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Janvier 2017
    Messages : 358
    Par défaut Parcourir l'intégralité des composants de l'application
    Bonjour,

    Est-il possible de parcourir l'intégralité des composants de l'application, ou dois-je passer par tous les Forms puis parcourir les composants ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    for i := 0 to Form1.ComponentCount - 1 do
      begin
         if Form1.Components[i] is TButton then
           begin
             // ...
           end;
      end;
    Merci
    Vous ne pouvez pas faire confiance à un code que vous n'avez pas totalement rédigé vous-même. :aie:
    Ce n’est pas un bogue - c’est une fonctionnalité non documentée. :lahola:

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 554
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 554
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    J'ai lu quelque part qu'il existait un application.componentcount (et donc application.components) toutefois mes essais FMX (OS Android) ne m'ont rien donné.

    D'un autre côté il faut certainement que les formes soient créées au départ (ce qui n'était pas le cas de mon test).
    Mais, j'ai un doute car la forme principale aurait du en faire partie, non ?
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre Expert
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 697
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 697
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    J'ai lu quelque part qu'il existait un application.componentcount (et donc application.components)
    Je ne connaissais pas non plus.
    J'ai testé dans D11.3 avec un projet de test : 2 fenêtres avec quelques composants dans chacune.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      for i:=0 to Pred(Application.componentcount) do
        RichEdit.Lines.Add(Application.Components[i].ClassName);
    Résultat :
    THintWindow
    TForm1
    TForm2
    Les sous-composants posés sur les fenêtres ne sont pas listés.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. :bug: ___ "http://club.developpez.com/regles/#LIII-A"Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.3 Entreprise - Visual studio 2022
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.7)

  4. #4
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 554
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 554
    Billets dans le blog
    65
    Par défaut
    Lung a été plus rapide que moi pour le test.

    Rapide et donc pas très propre

    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 TMain.Button2Click(Sender: TObject);
    var acomponent : TComponent;
    begin
    Memo1.lines.Clear;
    if Application.ComponentCount>0 then
     begin
       memo1.lines.add('Application.ComponentCount = '+Application.ComponentCount.ToString);
       for var i := 0 to Application.ComponentCount-1 do
         begin
           Memo1.lines.Add('  '+Application.Components[i].ClassName);
           aComponent:=Application.Components[i];  // pour éviter trop de cascade de Components[]
           if aComponent.ClassParent=TForm then   // aComponent.ClassParent is TForm n'est pas accepté
             begin
               for var j := 0 to TForm(aComponent).ComponentCount-1 do
                if TForm(acomponent).Components[j] is TButton then
                  memo1.lines.Add('      '+Application.Components[i].ClassName+' '+TButton(TForm(aComponent).Components[j]).Name)
             end;
     
         end;
     end;
    end;
    me fourni un truc qui semble correspondre au besoin
    Application.ComponentCount = 3
    THintWindow
    TMain
    TMain Button1
    TMain Button2
    TChild
    TChild Button1
    Suite à quoi, j'ai ôté la seconde forme du source du projet pour en faire une forme créée au runtime et là je n'ai plus que
    Application.ComponentCount = 2
    THintWindow
    TMain
    TMain Button1
    TMain Button2
    Conclusion en VCL Application.ComponentCount fonctionne en FMX environnement Windows pour l'instant que, bien sûr, je vais vérifier

    Vérifications faites :
    FMX Windows Ok, ça fonctionne
    FMX Linux Ok, ça fonctionne
    FMX Android Ok, ça fonctionne . Je n'imaginais même pas qu'il était possible d'avoir plusieurs fiches avec android, du coup une seconde forme ressemble (presque) à un showmodal, le seul truc manquant serait d'avoir une couleur plus ou moins transparente pour "voir" la première forme. Un truc à creuser
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    ComponentCount c'est une propriété de TComponent

    TApplication et TForm sont des dérivés de TComponent et hérite tout cela


    Il faut créer les TForm avec Application comme Owner si l'on crée une TForm avec nil comme Owner, cela ne fonctionnera pas.

    Comme évoqué dans ce sujet , il y a aussi, du moins en VCL, Screen.Forms[] et FormCount
    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
    Membre éprouvé
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Janvier 2017
    Messages : 358
    Par défaut
    Merci à tous pour votre réponse. Je teste ça demain.
    Vous ne pouvez pas faire confiance à un code que vous n'avez pas totalement rédigé vous-même. :aie:
    Ce n’est pas un bogue - c’est une fonctionnalité non documentée. :lahola:

  7. #7
    Membre éprouvé
    Avatar de XeGregory
    Homme Profil pro
    Passionné par la programmation
    Inscrit en
    Janvier 2017
    Messages
    358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Passionné par la programmation
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Janvier 2017
    Messages : 358
    Par défaut
    Cela fonctionne impeccable ,
    C'est tout de même beaucoup plus efficace de parcourir les composants de cette manière, que de déclarer tous les Units TForm puis de parcourir toutes les Forms à la recherche de composant.

    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
    { FrameHotInterface }
    procedure FrameHotInterface(Clr: TColor);
    var
      I, A: Integer;
      Acomponent: TComponent;
    begin
      for I := 0 to Application.ComponentCount - 1 do
      begin
        Acomponent := Application.Components[I];
     
        if Acomponent.ClassParent = TForm then
        begin
          for A := 0 to TForm(Acomponent).ComponentCount - 1 do
          begin
            if TForm(Acomponent).Components[A] is TscGPGlyphButton then
            begin
              case AnsiIndexStr(TForm(Acomponent).Components[A].Name, ['ActColorPicker', 'ActSettings',
                'ActAbout', 'ActFormMin', 'ActFormClose']) of
                0 .. 5:
                  Continue;
     
                -1:
                  with TscGPGlyphButton(TForm(Acomponent).Components[A]).Options do
                  begin
                    FrameHotColor := Clr;
                    FrameHotColorAlpha := 255;
                  end;
              end;
            end;
          end;
        end;
      end;
    end;
    Ceci dit, je ne peux pas appeler cette procédure dans le TForm.Create de la fiche principale, il faut que je l'appelle derrière Application.Run après la création de toutes les TForm.

    Merci
    Vous ne pouvez pas faire confiance à un code que vous n'avez pas totalement rédigé vous-même. :aie:
    Ce n’est pas un bogue - c’est une fonctionnalité non documentée. :lahola:

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    Par prudence, je changerais juste cette ligne if Acomponent.ClassParent = TForm then par if Acomponent is TForm then.

    Citation Envoyé par XeGregory Voir le message
    Ceci dit, je ne peux pas appeler cette procédure dans le TForm.Create de la fiche principale, il faut que je l'appelle derrière Application.Run après la création de toutes les TForm.
    Créer Toutes les fenêtres au lancement du programme, cela me gêne un peu, j'ai déjà eu des applications avec plus de 200 fiches ...


    Alors je peux te proposer une solution POO

    Toutes tes fiches sont déclarées aujourd'hui de la forme TForm1 = class(TForm) mais tu peux faire TForm1 = class(TXeGregoryForm) avec une TXeGregoryForm qui n'a pas de DFM, juste des méthodes.
    Faut évidemment faire un passage sur tout le projet et y penser pour les futures nouvelles fiches mais tu peux y inclure plusieurs fonctions réutilisables.


    Tu peux donc redéfinir Loaded par exemple, c'est après le chargement de la DFM

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type
      TXeGregoryForm = class(TForm)
      private
        class var FFrameHotColor: TColor;
        class procedure SetFrameHotColor(Value: TColor);
      protected
        procedure Loaded; override;
      public
        class property FrameHotColor: TColor read FFrameHotColor write SetFrameHotColor;
      end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TXeGregoryForm.Loaded;
    begin
      inherited Loaded();
     
      FrameHotInterface(Self, FrameHotColor);
    end;
    Attention !!!
    N'appelle plus FrameHotInterface manuellement entre le dernier CreateForm et le Run
    Ne Crée plus tes fenêtres dans le DPR

    Ajoute juste cette ligne dans le DPR avant ou après le CreateForm de la MainForm, l'un ou l'autre est possible juste que la façon de faire le FrameHotColor ne sera pas fait de la même façon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TXeGregoryForm.FrameHotColor := clBlue;
    Si c'est après les CreateForm, cela va patcher le Color après la construction
    Affecter FrameHotColor va appeler SetFrameHotColor donc FrameHotInterface(App) et donc FrameHotInterface(Form) ...

    Si c'est avant les CreateForm,
    Affecter FrameHotColor va faire la même chaine mais comme il n'y aura pas de Components cela ne fera rien
    Cependant c'est le Loaded qui va invoquer le FrameHotInterface(Form)

    Avantage, tu pourras créer tes fiches n'importe où et n'importe quand, cela prendra effet naturellement dès que cela hérite de TXeGregoryForm


    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
    procedure FrameHotInterface(AForm: TForm; AColor: TColor); // overload;
    const
      EXCLUSION: array[0..4] of string = ['ActColorPicker', 'ActSettings', 'ActAbout', 'ActFormMin', 'ActFormClose'];
    var
      I: Integer;
      LComponent: TComponent;
    begin
      for I := 0 to AForm.ComponentCount - 1 do
      begin
        LComponent : = AForm.Components[I];
        if LComponent is TscGPGlyphButton then
          if not MatchStr(LComponent.Name, EXCLUSION) then
            with TscGPGlyphButton(LComponent).Options do
            begin
              FrameHotColor := Clr;
              FrameHotColorAlpha := 255;
            end;
      end;
    end;
    Tu peux évidemment conserver la fonction plus générale et note l'utilisation d'un overload pour rendre le code à la fois réutilisable et plus facile à lire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure FrameHotInterface(AColor: TColor); // overload;
    var
      I: Integer;
    begin
      for I := 0 to Application.ComponentCount - 1 do
        if Application.Components[I] is TXeGregoryForm then // ou is TForm
          FrameHotInterface(TForm(Application.Components[I]), AColor);
    end;
    Et donc pousser plus loin

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class procedure TXeGregoryForm.SetFrameHotColor(Value: TColor);
    begin
      FFrameHotColor := Value;
      FrameHotInterface(Value);
    end;

    je suis resté en procédural pour FrameHotInterface mais j'aurais tendance à la déclarer comme méthode class procedure TXeGregoryForm.FrameHotInterface(AForm: TForm; AColor: TColor); ...



    Voilà, ce code permet tout ce que tu as déjà géré pour le cas du CreateForm mais n'a plus d'obligation d'être après et permet la création dynamique des fiches.
    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
    Membre expérimenté
    Homme Profil pro
    Consultant fonctionnel
    Inscrit en
    Décembre 2014
    Messages
    109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Consultant fonctionnel

    Informations forums :
    Inscription : Décembre 2014
    Messages : 109
    Par défaut
    Bonjour,
    Que vous êtes compliqués!
    Balayer les composants d'une appli, disons de n'importe quel composants (car TApplication est un composant), je ferai une proc récursive qui balaye les composants d'u composant passé en param.

    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
    // j'ai ajouté un "Level" pour montrer l'imbrication
    procedure TForm1.SweepComponents(Source: tComponent; Level: String);
    var i: Integer;
    begin
      with Source do
        for i := 0 to Source.ComponentCount-1 do
        begin
          Memo1.Lines.Add(Level + Format('%-20s %-20s', [ Components[i].ClassName, Components[i].Name]));
          SweepComponents(Source.Components[i], Level + '  ');
        end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Lines.Clear;
      SweepComponents(Application, '');
    end;
    Bonne journée à tous.

  10. #10
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    Citation Envoyé par solilog Voir le message
    Que vous êtes compliqués!
    Que trouvez vous compliqué ?

    Je pense que vous avez été abusé par un titre du sujet trompeur "Parcourir l'intégralité des composants de l'application" qui devrait être "Mettre à jour certains contrôles dans l'intégralité des composants de l'application" !
    C'est comme cela que l'on passe totalement à côté de la véritable problématique.


    Citation Envoyé par solilog Voir le message
    Balayer les composants d'une appli, disons de n'importe quel composants (car TApplication est un composant), je ferai une proc récursive qui balaye les composants d'u composant passé en param.
    Si le bayalage est "one-shot", je trouve que l'approche par Héritage pour ne plus avoir besoin de balayer est nettement plus performante.
    Il y a plusieurs méthodes pour résoudre ce problème, en fait le sujet n'est pas le balayage mais l'uniformisation des contrôles.

    Mais par soucis de compatibilité, j'en ai conservé la possibilité car on ne connaît pas le besoin exact.
    par exemple est-ce que la Color peut être changé à la volée via un menu de sélection des couleurs ?


    Votre code récursif gère un level mais qu'avez vous fait de Color et des TscGPGlyphButton ?





    Citation Envoyé par ShaiLeTroll Voir le message
    ComponentCount c'est une propriété de TComponent

    TApplication et TForm sont des dérivés de TComponent et hérite tout cela
    Sinon, c'est exactement ce que l'on a évoqué depuis le début, la récursivité sur le Onwer et Compenents, c'est un vieux classique.

    J'y vois un inconvénient de faire un balayage récursif :
    - balayer les DataModule si il y en a,
    - balayer des composants imbriqués qu'il n'est peut-être pas nécessaire de balayer,
    donc cibler précisément le TForm est un gain, certes de quelques itérations, négligeable mais c'est toujours ça de moins.




    Donc pour qu'un balayage récursif générique puisse répondre à la problématique de mise à jour de plusieurs Contrôles, il faut faire des CallBack pour reproduire le comportement souhaité

    Voici une adaptation de SweepComponents qui a une approche générique avec CallBack pour obtenir le même résultat que la dernière version de fonction FrameHotInterface par XeGregory.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    TSweepComponentFilterProc = function(AComponent: TComponent): Boolean of object;
    TSweepComponentFindProc = function(AComponent: TComponent): Boolean of object;
    TSweepComponentFoundProc = procedure(AComponent: TComponent) of object;
    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 TForm1.SweepComponents(Source: tComponent; AFilterProc: TSweepComponentFilterProc; AFindProc: TSweepComponentFindProc; AFoundProc: TSweepComponentFoundProc);
    var 
      i: Integer;
      C: TComponent;
    begin
      with Source do
        for i := 0 to Source.ComponentCount-1 do
        begin
          C := Source.Components[i];
          if AFindProc(C) then
            AFoundProc(C)
          else if AFilterProc(C) then
            SweepComponents(C, AFilterProc, AFindProc, AFoundProc);
        end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      SweepComponents(Application, FrameHotInterfaceSweepComponentFilterProc, FrameHotInterfaceSweepComponentFindProc, FrameHotInterfaceSweepComponentFoundProc);
    end;
    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
     
    function TForm1.FrameHotInterfaceSweepComponentFilterProc(AComponent: TComponent): Boolean;
    begin
      Result := AComponent is TForm;
    end;
     
    function TForm1.FrameHotInterfaceSweepComponentFindProc(AComponent: TComponent): Boolean;
    const
      EXCLUSION: array[0..4] of string = ['ActColorPicker', 'ActSettings', 'ActAbout', 'ActFormMin', 'ActFormClose'];
    begin
      Result := (AComponent is TscGPGlyphButton) and not MatchStr(AComponent.Name, EXCLUSION);
    end;
     
    procedure TForm1.FrameHotInterfaceSweepComponentFoundProc(AComponent: TComponent);
    begin
      with (AComponent as TscGPGlyphButton).Options do
      begin
       FrameHotColor := Clr;
       FrameHotColorAlpha := 255;
      end;
    end;
    Comme SweepComponents sera invoqué dans le DPR, il sera plus facile peut-être de faire des CallBack de type procédure et non sous forme de méthode pour ne pas avoir besoin d'un TForm1
    On devine très vite que SweepComponents peut devenir une classe TSweepComponents avec des Event OnFilter, OnFind, OnFound ou une classe abstraite TCustomSweepComponent avec des méthodes virtuelles DoFilter, DoFind et DoFound (cela aurait ma préférence dans ce cas)
    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

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 908
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Comme SweepComponents sera invoqué dans le DPR, il sera plus facile peut-être de faire des CallBack de type procédure et non sous forme de méthode pour ne pas avoir besoin d'un TForm1
    Les types méthodes (procedure of object) sont encore nécessaires pour les événements publiés, sinon il est préférable de passer par des références (reference to) qui elles acceptent indifféremment des procédures, des méthodes et des procédures anonymes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TSweepComponentFilterProc = reference to function(AComponent: TComponent): Boolean;
    TSweepComponentFindProc = reference to function(AComponent: TComponent): Boolean;
    TSweepComponentFoundProc = reference to procedure(AComponent: TComponent);

  12. #12
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    Je n'ai encore jamais utilisé reference to et c'est très intéressant pour utiliser du code procédural ou des méthodes.

    Cela fonctionne aussi sur une procédure local (imbriquée) ?

    Si oui, on pourrait donc écrire un code plus compact
    Si non, dommage

    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
     
    procedure TForm1.Button1Click(Sender: TObject);
     
      function Filter(AComponent: TComponent): Boolean;
      begin
        Result := AComponent is TForm;
      end;
     
      function Find(AComponent: TComponent): Boolean;
      const
        EXCLUSION: array[0..4] of string = ['ActColorPicker', 'ActSettings', 'ActAbout', 'ActFormMin', 'ActFormClose'];
      begin
       Result := (AComponent is TscGPGlyphButton) and not MatchStr(AComponent.Name, EXCLUSION);
      end;
     
      procedure Found(AComponent: TComponent);
      begin
        with (AComponent as TscGPGlyphButton).Options do
        begin
         FrameHotColor := Clr;
         FrameHotColorAlpha := 255;
        end;
      end;
     
     
    begin
      SweepComponents(Application, Filter, Find, Found);
    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

  13. #13
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 475
    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 475
    Par défaut
    Salut

    moi non plus je n'ai pas encore tester les reference

    quel est la grosse difference avec les procedure ou fonction of Object ?
    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 :resolu:

  14. #14
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    des procédures anonymes.

    Et les fans des Anonymes pourrait donc écrire ceci ! non ?
    Je ne connais pas bien la syntaxe



    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      SweepComponents(Application, 
        function (AComponent: TComponent): Boolean;
        begin
          Result := AComponent is TForm;
        end
        ,
        function (AComponent: TComponent): Boolean;
        const
          EXCLUSION: array[0..4] of string = ['ActColorPicker', 'ActSettings', 'ActAbout', 'ActFormMin', 'ActFormClose'];
        begin
         Result := (AComponent is TscGPGlyphButton) and not MatchStr(AComponent.Name, EXCLUSION);
        end
        ,
        procedure (AComponent: TComponent);
        begin
          with (AComponent as TscGPGlyphButton).Options do
          begin
           FrameHotColor := Clr;
           FrameHotColorAlpha := 255;
          end;
        end
      );
    end;

    On part grave en hors sujet ! non ?
    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

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 908
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Cela fonctionne aussi sur une procédure local (imbriquée) ?
    Non ça ne fonctionne pas sur les procédures imbriquées, la capture de procédure n'étant pas possible.

    Par contre ça le ferait avec une variable procédurale (écriture à peine plus compliquée) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    begin
      const Filter :TSweepComponentFilterProc =
        function (AComponent: TComponent): Boolean;
        begin
          Result := AComponent is TForm;
        end;
     
      if CallFunc(Filter) then ...;
    end;
    Citation Envoyé par ShaiLeTroll Voir le message
    Et les fans des Anonymes pourrait donc écrire ceci ! non ?
    Tout à fait

    Citation Envoyé par anapurna Voir le message
    quel est la grosse difference avec les procedure ou fonction of Object ?
    Comme je l'ai dit : accepter indifféremment des procédures, des méthodes (d'objet ou de classe) ou des procédures anonymes

    of Object implique un paramètre Self. Les références savent déterminer s'il est nécessaire ou pas, si c'est une méthode ou non, c'est transparent.

  16. #16
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 075
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 075
    Par défaut
    Bonjour,

    (c'est amusant, en ce moment j'étudie la récursivité !)
    Je reviens deux minutes au début du sujet (parce qu'après, vous m'avez perdu), je suis parti du projet de solilog, que je remercie bien fort, et l'ai bricolé ainsi :
    tout dans un seul bouton (c'est plus pratique pour le copier/coller) et suppression des 2 "source." inutiles puisque "with source do" fait le taf, pi j'ai changé ce nom SweepComponents en CompteComposants, ce qui donne ça :
    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
    procedure TForm1.Button7Click(Sender: TObject);
    var tot: integer;
      procedure CompteComposants(Source: tComponent; Level: String);
      var i: Integer;
      begin
        with Source do begin
          for i := 0 to ComponentCount-1 do
          begin
            Memo1.Lines.Add(Level + Format('%-20s %-20s', [Components[i].ClassName, Components[i].Name]));
            CompteComposants(Components[i], Level + '  ');
          end;
          tot := tot + i;
        end;
      end;
    begin
      Memo1.Lines.Clear;
      tot := 0;
      CompteComposants(Application, '');
      ShowMessage('Composants : '+IntToStr(tot)); // 33 ou 34 ou 35, lire + bas
    end;
    Et effectivement, dans mon contexte (Linux Debian), et je suis parti d'un projet en cours avec 2 fiches et des compos, auquel j'ai ajouté un bouton et ce code, et j'ai fait F9 : le ShowMessage m'a donné 33 et le TMemo 40 lignes, colonne de gauche sur l'image :
    Nom : récursivité_pifométrique.jpg
Affichages : 98
Taille : 348,6 Ko

    Si on observe attentivement, on constate un décalage vers la droite de 7 lignes, correspondant à des sous-composants venus avec les composants que j'ai posés il y a qq jours et donc, 40 - 7 = 33, les sous-composants ne sont donc pas comptés dans la boucle et on s'en fiche.

    Mais ce qui me perturbe, c'est que des fois, sans rien changer sauf un arrêt-redémarrage du prog, celui-ci remonte 34 ou 35 composants !
    Qu'on explique en examinant attentivement la copie d'écran et force est de constater que les sous-objets des sous-composants ne sont pas pris en compte !
    Je parle là des lignes TCustomTimer associées aux THintWindow liées aux TTreview.
    Je vous laisse comparer, dans le montage, comment ce sous-composant et son acolyte apparait, de g à d 0 fois, 1 fois, 2 fois.
    Tout en bas des 3 colonnes le nombre de composants remonté par le prog.

    En résumé, pour une raison qui m'échappe, le fait de démarrer plusieurs fois le prog va donner des résultats différents !
    Ah, les mystères de l'informatique aléatoire... (et après on s'étonne que des Tesla génèrent des accidents...)

    Alors maintenant, un truc qui serait bien, ça serait que les gens sous Windows fassent les mêmes tests, des fois que la blague se cache sous Linux et/ou FreePascal-Lazarus (qui est mon environnement de travail).
    Les composants "sensibles" sont le TTreeView et le TLabeledEdit (il existe sous Delphi ? Je ne sais pas)

    Bonne journée et merci de m'avoir lu.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 908
    Par défaut
    Il y a eu dissertation dernièrement sur l'utilisation de la variable de boucle en dehors de la boucle.

    Tu devrais plutôt écrire tot := tot +ComponentCount

  18. #18
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 075
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 075
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Il y a eu dissertation dernièrement sur l'utilisation de la variable de boucle en dehors de la boucle.
    Ah, mais comme je n'étais pas trop là ces derniers temps, j'ai dû louper une marche...

    Citation Envoyé par Andnotor Voir le message
    Tu devrais plutôt écrire tot := tot +ComponentCount
    Vu.
    J'ai testé, ça inclut maintenant les sous-composants et leur(s) acolyte(s), bien joué !, mais ça ne change rien au fait que le nombre de sous-composants varie aléatoirement -- et ça, ça me perturbe grave !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  19. #19
    Membre expérimenté
    Homme Profil pro
    ‫‬
    Inscrit en
    Septembre 2024
    Messages
    134
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : ‫‬

    Informations forums :
    Inscription : Septembre 2024
    Messages : 134
    Par défaut
    J'ai testé, ça inclut maintenant les sous-composants et leur(s) acolyte(s), bien joué !, mais ça ne change rien au fait que le nombre de sous-composants varie aléatoirement -- et ça, ça me perturbe grave !
    Components est juste une poubelle pour d’établir une liste des composants à libérer au moment de la destruction du composant cela inclut les composants créés dynamiquement:
    On peut dire que les THinWindow on été crées dynamiquement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    THinWindow.Create(form)
    Dans cette ligne form devient le Owner du HintWindow ce dernier aura la même durée de vie que son propriétaire

    Il existe une autre propriété Controls beaucoup plus soignée qui ne contient que les contrôles enfants.

  20. #20
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 969
    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 969
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Je reviens deux minutes au début du sujet (parce qu'après, vous m'avez perdu), je suis parti du projet de solilog
    En réalité, le sujet c'est pour manipuler en masse des TscGPGlyphButton pour en changer la couleur d'un coup pour tous, c'est le titre du sujet qui est trompeur !
    Du coup, la proposition de solilog était incomplète, la suite montrait comment utiliser une fonction "générique" et lui fournir des traitements spécifiques.

    Faudrait le renommer en "Mettre à jour certains contrôles dans l'intégralité des composants de l'application"
    Et mettre créer un autre sujet "Parcourir l'intégralité des composants de l'application" pour approfondir ce sujet vu et revu, tout le monde à déjà fait son TTreeView qui énumère tous les Components / Controles, typiquement c'est utile par exemple pour se faire un Translator intégré en RunTime.



    Sinon, le THintWindow n'est crée que lors d'un DoHint / OnHint, suffit d'une simple survol d'un item pour le créer, si tu n'as pas de survol, c'est le cas où il est absent

    Et le TCustomTimer c'est le système qui fait disparait le Hint ... c'est même une particularité Delphi car dans un sujet récent, il a été constaté qu'un Hint reste affiché jusqu'à ce que l'on clic sur le controle
    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

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 7
    Dernier message: 17/09/2014, 18h10
  2. Nommage des composants des applications.
    Par pascal B dans le forum Android
    Réponses: 2
    Dernier message: 11/03/2014, 04h18
  3. [Débutant] Ajouter des composant à un control lorsque l'application est déjà exécuté
    Par Gui4257 dans le forum Windows Presentation Foundation
    Réponses: 5
    Dernier message: 02/07/2012, 20h11
  4. comment récupérer la valeur des composants d'une autre application
    Par AlexTheDoctor dans le forum Windows Forms
    Réponses: 2
    Dernier message: 23/12/2009, 18h13
  5. des composants standard pour toute l'application
    Par lucky31 dans le forum Composants
    Réponses: 12
    Dernier message: 29/04/2009, 19h18

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