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)
|