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

C++Builder Discussion :

Initialisation d'un composant d'une forme


Sujet :

C++Builder

  1. #1
    Invité
    Invité(e)
    Par défaut Initialisation d'un composant d'une forme
    Bonjour,

    Une des formes de mon application (un descendant de TFrame) a, parmi ses composants, un autre descendants de TFrame, dont j'ai surchargé le constructeur. Donc j'ai un composant enfant et un composant, avec une entete du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class TMonEnfant : public TFrame {
    public:
    TMonEnfant(TComponent *owner, int param=0): TFrame(owner){...}
    }
     
    class TMonParent : public TFrame {
    __published:
       	TMonEnfant *enfant;
    }
    Actuellement le composant enfant est créé automatiquement quand on crée son parent, et le constructeur de TMonEnfant est bien appelé, avec le second paramètre par défaut (à zéro dans l'exemple)

    Maintenant, je voudrais changer ce paramètre dans le constructuer, en passant une liste d'initialisation au parent:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TMonParent(TComponent *owner) : TFrame(owner),enfant(owner,1) {}
    Et là j'ai deux questions :

    1- ca me donne un message : ne peut convertir int en TMonEnfant*, donc apparemment, l'initialisation de la liste enfant(owner,1) ne reconnait pas le constructeur, pourquoi?
    2- est ce bien "owner" qu'il faut passer? ou (TComponent *)this?

    Merci d'avance,
    Francois

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 057
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 057
    Par défaut
    Comment est créé la TMonEnfant ?
    Via l'IDE en Design Time
    Par le code par un new en RunTime ?
    __published sous-entend un chargement par DFM, tu es sur de cela ? j'en doute !
    Si Enfant est présent en DesignTime dans Parent, attention à ne pas créer deux fois l'Enfant :
    - une fois par DFM, Stream.ReadComponentRes et ses amis
    - une fois par constructeur manuel !

    ensuite, tu n'as pas redéfini le constructeur de TMonParent !
    Soit cohérent AOwner est le paramètre dans le constructeur de TFrame, reprend le même nom !
    A comme Argument, permettant de différencier de Owner la propriété !
    Tu n'as pas mentionné le __fastcall, dans la redéfinition (virtual), cela ne provoque-t-il pas un warning de méthode masquée (voir W8022 et HIDESBASE)

    Je n'aime pas trop les constructeurs inline sauf pour les exceptions

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class TMonEnfant : public TFrame {
    public:
      __fastcall virtual TMonEnfant(TComponent *AOwner, int param = 0);
    }
     
    class TMonParent : public TFrame
    {
    private:
      TMonEnfant *FEnfant;
    public:
      __fastcall virtual TMonParent(TComponent *AOwner);
     
      property TMonEnfant *Enfant = {read=FEnfant}; // garanti qu'on peut accéder à Enfant sans pouvoir changer la référence !
    }
    Ensuite, tu ne peux pas initialiser enfant sans un new

    soit comme ceci façon C++

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    __fastcall TMonParent::TMonParent (TComponent *AOwner)
      : TFrame(AOwner),
      FEnfant(new TMonEnfant(AOwner, 1))
    {
     
    }
    soit comme ceci façon C++ VCL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    __fastcall TMonParent::TMonParent(TComponent *AOwner)
      : TFrame(AOwner)
    {
      FEnfant() = new TMonEnfant(AOwner, 1);
    }
    Sinon effectivement, this pourrait être plus approprié que AOwner

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    __fastcall TMonParent::TMonParent(TComponent *AOwner)
      : TFrame(AOwner)
    {
      FEnfant() = new TMonEnfant(this, 1); // pas besoin de préciser (TComponent*)this
    }
    ou même NULL et un destructeur !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    __fastcall TMonParent::TMonParent(TComponent *AOwner)
      : TFrame(AOwner)
    {
      FEnfant = new TMonEnfant((TComponent*)NULL, 1);
    }
     
    __fastcall TMonParent::~TMonParent()
    {
      delete FEnfant;
      FEnfant = NULL;
    }


    et pour finir TMonEnfant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    __fastcall TMonEnfant::TMonEnfant (TComponent *AOwner, int param = 0)
      : TFrame(AOwner)  
    {
      ... param ...
    }
    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
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Comment est créé la TMonEnfant ?
    Via l'IDE en Design Time
    Par le code par un new en RunTime ?
    __published sous-entend un chargement par DFM, tu es sur de cela ? j'en doute !
    TMonEnfant est créé via l'IDE. Le TMonParent est créé par un new, qui instancie automatiquement ses membres, en en particulier TMonEnfant. C'est sur cette instanciation automatique que je voudrais intervenir.

    En gros, tu as qq part dans le code un appel du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    new TMonParent(owner);
    qui va appeler le constructeur de TMonParent, qui va construire ses enfants, et en particulier TMonEnfant. C'est cet appel implicite au constructeur de TMonEnfant que je voudrais rendre paramétrable, soit en passant un second paramètres au constructeur de TMonParent, soit sur la base d'une variable externe.

    Je ne crois pas que je puisse le faire en surchargeant le constructeur de TMonParent: à ce moment, TMonEnfant est déjà instancié. Pour un membre de classe normal, je le ferais en passant une liste d'initialisation. C'est ce que j'essaye de faire ici, et qui n'a pas l'air de marcher.

    Citation Envoyé par ShaiLeTroll Voir le message
    Tu n'as pas mentionné le __fastcall, dans la redéfinition (virtual), cela ne provoque-t-il pas un warning de méthode masquée
    Non, je l'ai viré en récrivant l'exemple, il est dans le code d'origine. Mais je pense que c'est par là qu'il faudrait chercher. En essayant de tracer le constructeur à deux paramètres de TMonEnfant, je me suis rendu compte qu'il n'était apparemment pas généré...

    Francois

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 057
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 057
    Par défaut
    N'inclu pas TMonEnfant dans TMonParent via la Conception !

    Effectivement, c'est le DFM qui va dans ce cas va appeler le constructeur virtuel (oui ça en théorie ça n'existe pas en C++, c'est une bidouille pour supporter les fonctionnalités Delphi)
    C'est ce que j'évoquais en mentionnant Stream.ReadComponentRes et ses amis

    Si tu reste en mode Conception :
    Ajoute une propriété à TMonEnfant que TMonParent pourra modifier lors de son constructeur
    Plus exactement durant AfterConstruction ou peut être même TComponent.Loaded

    Avec un TForm, j'aurais aucun problème, le Constructeur de la TForm a été appelé AVANT le constructeur de sa propre classe, le DFM est chargé, les objets sont instanciés !
    La TFrame, je ne maîtrise pas (une TForm Parented fait très bien la même chose en plus souple)
    Je pense que le constructeur est appelé pendant le chargement de la DFM, du coup, possible que FEnfant ne soit pas encore créer !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    __fastcall TMonParent::Loaded()
    {
      FEnfant.Dummy = 1;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    __property int Dummy = {read=FDummy, write=SetDummy};


    SetDummy sera automatiquement appelé par l'affectation et tu pourras y déporter le traitement prévu dans le constructeur !

    Si tu retire TMonEnfant de TMonParent, tu pourras faire ton New !
    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
    Invité
    Invité(e)
    Par défaut
    Merci beaucoup, c'est très clair.

    Si je passe par les DFM, je perds la main sur le processus d'instanciation de la forme (ou de la frame), et je dois intervenir à la fin de celui ci. Si j'instancie à l'exécution, ben, c'est comme en C++.

    Francois

Discussions similaires

  1. Probleme avec plus de 50 composants dans une form
    Par dalton5 dans le forum Windows Forms
    Réponses: 7
    Dernier message: 18/02/2007, 19h23
  2. Réponses: 5
    Dernier message: 01/11/2006, 16h04
  3. [C#][VS2005] centrer composants dans une form
    Par camilero dans le forum Windows Forms
    Réponses: 10
    Dernier message: 06/07/2006, 11h48
  4. Réponses: 2
    Dernier message: 06/06/2006, 08h32
  5. Envoie d'un message a TOUS les composant d'une form
    Par chddv dans le forum Composants VCL
    Réponses: 7
    Dernier message: 15/09/2003, 09h47

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