Developpez.com - C
X

Choisissez d'abord la catégorieensuite la rubrique :



Création d'un composant C++ Builder

Par CGi

Le 14 septembre 2004


12 - Les éditeurs de composants :

Introduction :

Dans ce chapitre nous allons voir à l'aide d'un exemple comment créer un éditeur de composants. On appelle éditeur de composants les actions pouvant être exécutées à la conception via des options de menus que l'on peut ajouter à son menu contextuel, destiné en principe à modifier ses propriétés. La première action pouvant aussi être appelée par un double click sur le composant.
Pour cet exemple nous ferons un composant descendant du composant TShape, semblable à celui du chapitre 10. Nous y utiliserons la même boîte de dialogue, à une différence près, c'est que nous pourrons appeler cette boîte de dialogue à la conception pour modifier la propriété brush.color de ce composant.
Le code de la boîte de dialogue étant identique à celle du chapitre 10 nous ne reviendrons donc pas dessus.

Création du composant :

Vous créez le composant selon la procédure habituelle, vous lui donnez comme ancêtre la classe TShape et vous le nommez "TShapeColorEx". Vous avez maintenant le code minimum du composant.

Fichier "ShapeColorEx.h"

#ifndef ShapeColorExH
#define ShapeColorExH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <ExtCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TShapeColorEx : public TShape
{
private:
protected:
public:
        __fastcall TShapeColorEx(TComponent* Owner);
__published:
};
//---------------------------------------------------------------------------
#endif

Fichier "ShapeColorEx.cpp"

#include <vcl.h>
#pragma hdrstop

#include "ShapeColorEx.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(TShapeColorEx *)
{
        new TShapeColorEx(NULL);
}
//---------------------------------------------------------------------------
__fastcall TShapeColorEx::TShapeColorEx(TComponent* Owner)
        : TShape(Owner)
{
}
//---------------------------------------------------------------------------
/*namespace Shapecolorex
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TShapeColorEx)};
                 RegisterComponents("MesCompo", classes, 0);
        }
}*/

Nous ne changerons rien à son code, son comportement à l'exécution étant identique au TShape. Mais, nous supprimerons le code destiné à l'enregistrement du composant dans l'EDI.

Partie du code à supprimer :

namespace Shapecolorex
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TShapeColorEx)};
                 RegisterComponents("MesCompo", classes, 0);
        }
}

Création de l'éditeur :

Nous allons maintenant ajouter les options de menu au menu contextuel du composant afin de pouvoir appeler la boîte de dialogue et une boîte de message. Pour cela nous allons créer un nouveau fichier cpp ou nous définirons une classe dérivé de la classe TComponentEditor. Nous la nommerons TShapeColorEditor. Nous allons y redéfinir trois méthodes : GetVerbCount, GetVerb, ExecuteVerb.
GetVerbCount doit retourner le nombre d'option du menu.
GetVerb doit retourner le texte de chaque option de menu en fonction de l'index qu'il reçoit en paramètre.
ExecuteVerb doit exécuter une action en fonction du paramètre Index qu'il reçoit en paramètre.
Vous n'avez pas à vous occuper de l'utilisation de cette classe, c'est l'EDI de C++ Builder qui s'en chargera, vous avez juste à la définir.

Fichier "ColorEditor.h"

#ifndef ColorEditorH
#define ColorEditorH

#include <SysUtils.hpp>
#include <Classes.hpp>
#include <Controls.hpp>
#include <ExtCtrls.hpp>

#include <DesignEditors.hpp> // pour TComponentEditor

class PACKAGE TShapeColorEditor : public TComponentEditor
{
    virtual void __fastcall ExecuteVerb(int Index);
    virtual AnsiString __fastcall GetVerb(int Index);
    virtual int __fastcall GetVerbCount(void);
};
//---------------------------------------------------------------------------
#endif

Voyons maintenant l'implémentation des 3 méthodes de la classe TShapeColorEditor : Comme dit plus haut GetVerbCount retourne le nombres d'options de menu, donc deux en ce qui nous concerne. GetVerb retourne les textes des options du menu, donc "Couleur..." pour l'index 0 et "A propos..." pour l'index 1. ExecuteVerb appelle les boîtes de dialogue dans une structure de contrôle "switch", nous ouvrirons la boîte de message pour l'index 1 et notre boîte de dialogue de changement de couleur pour l'index 0. A savoir que celle appelée par l'index 0 sera celle qui surgira lors d'un double click sur le composant, à la conception. La boîte de dialogue de changement de couleur est initialisée avec la couleur du composant qui l'appelle, pour récupérer cette couleur on utilise le pointeur Component fournit par le concepteur de l'EDI. Il suffit de le transtyper en un pointeur sur TShapeColorEx pour pouvoir l'utiliser. Comme au chapitre 10, il faut inclure le fichier entête de la boîte de dialogue "DlgColor.h", et indiquer l'ajout du fichier "DlgColor.obj" par la directive : #pragma link "DlgColor.obj".


Fichier "ColorEditor.cpp"

#include <vcl.h>
#pragma hdrstop

#include "ColorEditor.h"
#include "ShapeColorEx.h"
#include "DlgColor.h" // Fichier entête de la boîte de dialogue
#pragma link "DlgColor.obj" // Fichier obj de la boîte de dialogue

//---------------------------------------------------------------------------

#pragma package(smart_init)

int __fastcall TShapeColorEditor::GetVerbCount(void)
{
  return 2;
}
//---------------------------------------------------------------------------
void __fastcall TShapeColorEditor::ExecuteVerb(int Index)
{
  switch (Index) {

    case 0 : DlgColor1 = new TDlgColor1(NULL);
             DlgColor1->Shape1->Brush->Color =
                                     ((TShapeColorEx *)Component)->Brush->Color;
             DlgColor1->ScrollBar1->Position =
                          GetRValue(((TShapeColorEx *)Component)->Brush->Color);
             DlgColor1->ScrollBar2->Position =
                          GetGValue(((TShapeColorEx *)Component)->Brush->Color);
             DlgColor1->ScrollBar3->Position =
                          GetBValue(((TShapeColorEx *)Component)->Brush->Color);
             if (DlgColor1->ShowModal() == mrOk)
                                ((TShapeColorEx *)Component)->Brush->Color =
                                                DlgColor1->Shape1->Brush->Color;
             delete DlgColor1;
             break;

    case 1 : ShowMessage("    TShapeColorEx\nCopyright - 2004 - CGi");
             break;
  }
}
//---------------------------------------------------------------------------
AnsiString __fastcall TShapeColorEditor::GetVerb(int Index)
{
  switch (Index) {
    case 0 : return("Couleur...");
    case 1 : return("A propos ...");
  }
}
//---------------------------------------------------------------------------
namespace Shapecolorex
{
        void __fastcall PACKAGE Register()
        {
              TComponentClass classes[1] = {__classid(TShapeColorEx)};
              RegisterComponents("MesCompo", classes, 0);
              RegisterComponentEditor(__classid(TShapeColorEx),
                                                  __classid(TShapeColorEditor));
        }
}

Comme vous pouvez le voir dans le code ci-dessus la partie enregistrement du composant dans l'EDI ce trouve dans ce fichier. Pour utiliser la classe TShapeColorEditor l'EDI doit la trouver. Il faut donc l'enregistrer, comme on enregistre les composants pour les utiliser à la conception, ceci est fait par la fonction RegisterComponentEditor:

              RegisterComponentEditor(__classid(TShapeColorEx),
                                                  __classid(TShapeColorEditor));

Attention au nom du namespace, il doit être identique au nom du composant sans le "T" la première lettre en majuscule, les suivantes en minuscules. A savoir que tous les descendants de ce composant comporteront aussi cet éditeur.

Vous ajoutez les deux fichiers sources "ShapeColorEx.cpp" et "ColorEditor.cpp" à un paquet, il faudra aussi lui ajouter le fichier "DlgColor.cpp" si ce n'est déjà fait (N'oublier pas que c'est la même boîte de dialogue que le TShapeColor du chapitre 10). Vous compilez le paquet comme pour les précédents composants.
J'ai compilé ce composant sous BCB6. Je l'ai aussi compilé sous BCB4, mais j'ai du changer le "#include <DesignEditors.hpp>" par "#include <dsgnintf.hpp>" dans le fichier "ColorEditor.h". Sous BCB6 il faut que le paquet comporte le fichier "designide.bpi" dans la partie "Requires". Sous BCB6 la séparation en deux fichiers du composant est nécessaire sinon il fait appelle en mode execution à des paquets de conception qui n'ont pas leur égal en exécution. (Sous BCB4 cela pouvait fonctionner avec le code des deux classes dans le même fichier.)
Quand votre composant sera fonctionnel, vous pourrez essayer un petite modification, dans la fonction RegisterComponentEditor vous remplacerez __classid(TShapeColorEx) par __classid(TShape) et vous recompilerez. Vous aurez la surprise de voir que le TShape standard de C++ Builder comporte lui aussi l'éditeur, de même que votre composant puisqu'il descend de TShape.

Voilà ce n'était encore pas très compliqué, ce système peut être utile pour améliorer l'édition de composants sophistiqués à la conception, tel le composant TChart.

A bientôt pour la suite,

CGi

Avec la contribution d'Erwy pour la relecture.

Télécharger les sources. (BCB6)







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