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

Langage Delphi Discussion :

Comment accéder à une variable d'un Objet surchargé depuis un objet descendant ?


Sujet :

Langage Delphi

  1. #1
    Membre du Club
    Inscrit en
    Décembre 2002
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 74
    Points : 44
    Points
    44
    Par défaut Comment accéder à une variable d'un Objet surchargé depuis un objet descendant ?
    Bonjour,
    Je souhaite ajouter une variable à un Objet Delphi existant (surcharge de l'objet) et pouvoir accéder à cette variable depuis un objet Delphi descendant de l'Objet surchargé.
    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    TMyComponent = Class(TComponent )
        private
        public
          MyVariable : Integer;
          constructor Create(Owner: TComponent);override;
          destructor Destroy; override;
        end;
    et pouvoir faire dans un programme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var
       APanel : TPanel;
       AButton : TButton;
    begin
     
      APanel.MyVariable := 100;
      AButton.MyVariable := 200; 
     
    // ...
    end;
    cela est-il possible? Si oui comment procéder ?

    Merci d'avance pour toutes réponses

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    si tes objets sont bien des TPanel et TButton, ils ne descendent pas de TMyComponent et ne possèdent pas de champ MyVariable !!

  3. #3
    Membre du Club
    Inscrit en
    Décembre 2002
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 74
    Points : 44
    Points
    44
    Par défaut
    Effectivement, Les objet TPanel et TButton ne descendent pas de TMyComponent mais de TComponenet.
    En fait je souhaite surcharger (ex MyVariable) des objets Delphi et pouvoir accéder à MyVariable sans avoir à traiter le type de l'objet

    Par exemple lors d'un événement sur un objet, je veux pouvoir récuper la variable sans avoir à tester le type de l'objet.

    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
    Type
     
     TMyButton = Class(TButton)
        private
        public
          MyVariable : Integer;
          constructor Create(Owner: TComponent);override;
          destructor Destroy; override;
        end;
     
     TMyEdit = Class(TEdit)
        private
        public
          MyVariable : Integer;
          constructor Create(Owner: TComponent);override;
          destructor Destroy; override;
        end;
     
    ...
     
    procedure TForm1.EventTreatment(Sender: TObject);
    var
      AVar : Integer;
    begin
      if Sender is TMyButton then AVar := TMyButton(Sender).MyVariable
      else
      if Sender is TMyEdit then AVar := TMyEdit(Sender).MyVariable
      else 
      ...
    end;
    Je souhaite trouver une autre manière plus légère en nombre de lignes de programme.

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    alors, Delphi ne supportant pas l'héritage multiple, tu ne peux pas ajouter un propriété à un ensemble de composant sans passer par un ancêtre commun.

    tu as plusieurs approchent à ce problème

    1) utilise la propriété TAG pour y loger ta variable

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     AVar:=TComponent(Sender).Tag;
    2) pour une information plus complexe, transtyper TAG en TObject et y coller un instance d'objet qui contient toutes les informations dont tu as besoin

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
     i:TMesInfos;
    begin
     i:=TMesInfos.Create(Button1,...);
     Button1.Tag:=integer(i);
    end;
     
    ...Sender:TObject
    begin
     TMesInfos(TComponent(Sender).Tag)...
    end;
    3) tu peux créer une classe qui va gérer l'assocation de deux objets...ça demande un peu de codage mais ça peut être intéressant, et ça ne dépend plus de TComponent

    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
     
    type
     TObjectAssociation=class
     private
      fList1:TList;
      fList2:TList;
     public
      constructor Create;
      destructor Destroy; override;
      procedure Associate(Object1,Object2:TObject);
      function GetAsssociate(Object1:Object):TObject;
     end;
     
    constructor TObjectAssociation.Create;
    begin
     inherited;
     fList1:=TList.create;
     fList2:=TList.Create;
    end;
     
    destructor TObjectAssociation.Destroy;
    begin
     fList1.Free;
     fList2.Free;
     inherited;
    end;
     
    procedure TObjectAssociation.Associate(Object1,Object2:TObject);
    begin
     fList1.Add(Object1);
     fList2.Add(Object2);
    end;
     
    function TObjectAssociation.GetAsssociate(Object1:Object):TObject;
    var
     i:integer;
    begin
     i:=fList1.IndexOf(Object1);
     if i<0 then Result:=nil then Result:=fList2[i];
    end;
     
    // à l'usage à donne
     
    begin
     OA:=TObjectAssociate.Create;
     OA.Associate(Button1,MesInfo1);
    end;
     
    begin
     MesInfo:=OA.GetAssociate(Sender);
    end.
    et ce n'est qu'un exemple

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    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 563
    Points : 25 165
    Points
    25 165
    Par défaut
    tu peux utiliser la propriété Tag du TComponent pour stocker un objet ou un pointeur sur une structure ... c'est une valeur libre, moi j'ai créé un objet standard pour l'utiliser et ainsi la laisser ouverte à des utilisations vastes ...

    l'objet ressemble à peu près à cela, avec quelques fonctions en plus pour faciliter l'attachement à un objet ayant déjà un tag, ainsi qu'un peu de RTTI ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    type
      TTagItem = class(TObject)
      private
        FTag: Integer;
        FObject: TObject; 
        FData: Pointer;
      public
        property Tag: Integer read FTag write FTag; // on peut enchainer des TTagItem 
        property Object: TObject read FObject write FObject;
        property Data: Pointer read FData write FData;
    end;
    ou encore, une liste d'association, un objet encapsulant un tableau à deux dimensions (ou une TObjectList) contenant une colonne pointant sur l'objet, la seconde pointant vers la variable, ... tu parcours cette liste genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MaVar := ListAsso.IndexOf(Sender);

    Edit : le Temps que je réponde, Paul Toth avait pensé aux mêmes solutions

  6. #6
    Membre du Club
    Inscrit en
    Décembre 2002
    Messages
    74
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 74
    Points : 44
    Points
    44
    Par défaut
    Merci beaucoup pour vos solutions dont je n'y avais pas pensé !

    Je vais tester la solution de l'objet pointé par Tag. J'utilisais déjà Tag pour mémoriser une variable mais je n'avais pas imaginé que l'on pouvait pointer une objet. Comme quoi les objets Delphi sont très bien pensés (je m'en émerveille souvent).
    Mais n'y a-t-il pas de limitation entre Tag qui est de type Integer et un objet qui peut être de structure complexe ?

    Encore Merci

  7. #7
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    c'est pas mieux de dériver le composant et de lui coller la propriété en question et de créer les evenements personalisés?

    d'ailleurs personnellement, je dérive systematiquement les composants dont j'ai besoin dans un appli avant de les utiliser.

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    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 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Un objet étant toujours sous la forme d'un pointeur de delphi win32, tu peux donc caster un entier en pointeur ou en objet sans soucis

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TObject(Cpt.Tag).ClassName
    Citation Envoyé par Kaféine Voir le message
    d'ailleurs personnellement, je dérive systematiquement les composants dont j'ai besoin dans un appli avant de les utiliser.
    Même les Labels, Edit, DataSource, Grille, ... cela doit compliquer l'installation d'un nouveau poste delphi à installer tous ces nouveaux composants dans la palette ...
    Moi, je le fait avec des libs externes pas très répandue, pour si besoin, changer de lib sans devoir remplacer les composants dans toutes les applicatios, quoi que, je ne fais pas d'héritage mais une encapsulation ... pour justement détaché la lib et la fonctionnalité, ... pour les sockets par exemple, ce fut utile vu la permanente évolution des composants en delphi ... avec un jeu de directive permettant d'avoir le même comportement de D3 à D7 en utilisant 3 lib différentes ...

  9. #9
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Citation Envoyé par ShaiLeTroll
    Même les Labels, Edit, DataSource, Grille, ... cela doit compliquer l'installation d'un nouveau poste delphi à installer tous ces nouveaux composants dans la palette
    seulement les composants visuels genre label, edit....
    evidemment, il faut installer les packages, mais bon de la à dire que ca complique l'installation du poste delphi

    pour les librairies tiers, c'est encore plus systématique. ce qui evite de modifier les unités de la librairie originale pour ajouter des fonctionnalités. de plus ca permet de garder le support technique, dont avec certain on doit pas modifier le source. je pense notamment à DevExpress.

    enfin, pour certaines classes, je crée des wrappers à base d'interfaces.

  10. #10
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    c'est pas mieux de dériver le composant et de lui coller la propriété en question et de créer les evenements personalisés?

    d'ailleurs personnellement, je dérive systematiquement les composants dont j'ai besoin dans un appli avant de les utiliser.
    oui et non, tu peux t'en sortir uniquement si tu utilises une interface, car sinon tu n'auras rien de commun entre tes différents objets dérivés

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    type
     TMyButton=class(TButton,IMyInterface)
     ...
     end;
     TMyPanel=class(TPanel,IMyInterface)
     end;
     
    begin
     with (Sender as IMyInterface) do ...
    end;

  11. #11
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Citation Envoyé par Paul TOTH
    tu peux t'en sortir uniquement si tu utilises une interface, car sinon tu n'auras rien de commun entre tes différents objets dérivés
    tout à fait.

    mais je pensais à un truc plus basique et plus chiant aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    TMonEdit = class(TEdit)
    public
      property MaProp: Boolean..
    end;
     
    TMonPanel = class(TPanel)
    public
      property MaProp: Boolean..
    end;
    ca fait ecrire plusieurs fois la meme chose.

    evidemment, la combinaison avec les interfaces est meilleurs.

  12. #12
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    apparement les class helper (depuis D2006?) peut résoudre le problème.

    je déclare le helper sur TObject
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
      TObjHelper = class helper for TObject
        class var MaVar: Boolean;
      end;
    du coup je peux écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    procedure TForm1.Button3Click(Sender: TObject);
    var
      t: TObject;
    begin
      t := TList.Create;
      try
        t.MaVar := True;
      finally
        t.Free;
      end;
    end;
    MaVar est donc accessible sur n'importe quel descendant de TObject apparement.

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    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 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Sinon, une propriété publiqué accéder via IsPublishedProp et GetPropValue ... cela permet de ne plus se préoccuper du type mais juste de vérifier l'existence de la variable

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TMyButton = Class(TButton)
        private
          FMyVariable: Integer;
        public      
          constructor Create(Owner: TComponent);override;
          destructor Destroy; override;
        published
          property MyVariable : Integer read FMyVariable write FMyVariable;
        end;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if isPublishedProp(Sender, 'MyVariable') then
      SetPropValue(Sender, 'MyVariable', 100);
     
    if isPublishedProp(Sender, 'MyVariable') then
     AVar := GetPropValue(Sender, 'MyVariable');


    @Kaféïne
    Tu as vachement du temps, lol, si on devait encapsulé tous les objets utilisés dans les libs externes que l'on a, on y passerait trop de temps, ... et y a tellement de métier à livrer ...

    Sinon, on ne modifie jamais les libs si je dois greffer des fonctionnaliés, je ferais un héritage ou un ToolHelp *, c'est EVIDENT !
    Après comment faire pour mettre à jour lors Delphi, Jedi, TMS, DVE, ... propose une nouvelle version ...

    Parfois l'héritage ne suffit pas pour revoir un composant, je passe par l'astuce du Hack du protected pour choper dans l'unité courante de mon ToolHelp, les propriétés protégées, et faire un miroir des membres privées ... pour modifier le comportement de l'objet ...

    * ils ont inventé ça, c'est beau, faudrait un jour que je dépasse Delphi 7, il y a des nouveautes intéressantes ... on peut rajouter des fonctionnalités, vachement bas niveau, cela peut ouvrir des portes dangereuses, genre une propriété publié sur le TComponent, ouch ... risque d'avoir des DFM absolument plus compatible avec un autre Delphi !!!

  14. #14
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par Kaféine Voir le message
    tout à fait.

    mais je pensais à un truc plus basique et plus chiant aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
    TMonEdit = class(TEdit)
    public
      property MaProp: Boolean..
    end;
     
    TMonPanel = class(TPanel)
    public
      property MaProp: Boolean..
    end;
    ca fait ecrire plusieurs fois la meme chose.

    evidemment, la combinaison avec les interfaces est meilleurs.
    sauf que TMonEdit.MaProp n'est pas équivalent à TMonPanel.MaProp !!!!

    les deux propriétés sont des boolean, mais leur position dans l'instance n'est pas forcément la même; ça ne serait le cas que si TPanel.InstanceSize=TEdit.InstanceSize !

    du coup je ne peux pas avoir une syntaxe unique XXX.MaProp, je suis obligé de tester le type de classe de Sender pour savoir si c'est TMonEdit.MaProp ou TMonPanel.MaProp qu'il faut utiliser.

    et le classHelper n'aide pas non plus car lui aussi est lié à un type et que ta "class var" est commune à toutes les instances.

  15. #15
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Citation Envoyé par ShaiLeTroll
    Tu as vachement du temps, lol, si on devait encapsulé tous les...
    tu charges le département architecture

    aprés j'utilise qu'une librairie en l'occurence DevExpress.
    ca prend du temps, mais tu en gagne par la suite....

    Citation Envoyé par ShaiLeTroll
    Après comment faire pour mettre à jour lors Delphi, Jedi, TMS, DVE, ... propose une nouvelle version
    ca pose pas de problème vu que ton package depend de celui de l'editeur tier. Evidemment si l'éditeur change ou vire des propriétés published ....

  16. #16
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Citation Envoyé par Paul TOTH
    et le classHelper n'aide pas non plus car lui aussi est lié à un type et que ta "class var" est commune à toutes les instances.
    effectivement tu as raison pour ce point, la variable est liée à la classe.

    j'avais lu de BaldeckJ.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    var
       APanel : TPanel;
       AButton : TButton;
    begin
     
      APanel.MyVariable := 100;
      AButton.MyVariable := 200; 
     
    // ...
    end;
    donc ca devient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    var
       APanel : TMonPanel;
       AEdit : TMonEdit;
    begin
     
      APanel.MaVar := true;
      AEdit.MaVar := false; 
     
    // ...
    end;

Discussions similaires

  1. Réponses: 11
    Dernier message: 10/05/2010, 09h40
  2. Accéder à une variable d'un objet contenu dans une collection
    Par derlone dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 30/04/2009, 16h50
  3. Réponses: 4
    Dernier message: 23/04/2008, 15h29
  4. Réponses: 3
    Dernier message: 16/11/2007, 11h03
  5. [VBA-E] Comment accéder à une variable tableau située dans un autre module
    Par jeanpierreco dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 17/02/2007, 13h15

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