Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



Création d'un composant C++ Builder

Par CGi

Le 10 juillet 2003


3 - Ajouter une propriété de type TStrings à un composant :

Nous allons voir comment inclure une propriété de type TStrings (Liste de chaînes) dans un composant, chose qui n'est pas aussi intuitive que cela, de plus l'aide de C++ Builder ne fournit rien à ce sujet.
Pour l'exemple nous allons faire un composant très simple de type TLabel. Il descendra donc de TCustomLabel, tout comme le composant TLabelDate que nous avions créé dans le premier chapitre. Il affichera une chaîne de caractères de type AnsiString appartenant à une TStringList en fonction d'une propriété Indice que nous créerons pour la circonstance. Cette TStringList sera incorporée à notre composant, elle contiendra par défaut les jours de la semaine et pourra être modifiée dans l'inspecteur d'objets. Nous nommerons donc ce composant TLabelIndice. Nous allons maintenant écrire son code.

Fichier "labelindice.h" :

#ifndef LabelIndiceH
#define LabelIndiceH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TLabelIndice : public TCustomLabel
{
private:
        TStringList *FListe;
        int FIndice;
        void __fastcall ListeChange(TObject *Sender);
protected:
        virtual void __fastcall SetListe(TStrings *AListe);
        virtual TStrings* __fastcall GetListe();
        virtual void __fastcall SetIndice(int AIndice);
        AnsiString __fastcall GetLabelText();
public:
        __fastcall TLabelIndice(TComponent* Owner);
        virtual __fastcall ~TLabelIndice();
__published:
        
        // Propriétés héritées :
        __property Align;
        __property Color;
        __property Font;
        __property Alignment;
        __property Layout;
        __property Anchors;
        __property AutoSize;
        __property Transparent;
        // Nouvelles propriétés :
        __property int Indice =  {read=FIndice, write=SetIndice};
        __property TStrings *Liste = {read=GetListe, write=SetListe};
};
//---------------------------------------------------------------------------
#endif

Dans le fichier en-tête "labelindice.h" section private nous déclarons un pointeur sur une TStringList FListe qui contiendra nos chaînes à afficher, un entier FIndice qui nous servira à accéder à nos chaînes. Ces deux données membres seront accessibles depuis l'inspecteur d'objets via les propriétés Liste et Indice. Nous y déclarons aussi une méthode ListeChange qui actualisera le LabelIndice si la liste de chaînes a changé. Cette méthode sera appelée par un événement OnChange de la TStringList.
Dans la section protected nous déclarons les méthodes SetListe et GetListe appelées par les fonctions write et read de la propriété Liste. Vous avez dû remarquer que les méthodes appelées par write ont toujours un paramètre du type de la propriété et renvoient void et celles appelées par read n'ont pas de paramètres et renvoient une valeur du type de la propriété. Par principe le nom de la méthode appelée par read commence par "Get" et celle appelée par write par "Set" suivi du nom de la propriété auquel elles correspondent. Il est conseillé de les déclarer virtual au cas ou votre composant serait dérivé. Nous y déclarons aussi la méthode GetLabelText déjà vue au 1er chapitre et SetIndice pour mettre à jour la propriété Indice. Dans la section __published les propriétés héritées puis les deux nouvelles propriétés Liste et Indice.


Fichier "labelindice.cpp"

#include <vcl.h>

#pragma hdrstop

#include "LabelIndice.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
//  ValidCtrCheck est utilisé pour vérifier que les composants créés n'ont
// aucune fonction virtuelle pure.
static inline void ValidCtrCheck(TLabelIndice *)
{
        new TLabelIndice(NULL);
}
//---------------------------------------------------------------------------
__fastcall TLabelIndice::TLabelIndice(TComponent* Owner)
        : TCustomLabel(Owner)
{
        ControlStyle << csOpaque;
        FListe = new TStringList();
        FListe->OnChange = ListeChange;
        FIndice = 0;
        FListe->Add("Lundi");
        FListe->Add("Mardi");
        FListe->Add("Mercredi");
        FListe->Add("Jeudi");
        FListe->Add("Vendredi");
        FListe->Add("Samedi");
        FListe->Add("Dimanche");
}
//---------------------------------------------------------------------------
__fastcall TLabelIndice::~TLabelIndice()
{
      delete FListe;
}
//---------------------------------------------------------------------------
void __fastcall TLabelIndice::SetIndice (int AIndice)
{
       if (AIndice>=0 && AIndice < Liste->Count)  FIndice = AIndice;
       else Application->MessageBox("La valeur de l'indice hors limite.",
                                                           "Erreur", MB_OK);
       Invalidate();
       AdjustBounds();
}
//---------------------------------------------------------------------------
AnsiString __fastcall TLabelIndice::GetLabelText()
{
     if(Liste->Count>0)
          return Liste->Strings[Indice];
     else return "Vide";
}
//---------------------------------------------------------------------------
TStrings* __fastcall TLabelIndice::GetListe()
{
      return FListe;
}
//---------------------------------------------------------------------------
void __fastcall TLabelIndice::SetListe(TStrings *AListe)
{
      FListe->Assign(AListe);
}
//---------------------------------------------------------------------------
void __fastcall TLabelIndice::ListeChange(TObject *Sender)
{
      Invalidate();
      AdjustBounds();
}
//---------------------------------------------------------------------------
namespace Labelindice
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TLabelIndice)};
                 RegisterComponents("MesCompo", classes, 0);
        }
}
//---------------------------------------------------------------------------

Nous allons voir maintenant l'implémentation du composant en commençant par le constructeur. Nous y créons tout d'abord notre TStringList, nous affectons la méthode ListeChange à l'événement OnChange de la TStringList, nous initialisons FIndice à zéro, puis nous remplissons la liste de chaînes avec les jours de la semaine.
La TStringList étant créée dynamiquement nous la détruirons donc dans le destructeur.
La méthode SetIndice affecte la nouvelle valeur à FIndice et affiche la chaîne correspondante. Au cas où cette valeur serait hors limites, c'est-à-dire inférieure à zéro ou supérieure au nombre de chaînes moins une de la liste de chaînes, c'est une boîte de message qui s'affiche indiquant l'erreur. Nous pouvons remarquer que cette boîte de message s'affiche aussi bien à l'exécution qu'à la conception.
La méthode GetListe retourne un pointeur sur la Liste de chaînes FListe qui permettra à la propriété de récupérer ses valeurs.
La méthode SetListe par l'intermédiaire de la méthode Assign copie le contenu de la propriété Liste dans la liste de chaînes FListe.
La méthode ListeChange pour l'actualisation de l'affichage.
Les propriétés qui sont des objets de la VCL se créent donc sur ce principe, ces objets ne pouvant être créés que dynamiquement.


CGi

Avec la contribution d'Alacazam pour la relecture.

Télécharger les sources.
(Est inclus le fichier "labelindice.dcr" contenant l'icône qui le représente sur la palette de composants)





Sommaire

1 - Création d'un composant pas à pas.
2 - Création d'un composant graphique.
3 - Propriété de type TStrings.
4 - Propriété de type TBitmap et contrôle du Owner.
5 - Propriété de type enum.
6 - Contrôle fenêtré.
7 - Evénement personnalisé et sous-propriétés.
8 - Composant pouvant interagir avec ses semblables.
9 - Ressources dans un composant.
10 - Boîte de dialogue dans un composant.
11 - Composant conteneur.
12 - Les éditeurs de composants. Nouveau



C/C++
  Les pointeurs du C/C++.   Les listes chaînées.             Liste simple.             Liste triée.             Liste double.   Les arbres.   Les tas.   Le C orienté objets ?

  1 - La fenêtre principale.   2 - Contrôles et messages.   3 - Les commandes.   4 - Dialogue std.   5 - Contexte de périph.   6 - Dessiner.   7 - Les ressources.   8 - Dialogue perso.   9 - Dialogue comm.   10 - Les accélérateurs.

Assembleur
  Assembleur sous Visual C++.

C++ BUILDER
  Trucs et astuces.   Composant.   TRichEdit.   TDrawGrid.   Application MDI.   TThread.   wxWidgets.   Style Win XP.

  Première application.   Construire un menu.   Dessiner.   Sisers, Timers...   Dialogues standards.   Dialogues perso.

DotNet
  Composant C# Builder.   Contrôle WinForm.   Application MDI.

Java
  Applet java.





Copyright 2002-2016 CGi - Tous droits réservés CGi. Toutes reproduction, utilisation ou diffusion de ce document par quelque moyen que ce soit autre que pour un usage personnel doit faire l'objet d'une autorisation écrite de la part de l'auteur, propriétaire des droits intellectuels.
Les codes sources de ce document sont fournis en l'état. L'utilisateur les utilise à ses risques et périls, sans garantie d'aucune sorte de la part de l'auteur. L'auteur n'est responsable d'aucun dommage subi par l'utilisateur pouvant résulter de l'utilisation ou de la distribution des codes sources de ce document.
De la même façon, l'auteur n'est en aucun cas responsable d'une quelconque perte de revenus ou de profits, ou de données, ou de tous dommages directs ou indirects, susceptibles de survenir du fait de l'utilisation des codes sources de ce document, quand bien même l'auteur aurait été averti de la possibilité de tels dommages. L'utilisation des codes sources de ce document vaut acceptation par l'utilisateur des termes de la licence ci-dessus.

Contacter le responsable de la rubrique C