Vous êtes sur la page 1sur 112

Introduction C++ Builder

OURS BLANC DES CARPATHES

ISIMA 1988-1999

Introduction C++ Builder

Table des matires


1. C++ BUILDER : UN ENVIRONNEMENT RAD BAS SUR C++

1.1
UN ENVIRONNEMENT RAD
1.1.1
PHILOSOPHIE
1.1.2
LIMITATIONS
1.2
C++ BUILDER VIS VIS DE LA CONCURRENCE
1.2.1
C++ BUILDER VS DELPHI O LES FRRES ENNEMIS !
1.2.2
DIFFRENCES PAR RAPPORT BORLAND C++
1.2.3
C++ BUILDER CONTRE VB
1.3
POUR CONCLURE

7
7
7
8
8
8
9
9

2. LENVIRONNEMENT DE DVELOPPEMENT C++ BUILDER

10

LINTERFACE DE C++ BUILDER


2.2
LES COMPOSANTES DE C++ BUILDER
2.3
CRATION DUNE APPLICATION SIMPLE C++ BUILDER
2.4
LINSPECTEUR DOBJETS ET LES PROPRITS
2.5
LA PROPRIT NAME
2.6
MANIPULER LES VNEMENTS
2.7
C++ BUILDER ET LES EXCEPTIONS
2.8
UTILISEZ LA FENTRE DHISTORIQUE !

10
11
11
12
12
13
14
15

3. ETUDE DE LA VCL

17

3.1
3.2
3.3
3.3.1
3.3.2
3.4
3.4.1
3.4.2
3.4.3
3.4.4
3.4.5
3.5
3.5.1
3.5.2
3.5.3
3.5.4
3.6
3.6.1
3.6.2
3.6.3
3.6.4

17
17
18
18
19
19
20
22
23
23
24
25
27
28
29
31
31
31
32
35

ORGANISATION DE LA VCL
LES COMPOSANTS
LES CONTRLES
LES CONTRLES FENTRS
LES CONTRLES GRAPHIQUES
LES BOTES DE DIALOGUE STANDARD DE WINDOWS
LES BOTES DE DIALOGUE DE MANIPULATION DE FICHIERS
LA BOTE DE SLECTION DE COULEURS
LA BOTE DE SLECTION DE FONTE
LES BOTES DE RECHERCHE ET RECHERCHE / REMPLACEMENT
EXERCICE SUR LES BOTES DE DIALOGUE COMMUNES ( )
LES BOTES COMBO
EXERCICE RSOLU N1 ( )
)
EXERCICE RSOLU N2 (
)
EXERCICE RSOLU N3 (
)
EXERCICE N4 (
LES MENUS
MISE EN PLACE DUN MENU PRINCIPAL
LDITEUR DE MENUS
LUTILISATION DES MENUS
UN EXEMPLE DE MODIFICATION PAR PROGRAMMATION : LA LISTE DES DERNIERS FICHIERS
OUVERTS 35
3.6.5
LES MENUS SURGISSANTS
3.7
LES BOTES DROULANTES
3.7.1
GNRALITS

Introduction C++ Builder

37
37
37

3.7.2
QUE PEUT ON METTRE DANS UNE TSCROLLBOX ?
3.7.3
EXERCICE RSOLU : AFFICHAGE DUN DESSIN AVEC FACTEUR DE ZOOM (
3.8
LES ASCENSEURS SIMPLES
3.8.1
GNRALITS
3.8.2
EXERCICE (
)
3.9
LES BARRES DOUTILS DE C++ BUILDER
3.9.1
INSERTION DE CONTRLES STANDARD DANS UNE BARRE DOUTILS
3.9.2
LES BOUTONS GADGETS

38
38
40
40
41
42
42
42

4. UTILISATION MINIMALISTE DES BASES DE DONNES AVEC C++ BUILDER

44

4.1
4.1.1
4.1.2
4.2
4.3
4.3.1
4.3.2
4.4
4.4.1
4.4.2
4.4.3
4.4.4

44
44
45
47
50
51
53
53
54
56
56
58

MISE EN PLACE DE LA BASE DE DONNES


LOUTIL ADMINISTRATEUR BDE
CRATION DE LALIAS
ACCS AUX DONNES DANS C++ BUILDER
LES CONTRLES ORIENTS BASES DE DONNES
PRSENTATION TABULAIRE DUNE TABLE OU DUNE REQUTE
LES AUTRES CONTRLES
MANIPULATIONS LMENTAIRES SUR LES BASES DE DONNES
RALISATION DE JONCTIONS
LE FILTRAGE
CRATION DE FICHES MATRE / DTAIL
AJOUT DUN TUPLE DANS UNE OU PLUSIEURS TABLE

5. UTILISATION DU MODULE DE BASES DE DONNES

61

5.1
5.2
5.3
5.3.1
5.3.2
5.3.3
5.3.4
5.4

61
61
63
63
63
64
64
64

LE MODULE DE BASES DE DONNES


PRSENTATION DE LINTERFACE
AJOUT DE CHAMPS
LE NOM
LE TYPE
LA TAILLE
LA PRSENCE DANS LA CLEF PRIMAIRE
DFINIR DES INDEX SECONDAIRES

6. UTILISATION DES CONTRLES ACTIVEX

66

6.1
MISE EN PLACE
6.1.1
EDITION DE LA LISTE DES CONTRLES DISPONIBLES
6.1.2
RECENSEMENT DANS LA BASE DE REGISTRES DUN NOUVEAU COMPOSANT
6.1.3
CRATION DUNE UNIT
6.2
UTILISATION DUN CONTRLE ACTIVEX
6.3
DPLOIEMENT DUN PROGRAMME UTILISANT UN CONTRLE ACTIVEX

66
66
67
68
69
70

7. LCRITURE DE NOUVEAUX COMPOSANTS

71

7.1
GNRALITS
7.2
CRATION DUN NOUVEAU COMPOSANT
7.2.1
LEXPERT COMPOSANT
7.2.2
DE QUEL COMPOSANT DRIVER ?
7.3
EXERCICE RSOLU : CRATION DU COMPOSANT TLISTBOXCOOL

71
71
72
74
76

Introduction C++ Builder

7.3.1
7.3.2
7.3.3
7.3.4
7.4
7.4.1
7.4.2
7.4.3
7.4.4
7.4.5
7.5
7.6
7.6.1
7.6.2
7.6.3
7.6.4
7.7
7.7.1
7.7.2
7.7.3
7.7.4
7.7.5
7.8
7.8.1
7.8.2
7.9

MOTIVATION ET DROULEMENT GNRAL DE LEXERCICE


MISE EN PLACE
UTILISATION DU COMPOSANT
UTILISATION DUN COMPOSANT NON INSTALL SUR LA PALETTE
EXERCICE RSOLU N2 : LA CALCULETTE FRANCS EUROS
CRER LE COMPOSANT
CRER DES PROPRITS
GRER LASPECT VISUEL DU COMPOSANT
GESTION DES VNEMENTS INTERNES
AJOUTER LA SAISIE DU TAUX
EXERCICE RSOLU N3 RALISATION DUN COMPOSANT DE SAISIE DE DATE
GESTION DES VNEMENTS EXTERNES
MOTIVATION ET MISE EN UVRE
UN EXEMPLE SIMPLE
PRENDRE EN COMPTE LES VNEMENTS
EXERCICE : INTERDIRE LA MODIFICATION DE LA DATE (
)
CONVERSION DUNE BOTE DE DIALOGUE GNRIQUE EN COMPOSANT
MOTIVATION
FONCTIONNEMENT DE LENCAPSULATION
RALISATION
MISE EN PLACE DES PROPRITS
CODAGE DE LA MTHODE EXECUTE
RALISATION DUN COMPOSANT GRAPHIQUE
LE COMPOSANT AFFICHAGE DE GRAPHE
MISE EN UVRE
EXERCICES SUPPLMENTAIRES

76
77
83
83
83
84
84
86
93
96
98
101
101
101
103
105
105
105
106
107
107
108
108
109
109
110

8. EN GUISE DE CONCLUSION

Introduction C++ Builder

112

Table des illustrations


Figures
Figure 2.1 Linterface de C++ Builder......................................................................................................................10
Figure 2.2 Edition des proprits dans linspecteur dobjets......................................................................................12
Figure 2.3 Manipulation des gestionnaires dvnements ..........................................................................................13
Figure 2.4 Fentre dinterception dune exception ....................................................................................................14
Figure 2.5 Options du dbogueur de lEDI C++ Builder...........................................................................................15
Figure 2.6 Options de la fentre dhistorique.............................................................................................................16
Figure 3.1 La palette dialogues .................................................................................................................................20
Figure 3.2 Proprits des dialogues orients fichier ..................................................................................................21
Figure 3.3 Bote d'dition de la proprit filter..........................................................................................................21
Figure 3.4 Proprits de la bote de choix de couleur................................................................................................22
Figure 3.5 Les deux modes de fonctionnement de la bote de slection de couleurs....................................................22
Figure 3.6 Proprits de la bote de slection de police.............................................................................................23
Figure 3.7 Interface de lexercice sur les botes de dialogue......................................................................................25
Figure 3.8 Mise en place du menu principal ..............................................................................................................31
Figure 3.9 Le concepteur (ou diteur) de menus ........................................................................................................32
Figure 3.10 Le menu contextuel du concepteur de menus ( rpter trs vite 3 fois ) ...............................................33
Figure 3.11 Les modles de menus.............................................................................................................................33
Figure 3.12 Aprs insertion du menu daide par dfaut .............................................................................................34
Figure 3.13 Cration dun sous menu ........................................................................................................................34
Figure 3.14 Rservation des emplacements de menu pour la liste des derniers fichiers ouverts .................................35
Figure 3.15 Partie visible et tendue virtuelle dun TScrollBox ............................................................................37
Figure 3.16 Utilisation dune TScrollBox pour le problme du dessin Zoomer ..................................................39
Figure 3.17 Utilisation de TScrollBar ..................................................................................................................41
Figure 4.1 Ladministrateur BDE en mode configuration ..........................................................................................45
Figure 4.2 Slection du type de la base de donnes ...................................................................................................46
Figure 4.3 Slection du nom de lalias et du chemin des donnes ..............................................................................46
Figure 4.4 Premire tape de la cration dun composant TTable : slection dun alias de base de donnes .............48
Figure 4.5 Les composants TDataSource ..............................................................................................................50
Figure 4.6 Prsentation tabulaire des donnes dans un composant TDBGrid ...........................................................51
Figure 4.7 Manipulation des colonnes .......................................................................................................................52
Figure 4.8 cration dun champ de donnes...............................................................................................................55
Figure 4.9 Ralisation dune jonction : tape 2 .........................................................................................................55
Figure 4.10 Cration dune liaison Matre / Dtail : Mise en place ...........................................................................58
Figure 4.11 Fin de cration dune liaison Matre / Dtail..........................................................................................58
Figure 5.1 Liste des formats disponibles en cration de table ....................................................................................61
Figure 5.2 Fentre principale du MDD......................................................................................................................62
Figure 5.3 liste des options disponibles .....................................................................................................................62
Figure 5.4 Types de donnes disponibles ...................................................................................................................63
Figure 5.5 la case Index ............................................................................................................................................64
Figure 5.6 la liste des index secondaires....................................................................................................................64
Figure 5.7 Dfinition des index secondaires ..............................................................................................................65
Figure 6.1 La bote de dialogue des composants Active X..........................................................................................66
Figure 6.2 Fentre des composants ActiveX aprs enregistrement dun composant....................................................67
Figure 6.3 Installation du composant dans un paquet ............................................................................................68
Figure 6.4 mise jour de la palette ...........................................................................................................................69
Figure 6.5 le composant Calendrier plac sur une fiche ............................................................................................70
Figure 6.6 Evnements associs au contrle calendrier .............................................................................................70
Figure 7.1 Expert composant .....................................................................................................................................72
Figure 7.2 Spcification du paquet d'installation d'un nouveau composant................................................................73
Figure 7.3 dtermination de la classe de base dun nouveau composant ....................................................................74
Figure 7.4 Affichage des index et des lments slectionns dune bote de liste par le Programme 7.8.....................77
Figure 7.5 Cration dun nouveau paquet..................................................................................................................78
Figure 7.6 le gestionnaire de paquets ........................................................................................................................78

Introduction C++ Builder

Figure 7.7 Liste des composants dun paquet.............................................................................................................79


Figure 7.8 Avertissement de recompilation dun paquet.............................................................................................82
Figure 7.9 Avertissement de mise jour du registre des composants .........................................................................82
Figure 7.10 Mise jour de la palette !.......................................................................................................................83
Figure 7.11 Le composant calculette avec ses proprits associes ...........................................................................84
Figure 7.12 Bote de saisie du taux de lEuro ............................................................................................................96
Figure 7.13 Composant de saisie de date...................................................................................................................98
Figure 7.14 Manipulation des vnements externes du composant de saisie de date ................................................103
Figure 7.15 Bote de dialogue de saisie gnrique...................................................................................................105
Figure 7.16 les proprits de notre composant saisie...............................................................................................106
Figure 7.17 Format dun fichier de graphe..............................................................................................................109
Figure 7.18 Visualisation du composant Graphe......................................................................................................110

Programmes
Programme 3.1 Ajout dune ligne saisie dans une bote combo..................................................................................27
Programme 3.2 Affichage de styles de traits dans une bote combo............................................................................29
Programme 3.3 Lvnement OnMeasureItem de calcul de hauteur dun lment de bote combo .............................30
Programme 3.4 trac dun trait dpaisseur variable dans une bote combo ..............................................................31
Programme 3.5 Dclarations relatives la mise en place de la liste des derniers fichiers ouverts .............................36
Programme 3.6 Code dimplmentation du remplissage de la liste ............................................................................37
Programme 7.1 Programme daffichage des index et des lments slectionns dune bote de liste ..........................77
Programme 7.2 Vers une utilisation plus simple des botes de listes...........................................................................77
Programme 7.3 Dclaration de la code TListBoxCool ...............................................................................................80
Programme 7.4 Implmentation de la mthode daccs getIndices ......................................................................81
Programme 7.5 Utilisation de la proprit Indices ................................................................................................82
Programme 7.6 Mise en place dattributs de stockage des proprits ........................................................................85
Programme 7.7 Dclaration de mthodes daccs et des proprits ...........................................................................85
Programme 7.8 dclaration simplifie de la classe Set ............................................................................................88
Programme 7.9 Constructeur du composant Calculette..............................................................................................91
Programme 7.10 Publication des proprits caches .................................................................................................91
Programme 7.11 code dimplmentation des mthodes daccs en criture aux proprits financires ..................92
Programme 7.12 Prototype des vnements de type Notification................................................................................94
Programme 7.13 Prototypes des vnements associs au clavier ...............................................................................95
Programme 7.14 implmentation dun gestionnaire dvnement interne...................................................................96
Programme 7.15 Utilisation de la bote de dialogue de saisie du taux de lEuro........................................................98
Programme 7.16 Code du constructeur....................................................................................................................100
Programme 7.17 Code de Paint ...............................................................................................................................101
Programme 7.18 Dclaration et publication dvnements utilisateur .....................................................................102
Programme 7.19 Code associ aux vnements externes du composant de saisie de date.........................................103
Programme 7.20 Code gnrique de prise en compte dun gestionnaire utilisateur..................................................104
Programme 7.21 Prise encompte des vnments spcifiques ..................................................................................104
Programme 7.22 Mise en place du composant .........................................................................................................107
Programme 7.23 Cration des proprits du nouveau composant ............................................................................108
Programme 7.24 la mthode Execute ...................................................................................................................108

Tableaux
Tableau 2.1 Quelques prfixes de nommage pour les composants VCL ......................................................................13
Tableau 3.1 Codes de retour des boutons modaux......................................................................................................20
Tableau 3.2 Quelques proprits du contrle TTrackBar .......................................................................................39
Tableau 3.3 Proprits fondamentales des ascenceurs (TScrollBar).....................................................................41
Tableau 4.1 Correspondance entre oprations dalgbre relationnel et oprations C++ Builder...............................53
Tableau 7.1 Les mthodes de la classe Set ...............................................................................................................89

Introduction C++ Builder

1. C++ Builder : un environnement RAD bas sur


C++
C++ Builder est le nouvel environnement de dveloppement bas sur C++
propos par Borland pardon Inprise ! Fort du succs de Delphi, Borland a repris la
philosophie, linterface et la bibliothque de composants visuels de ce dernier pour
ladapter depuis le langage Pascal Orient Objet vers C++ rpondant ainsi une large
faction de programmeurs peu enclins lutilisation du Pascal quils jugent quelque
peu dpass.

1.1 Un environnement RAD


1.1.1 Philosophie
Tout dabord C++ est un outil RAD, cest dire tourn vers le dveloppement
rapide dapplications (Rapid Application Development) sous Windows. En un mot,
C++ Builder permet de raliser de faon trs simple linterface des applications et de
relier aisment le code utilisateur aux vnements Windows, quelle que soit leur
origine (souris, clavier, vnement systme, etc. )
Pour ce faire, C++ Builder repose sur un ensemble trs complet de composants
visuels prts lemploi. La quasi totalit des contrles de Windows (boutons, botes de
saisies, listes droulantes, menus et autres barres doutils) y sont reprsents,
regroups par famille. Leurs caractristiques sont ditables directement dans une
fentre spciale intitule diteur dobjets. Lautre volet de cette mme fentre permet
dassocier du code au contrle slectionn.
Il est possible dajouter lenvironnement de base des composants fournis par
des socits tierces et mme den crer soit mme.
Un outil RAD cest galement un ensemble de squelettes de projets qui
permettent de crer plus facilement une application SDI ou MDI, une DLL, des objets
OLE, etc. A chacun de ces squelettes est habituellement associ un expert qui par une
srie de botes de dialogues permet de fixer une partie des options essentielles la
ralisation du projet associ.

1.1.2 Limitations
Tout dabord, il faut savoir que la technologie RAD ne sapplique quau squelette
ou linterface dune application. Bien entendu, toute la partie spcifique votre
projet reste votre charge.
Du point de vue portabilit, le code C++ Builder nest pas compatible C++ ANSI.
Ceci est du la gestion de la bibliothque des composants visuels et en particulier de
leurs proprits. Pour lheure, il suffit de savoir quune proprit dun objet est
assimilable un attribut auquel on accde par affectation directe dans le code
utilisateur. Toutefois, cet accs apparemment direct masque lutilisation de mthodes
daccs en lecture et / ou criture. Ce systme de proprit a t mis au point par
Introduction C++ Builder

Microsoft dans le cadre dOLE puis dmocratis par le langage Visual Basic. Bien
intgr dans le langage Pascal Orient Objet, support, rappelons-le, de Delphi, il a
fallu tendre le C++ pour ly intgrer, notamment en ajoutant le mot clef non ANSI
__property. De fait, tout le code C++ Builder qui fait appel la VCL est non
portable. En revanche, toute partie du code de lapplication non directement lie
linterface peut trs bien tre crit en C++ ANSI. Plus que jamais, il convient
dadopter la dcomposition Interface / Donnes / Mthodes pour lcriture dune
application C++ Builder.

1.2 C++ Builder vis vis de la concurrence


Loin dtre exhaustive, cette partie ne vise qu placer C++ Builder dans le
cadre des outils RAD les plus prsents sur le march. Ayant peu travaill avec
Visual C++, je prfre ne pas prsenter de comparatif avec cet outil par soucis
dquit. Je prciserai mme, au bnfice de Visual C++, que ce dernier accorde une
bien meilleure place au modle Document/Interface/Contrleur que son rival, au
dtriment dune interface un peu plus complexe utiliser au premier abord.

1.2.1 C++ Builder vs Delphi o les frres ennemis !


Tout dabord, il faut savoir que, pour un mme problme, lexcutable fourni par
C++ Builder est toujours un peu plus gros que celui issu de Delphi. Ceci tient au fait
que la bibliothque de composants visuels utilise par les deux reste nativement celle
de Delphi, aussi lexcutable C++ Builder contient-il un module supplmentaire
destin faire le lien avec des objets au format Delphi.
En dehors de a, les deux outils sont trs similaires. Mon choix se portera tout
de mme sur C++ Builder car ce dernier permet une meilleure intgration des
contrles ActiveX et autres mcanismes issus dOLE.

1.2.2 Diffrences par rapport Borland C++


Les diffrences par rapport Borland C++ sont assez nombreuses. La premire
rside dans la nature du code produit. Si OWL, la bibliothque de gestion de la
programmation sous Windows et Borland C++ tait 100% compatible C++ ANSI, la
gestion de la VCL ne lest pas pour les raisons exprimes au paragraphe prcdent.
En outre, C++ Builder pose les problmes communment lis aux outils de haut
niveau. Par exemple, il est trs difficile daccder directement aux messages Windows.
En effet, sil est toujours possible dutiliser les primitives de lAPI Windows, ces
dernires ont elles - mme t encapsules dans une API de plus haut niveau,
fournissant certaines valeurs par dfaut des paramtres clef.
En outre, certains messages Windows se rvlent totalement inaccessibles.
Donnons un exemple li aux botes ddition de texte. Dans OWL, rappelons le, il tait
possible de passer la taille du tampon de saisie au constructeur de lobjet associ une
bote ddition. Il tait alors possible dassocier un vnement au remplissage du
tampon de saisie. Avec C++ Builder, cette facilit a disparu. En outre, les vnements
lis aux groupes de boutons radio ou de cases cocher sont grer individuellement
pour chacun deux. Il nest pas possible dutiliser un vnement de type
Introduction C++ Builder

CHILD_NOTIFY autorisant la gestion globale dun groupe de boutons par le contrle


groupe les englobant.
La gestion du modle document / visualisation tant prne par OWL (et
reprenant les principes du dcoupage donnes / mthodes / interface) est ici
abandonne. De fait, on ne retrouve plus les fameuses classes TDocument et TView
la base dun tel mcanisme. Il vous faudra composer vous mme pour respecter un tel
modle.
Alors, la question, faut il jeter Borland C++ au profit de C++ Builder ? je
rpondrai : faut voir Si vous gnrez des applications de bases de donnes axes
interface utilisateur la rponse est sans aucun doute : oui. A lvidence, la rponse
sera toujours oui sauf si vous avez besoin de descendre trs bas dans lexploitation
de Windows ou si vous gnrez des types de documents complexes avec des
applications bases sur le modle Document / Visualisation auquel cas il vaut mieux
rester sous Borland C++.

1.2.3 C++ Builder contre VB


Depuis quelques annes, Microsoft a propos le langage Visual Basic associ
un environnement RAD pour crire rapidement des applications Windows. En outre, il
est intgr aux applications de la suite bureautique Office sous la forme VBA et
permet de manipuler simplement les donnes de chaque application et offre une
certaine souplesse pour effectuer des appels OLE entre ces applications.
Sil se rvle trs agrable utiliser pour concevoir un micro outil usage
unique ou une macro-commande dans lun de vos logiciels prfrs, son utilisation
vaste chelle devient, mon avis, vite pnible. Deux syntaxes daffectation,
lutilisation quasi systmatique du fameux type variant, linefficacit des commandes
arithmtiques sont autant darguments brandis par les dtracteurs de Visual Basic
(dont je suis) et qui, tout chauvinisme mis part, cartent ce langage des
dveloppements importants.
Pour terminer cette partie, certains argueront (avec raison) de lexcellente
interface entre Visual Basic et JET, le moteur de base de donnes de Microsoft sur
lequel repose ACCESS. Il est vrai quACCESS offre un environnement de
programmation dapplications de bases de donnes particulirement efficace.
Toutefois, BDE, le moteur de base de donnes de Borland dont lAPI complte ainsi
que des contrles Windows orients donnes est incluses dans C++ Builder offre les
mmes fonctionnalits mme si, contrairement son concurrent, il est ncessaire
dinvoquer un programme complmentaire (fourni) pour dfinir graphiquement une
relation ou une requte.

1.3 Pour conclure


Souvenez vous que la programmation RAD est trs axe sur la dfinition de
linterface et que, si elle permet de gagner un temps considrable sur le traitement des
vnements les plus simples, elle ne vous sera daucun intrt voir mme dun certain
dsavantage lorsque vous voudrez composer des applications plus complexes.
Toutefois, dans limmense majorit des cas, je ne saurais trop recommander lusage de
tels outils.
Introduction C++ Builder

2. Lenvironnement de dveloppement C++ Builder


Aprs ces considrations somme toute assez philosophiques, nous allons
attaquer dsormais ltude de C++ Builder commencer par la prise en main de son
interface identique celle de son frre an : Delphi.

2.1 Linterface de C++ Builder


La figure 1 reprsente un exemple typique de linterface de C++ Builder au
cours dune session de travail.
Onglets des palettes
de composants

Palette doutils

Inspecteur dobjets

Code associ aux


lments dinterface

Palette de composants
active

Fentre dinterface en
cours de composition

Figure 2.1 Linterface de C++ Builder


Cette interface est assez droutante au premier abord car elle noccupe pas tout
lcran. De fait, une partie des crans des autres applications que vous utilisez (ou du
bureau !) est visible.
On peut toutefois distinguer plusieurs grandes parties :

La classique barre de menu


La barre doutils qui se dcompose en 2 grandes parties :

La palette doutils permettant deffectuer les oprations les plus


courantes (sauvegarde, ouverture de fentres, etc.)
Les palettes de composants disposes accessibles par des onglets

Introduction C++ Builder

10

Linspecteur dobjets qui permet de manipuler les proprits des composants


et dassocier du code leurs vnements
Les fentres dinterface cres par lutilisateur. Ce sont les fentres de
lapplication en cours de cration, elles portent ici le nom de fiche (form en
anglais). Certaines peuvent tre caches, dautres prsentes lcran. On
verra que dans la plupart des cas, leur position (ainsi que leurs autres
caractristiques gomtriques) lexcution sont le reflet exact de ce quelle
taient lors de la conception
Lditeur de code. A chaque fiche ouverte correspond deux fichiers source
(un fichier .h et un fichier .cpp) qui sont ditables dans cette fentre avec
mise en vidence de la syntaxe.

Dautres fentres auraient pu tre prsentes dans des phases spcifiques de


dveloppement. Citons ple-mle : les inspecteurs de variables du dbogueur, la liste
des points darrt, les diffrents experts, etc.

2.2 Les composantes de C++ Builder


Par dfaut, C++ Builder utilise un compilateur C++, un diteur de liens, un
compilateur de ressources et un gestionnaire de projets intgrs. Il est toutefois
possible de spcifier que vous dsirez lui faire utiliser les outils en ligne de commande
livrs conjointement ou mme dautres outils. Ce dernier cas, trs intressant lorsque
lon souhaite utiliser des modules compils dans dautres langages (cest tout de mme
un peu technique) doit tre tudi trs soigneusement. En particulier, il faut sassurer
que les diffrents codes soient compatibles.
Thoriquement, C++ Builder se charge de grer les imports et les exports des
diffrentes librairies dynamiques (DLL) utilises. Toutefois, vous pouvez grer cela
manuellement (notamment pour viter quune de vos propres DLL nexporte toutes ses
dfinitions, ce qui est le comportement par dfaut) en ditant manuellement le fichier
des dfinitions (.DEF) puis en appelant lutilitaire implib.

2.3 Cration dune application simple C++ Builder


C++ Builder permet de crer diffrents types de module trs simplement en se
laissant guider par des experts. Toutefois, il est possible de demander crer une
application simple en activant loption Nouvelle application du menu Fichier.
Les lments automatiquement crs sont les suivants : une fiche nomme Form1
ainsi que les fichiers associs Unit1.cpp et Unit1.h. Notons au passage que la
terminologie unit est directement calque sur celle chre Delphi et que les
fonctionnalits ainsi cres sont toujours renommables aprs coup.
Je recommande de toujours sauvegarder le projet juste aprs sa cration : on
vite ainsi la cration des fichiers de compilation dans les rpertoires par dfaut. Cette
opration est ralise avec la commande Sauvegarder le projet sous du menu
Fichier. Le projet en lui mme (fichier .bpr) est sauvegard aprs les diffrents
fichiers .cpp et .h.

Introduction C++ Builder

11

Une fois cette opration ralise, il reste raliser lapplication en crant les
objets dinterface et en leur associant des gestionnaires dvnements.

2.4 Linspecteur dobjets et les proprits


Linspecteur dobjets est une fentre deux volets respectivement spcialiss
dans ldition des valeurs des proprits des composants et lintendance de leurs
gestionnaires dvnements.
Nom et type de lobjet

Objet en cours de
modification

Proprits et leurs
valeurs

Figure 2.2 Edition des proprits dans linspecteur dobjets


La figure prcdente montre laspect de linspecteur dobjets lors de la
modification des proprits dun bouton radio.
Selon le type de la proprit, ldition se fera sous forme dune bote ddition de
texte simple, dans une liste drouler ou mme une fentre spcialise.

2.5 La proprit Name


Permettez-moi, sil vous plait, de jouer au prof gavant (je sais, je fais a trs
bien) et dinsister sur la proprit Name. Celle-ci est terriblement important car elle
vous permet daccder vos composants lintrieur de votre programme. Par dfaut,
lorsque vous ajoutez un composant une fiche, C++ Builder lui confre un nom
automatique du genre TypeNumro, par exemple le premier label que vous poserez
sur une fiche aura pour nom Label1 ce qui nest gure explicite !
Il est prfrable de respecter certaines conventions de nommage de ses
composants. Par exemple, il faut que le nom dun composant vous indique :

Le type du composant
Sa fonction

Lusage veut que la fonction soit dans le corps du nom alors que le type est
indiqu par un prfixe. La table suivante donne ( titre purement indicatif) quelques
uns des prfixes utiliss dans ce manuel.

Introduction C++ Builder

12

b:

bouton daction

lb :

label

br :

bouton radio

gb :

bote de groupe

cc :

case cocher

edit :

bote ddition

pl :

panel

me :

mmo

Tableau 2.1 Quelques prfixes de nommage pour les composants VCL

2.6 Manipuler les vnements


La manipulation des vnements est quelque peu plus complexe. La figure
suivante illustre quelques principes.
Liste des vnements
disponibles

Liste de mthodes que


lon pourrait affecter
lvnement

Nom de la
mthode
associe cet
vnement

Objet TImage
slectionn

Figure 2.3 Manipulation des gestionnaires dvnements


Tout dabord, il est important de rappeler certains principes :
Les gestionnaires dvnements sont toujours des mthodes de la fiche.
En effet, avec C++ Builder, les vnements gnrs par les contrles sont toujours
renvoys vers la fiche.
Ce mcanisme (connu sous le nom de notification au parent) est trs pratique
car il permet de simplifier considrablement la tche du programmeur : tous les
vnements pour une mme fiche sont gnrs au mme niveau. Nanmoins, il est
parfois gnant. Prenons, par exemple, le cas de la gestion dun groupe de boutons
radio.
Typiquement, ces derniers seront rassembls dans une fentre de groupe. Avec
Borland C++, il tait possible de rediriger les vnements gnrs par les boutons
radio vers la fentre de groupe et de les traiter ainsi avec une seule mthode. Avec la
mthode C++ Builder, tous les vnements tant automatiquement redescendus au
niveau de la fiche, il faudra grer individuellement les vnements ou ruser comme un
sioux.
Une mme mthode peut grer plusieurs vnements si son prototype le permet.

Introduction C++ Builder

13

Notons que la liste de paramtres dun gestionnaire dvnements contient


toujours au moins un paramtre nomm Sender, de type TObject* et qui contient
ladresse du composant ayant gnr le message. Dautres paramtres peuvent tre
prsents, par exemple :

Les positions de la souris


Ltat des touches de modification du clavier

Pour crer une nouvelle mthode de gestion dvnement, il suffit de double


cliquer dans lespace vide droite du nom de lvnement, une mthode avec le nom
par dfaut est alors cre. Son appellation reprend en partie le nom ou le type du
contrle gnrant lvnement et la dnomination de lvnement. Vous pouvez
galement choisir le nom vous mme.
Pour affecter une mthode dj existante un gestionnaire, il suffit de puiser
dans la liste droulante.

2.7 C++ Builder et les exceptions


Le comportement de C++ Builder vis vis des exceptions peut paratre parfois
droutant. En effet, la mise en place dun gestionnaire dexceptions, par exemple, pour
lexception EConvertError se traduit dabord par laffichage dun message du genre :

Figure 2.4 Fentre dinterception dune exception


Ce qui se traduit en clair par la phrase suivante : Le dbogueur intgr C++
Builder a intercept linterruption avant de vous passer la main. Notez au passage
que la fentre contient le message dexplication inclus dans toute exception C++
Builder : il sagit du texte entre guillemets Anglais.
Le plus important est de savoir que ce comportement nexiste que dans lEDI.
En effet, en excution indpendante, ce message napparatrait que si lexception
dclenche ntait pas traite ; si vous fournissez un handler dexception, celui-ci
serait activ normalement.
Dans de nombreux cas, ce fonctionnement de lEDI est plus une gne quun
atout. Il est toutefois possible de le dsactiver grce la bote de dialogue prsente
sur la page suivante directement issue du menu Outils
Options denvironnement,
onglet Dbogueur.

En plus de fournir de nombreuses options de configuration du dbogueur, cette


page nous permet de spcifier le comportement des exceptions lorsquun programme
C++ Builder est lanc depuis lEDI.

Introduction C++ Builder

14

Liste des catgories dexceptions


Le rond signifie que lexception est gre par
lEDI, la flche ajoute la notion de gestion la
reprise

Option activer pour


viter lEDI nintercepte les
exceptions que vous grez

Indique si, la sortie de la


fentre de lEDI,
lexception est gre ou non

Figure 2.5 Options du dbogueur de lEDI C++ Builder


Ainsi, toutes les catgories marques dun petit rond (de couleur rouge !) voir
la figure prcdente sont gres, dabord par lEDI et dans un second temps par le
programmeur. Il est trs facile de modifier ce comportement en slectionnant le
bouton radio Programme utilisateur.
En outre, si vous laissez lEDI grer votre interruption, il est possible de
spcifier le comportement de votre programme la sortie de la fentre de lEDI en
jouant sur les boutons radio A la reprise .
Par dfaut, les exceptions de lutilisateur sont ranges dans la rubrique
Exceptions C++ alors que les exceptions leves par la VCL sont dans la catgorie
Exceptions Delphi et dans la catgorie Exceptions C++ .
Le seul moyen dtre tranquille consiste donc dsactiver linterception par
lEDI de tout type dexception.

2.8 Utilisez la fentre dhistorique !


La fentre dhistorique des vnements est lun des mcanismes de traage des
programmes les plus mconnus de Windows. C++ Builder nous permet de consulter
ltat de cette fentre en lactivant dans le menu Voir.
La page de configuration des options du dbogueur permet galement de
modifier le comportement de cette fentre. Focalisons nous donc sur ce dernier aspect :

Introduction C++ Builder

15

Figure 2.6 Options de la fentre dhistorique


Deux grands types doptions sont grables :

La taille de lhistorique

Illimit
Nombre de lignes spcifiable par lutilisateur

Les catgories de message tracs

Les points darrt : chaque fois que lexcution est stoppe un


point darrt, un message est imprim dans la fentre
Les messages du processus : ils concernent, par exemple, le
chargement de DLL ou dinformations de dboguage au lancement du
programme
Les messages de fentre : chaque fois quune fentre reoit un
message, il y a mission dun message contenant :

) Le rcepteur du message
) Les paramtres (WPARAM et LPARAM)
Attention, si ce comportement peut se rvler trs pratique, il peut crer des
traces normes. En effet, on imagine rarement le volume considrable de
messages traits par les applications Windows.

Les messages de sortie sont crs par lutilisateur laide de la


commande API OutputDebugString. Le seul problme tient la
bufferisation de cette fentre. En effet, les messages envoys par
OutputDebugString ne sont pas affichs immdiatement, ce qui limite
lintrt de cette fonctionnalit.
En outre, cette fonction prend comme paramtre un char * et non pas
une AnsiString comme la plupart des mthodes et fonctions de la
VCL, ce qui rend des cast ncessaires.

Introduction C++ Builder

16

3. Etude de la VCL
3.1 Organisation de la VCL
La VCL (Visual Component Library) livre par Inprise avec C++ Builder ou
Delphi est un ensemble de classes orientes vers le dveloppement rapide
dapplication. Toutes les classes prsentes partagent un anctre commun : la classe
TObject. Elles possdent galement une caractristique particulire : elles ne
peuvent pas possder dinstances statiques : seules les instances dynamiques cres
avec new sont acceptes. Ceci est ncessaire pour assurer la compatibilit avec Delphi
qui ne reconnat que les instances dynamiques. Toutes les classes de la VCL sont
implmentes en Pascal Objet. En fait, la librairie dexcution de C++ Builder est celle
de Delphi, ce qui implique un certain nombre de gymnastiques pour assurer une
dition de liens correcte.

3.2 Les composants


Les composants sont des instances de classes drivant plus ou moins
directement de TComponent. Si leur forme la plus habituelle est celle des composants
que lon dpose dune palette vers une fiche, ils englobent plus gnralement la notion
de brique logicielle rutilisable. Bien que non dclare virtuelle pure1 la classe
TComponent nest pas destine tre instancie. Compulsons sa documentation ;nous
y apprenons que la plupart des mthodes sont protgs, cest dire inaccessibles
lutilisateur, cest une technique courante en Pascal Orient Objet : dfinir le cadre de
travail laide de mthodes virtuelles protges, lesquelles seront dclares publiques
dans les classes drives.
Autre aspect particulirement intressant : la prsence des mthodes AddRef,
Release et QueryInterface ce qui dnote limplmentation de linterface OLE
IUnknown. Ainsi, lorsque lon transformera un composant VCL en composant ActiveX,
la gestion dIUnknown sera directement prise en compte au niveau de TComponent.
De la mme manire, TComponent implmente linterface principale dautomation
IDispatch (mthodes GetIDsOfNames, GetTypeInfo, GetTypeInfoCount et
Invoke). Nous aurons loccasion de revenir plus en dtails sur ces mcanismes
spcifiques OLE dans un prochain chapitre.
Pour finir, notons que les composants que vous crez avec Delphi ou
C++ Builder sont compatibles avec les deux environnements : autrement dit, il est tout
fait possible dutiliser dans C++ Builder un composant cr avec Delphi et
rciproquement.

En effet, la classe TComponent, linstar de toutes les autres classes de la VCL est
implmente en langage Pascal Objet, lequel saccommode assez mal de la notion de classe virtuelle
pure.
1

Introduction C++ Builder

17

3.3 Les Contrles


On appellera Contrle, tout objet instance dune classe drivant de TControl.
Les contrles ont pour caractristique particulire dtre des composants mme de
safficher sur une fiche dans leurs dimensions dexcution.
Par exemple, les boutons (TButton), les tiquettes (TLabel) ou les images sont
des contrles. En revanche, les menus (TMenu) ou les botes de dialogue communes
(TCommonDialog) de Windows qui sont reprsentes par une icne sur les fiches ne
sont pas des contrles.
En terminologie C++ Builder, les contrles se sparent en deux grandes
catgories :

Les contrles fentrs


Les contrles graphiques

3.3.1 Les contrles fentrs


Comme leur nom lindique, les contrles fentrs sont bass sur une fentre
Windows. Ceci leur confre plusieurs caractristiques :

Ils disposent dun handle de fentre. Un handle est un numro unique


allou par le systme toute ressource telles que les fentres, les polices, les
pinceaux ou les brosses.
De ce fait, chaque contrle fentr monopolise une ressource fentre : il ne
pourra y en avoir quun nombre limit prsents dans le systme un
instant donn.

Leur tat visuel est sauvegard par le systme. Lorsquils redeviennent


visibles, leur apparence est restaure automatiquement sans que le
programmeur nait sen soucier.
Consquence ngative : il est plus lent de dessiner dans un contrle fentr
que dans un contrle graphique.

Ils peuvent recevoir la focalisation, cest dire intercepter des vnements


en provenance du clavier
Ils peuvent contenir dautres contrles. Par exemple, les botes de groupe
(TGroupBox) sont des contrles fentrs.
Ils drivent de la classe TWinControl et, la plupart du temps, de la classe
TCustomControl laquelle dispose dune proprit Canvas permettant de
dessiner facilement dans la zone client du contrle. Si vous devez dessiner
dans la zone client dun contrle sans que celui-ci ncessite la focalisation,
alors, il faudra mieux utiliser un contrle graphique moins gourmand en
ressources systme.

Introduction C++ Builder

18

La plupart des lments actifs dans une interface sont des contrles fentrs.
En particulier, les fiches sont des contrles fentrs.

3.3.2 Les contrles graphiques


Contrairement aux contrles fentrs, les contrles graphiques ne sont pas
bass sur une fentre. Ils ne disposent donc pas dun handle de fentre et ne peuvent
recevoir dvnements en provenance du clavier (pas de focalisation). Ils ne peuvent
pas non plus contenir dautres contrles, toutes ces fonctionnalits tant rserves aux
contrles fentrs (voir paragraphe prcdent). Du coup, ils sont moins gourmands en
ressources que les composants fentrs.
En outre, ltat visuel (ou apparence graphique) dun contrle graphique nest
pas gre par le systme :
Il sera plus rapide de dessiner dans un contrle graphique que dans un contrle
fentr car dans ce cas, seul laffichage est concern. Il ny a pas de sauvegarde de
ltat dans la mmoire du systme.
Lorsquun contrle graphique est masqu puis raffich, le systme lui envoie
un vnement WM_PAINT lui indiquant quil doit mettre jour son apparence visuelle.
Le programmeur doit donc intercepter cet vnement (OnPaint) pour redessiner la
zone client de son composant. Pour cela, il dispose de la proprit Canvas qui fournit
une plate-forme de dessin des plus agrables utiliser. Il faut galement savoir que le
gestionnaire dvnement OnPaint est appel par la mthode virtuelle Paint
directement dclenche par lvnement Windows WM_PAINT. De fait, la cration dun
nouveau contrle graphique passe le plus souvent par la redfinition de cette mthode.
La plupart des composants purement orients vers laffichage sont des contrles
graphiques. Citons par exemple TLabel (affichage pur et simple dun texte), TImage
(affichage dun graphique) ou TBevel (affichage dune ligne, dune forme en creux ou
en relief).

3.4 Les botes de dialogue standard de Windows


Les botes de dialogue standard de Windows sont des objets partags par toutes
les applications et permettant deffectuer des oprations de routine telles que la
slection dun nom de fichier, la configuration de limprimante ou le choix dune
couleur. C++ Builder encapsule la plupart dentre elles dans des classes non visuelles
dont les composants sont regroups au sein de la palette Dialogues. Les classes
associes drivent de TCommonDialog, classe servant tablir le lien entre les classes
de C++ Builder et les ressources Windows incluses dans la DLL COMMONDLG.DLL.
Ces composant ne sont pas des contrles : ils napparaissent pas sous leur forme
dfinitive lorsquils sont insrs sur une fiche mais plutt au travers dune icne. Cette
dernire napparat pas lors de lexcution, au contraire de la bote qui elle sera
invoque laide de sa mthode Execute. Licne pose sur la fiche ne sert qu
rserver une ressource Windows et permet de modifier les proprits associes la
bote. La figure suivante illustre la palette dialogues.

Introduction C++ Builder

19

Ouverture
de fichier

Sauvegarde
de fichier

Ouverture
spcialise
dans les
fichiers d'images

Sauvegarde
spcialise
dans les
fichiers d'images

Slection
de couleur

Impression

Slection
de police

Configuration
de l'impression

Recherche
de texte

Recherche/
Remplacement

Figure 3.1 La palette dialogues


Ces botes de dialogue sont toujours excutes en mode modal laide de leur
mthode Execute. Cela signifie quelles monopolisent la souris et le clavier tant que
lutilisateur ne les a pas fermes. Le rsultat de Execute indique linvocateur
laide de quel bouton lutilisateur ferm la bote. Les constantes (aux noms trs
explicites) sont les suivantes :
mrOk

mrCancel

mrNo

mrRetry

mrIgnore

mrYes

mrAbort

Tableau 3.1 Codes de retour des boutons modaux


Insistons sur le fait que lutilisation de ces classes dpend fortement de la DLL
standard de Windows COMMDLG.DLL, leur aspect et leur comportement peuvent donc
varier lgrement dun systme un autre.
Nous ne dtaillerons ici que lutilisation des botes de manipulation de fichiers
et de slection de couleur.

3.4.1 Les botes de dialogue de manipulation de fichiers


Il est particulirement pratique dutiliser les botes de dialogue communes de
Windows pour rcuprer le nom dun fichier ouvrir ou enregistrer car elles
permettent, en particulier, une gestion intgre de la navigation dans larborescence
des rpertoires. Les classes TOpenDialog et TSaveDialog sont trs similaires dans
le sens o elles reposent sur les mmes proprits. Elles ont dailleurs une structure
de donne identique. Voici un exemple de bote douverture :

Introduction C++ Builder

20

Extension par
dfaut des
fichiers
rechercher

Rpertoire
initial
l'ouverture

Icne de la
bote sur
une fiche

Filtre
d'ouverture

Titre de la bote
de dialogue

Figure 3.2 Proprits des dialogues orients fichier


Quelques proprits mritent plus ample discussion :

FileName contient, avant excution, le nom du fichier ouvrir par dfaut,


et au retour de lexcution, le nom rsultat de la recherche
Filter contient la liste des formats de fichiers (spcifis par leurs
extensions) que lapplication est susceptible douvrir. En labsence de toute
indication, *.* est assum. Cette proprit a un format bien particulier.
Cest une chane de caractres obissant au format :
Chane de description|liste des extensions associes|description

Bien que lon puisse trs bien la saisir ainsi, il vaut mieux se reposer sur la
bote spciale qui apparat lorsque lon clique sur

Nom et
description
du filtre

Extensions
associes

Figure 3.3 Bote d'dition de la proprit filter


Les deux botes (ouverture et fermeture) se distinguent essentiellement par les
options qui sont disponibles (prcisment dans la proprit Options). Par exemple, la
bote douverture (TOpenDialog) peut prsenter une case cocher proposant douvrir
un fichier en lecture seulement.
Il existe deux versions spcialises dans louverture et la sauvegarde de fichiers
image qui ne posent pas de problme spcifique.

Introduction C++ Builder

21

3.4.2 La bote de slection de couleurs


La figure suivante montre les proprits les plus intressantes de la bote de
slection de couleurs de C++ Builder (classe TColorDialog).
Les options sont particulirement intressantes car elles conditionnent toute
lexcution, et en particulier la possibilit doffrir lutilisateur la potentialit de crer
lui-mme ses propres couleurs.

Couleur initiale
puis slection de
l'utilisateur

Icne de la
bote sur
une fiche

Dfinitions des
couleurs
utilisateur

Figure 3.4 Proprits de la bote de choix de couleur


Une fois nest pas coutume, intressons nous aux options internes de la bote :
cdFullOpen : ds louverture, la bote est en mode complet, cest dire avec la
possibilit de dfinir les couleurs utilisateurs et de choisir parmi
lintgralit du nuancier. Sinon, la bote souvre en mode standard. La
figure suivante montre les deux modes de fonctionnement de la bote.

(a) : Mode standard

(a) : Mode complet

Figure 3.5 Les deux modes de fonctionnement de la bote de slection de


couleurs

Introduction C++ Builder

22

cdPreventFullOpen : si cette option est active, alors il est impossible


dactiver le mode complet. Le bouton Dfinir les couleurs personnalises
du mode standard est cach
cdShowHelp : si cette option est active, alors un bouton permettant dactiver
un texte daide est prsent
cdSolidColor et cdAnyColor sont deux options quil est utile dactiver si la
carte graphique de lutilisateur final ne supporte pas le mode true colors.
Lorsque cdSolidColor est true, alors la slection dune couleur obtenue
par tramage renvoie vers la vraie couleur la plus proche. Si cdAnyColor est
active, alors il est possible de crer de nouvelles couleurs par tramage.

3.4.3 La bote de slection de Fonte


Cette bote, trs simple, permet de slectionner une police parmi celles
installes dans Windows. Toutes les informations slectionnes sont regroupes dans
la proprit Font qui elle mme peut se dplier pour donner des informations aussi
diverses que : le nom de la police, le jeu de caractres employ, le crnage, le style, la
couleur ou, tout simplement, la hauteur des caractres.
La figure suivante illustre lensemble des proprits disponibles :
Proprit Font dploye
au maximum

Nom de la police

Icne de la bote de
slection de police

Taille des caractres


Enrichissements de style

Figure 3.6 Proprits de la bote de slection de police


Les options de la bote elle mme permettent de limiter lutilisateur dans ces
choix (par exemple, ne lautoriser qu choisir des fontes non proportionnelles) ou de
contrler laspect visuel de la bote.

3.4.4 Les botes de Recherche et Recherche / Remplacement


Ce sont les botes les plus compliques utiliser. Tout dabord, ce sont les seules
pour lesquelles le comportement nest pas modal et binaire :
Introduction C++ Builder

23

En effet, elles restent ouvertes tant que lutilisateur appuie sur le bouton
Suivant . En outre elles nont pas de bouton Ok , le seul moyen permettant de les
fermer consiste utiliser le bouton Annuler .
En outre, elles neffectuent pas directement la recherche ! Elles ne permettent
que de saisir le texte rechercher (ou le texte de remplacement) et de slectionner des
options. Le corps de la recherche reste la charge du programmeur.
Les options de ces botes de dialogue sont aises comprendre, elles
conditionnent laffichage des diverses possibilits et le rsultat de la slection de
lutilisateur.
Le rsultat de la bote comprend, entre autres : la recherche de mots complets
(frWholeWord), la prise en compte de la casse (frMatchCase), le sens et la porte de
la recherche (frDown, frHideUpDown, etc.) .
Par dfaut, les botes saffichent avec ltendue totale de leurs possibilits.
Toutefois, lutilisateur peut les limiter en activant des options dont le nom comprend
Hide ou Disable, par exemple frDisableMatchCase dsactive la case permettant
relative la casse des mots recherchs.
Comme la recherche elle mme, la prise en compte des options de recherche est
entirement la charge du programmeur. On ne rptera jamais assez que ces botes
ne sont que des outils de saisie des options !
La bote de recherche simple fournit un vnement nomm OnFind notifiant au
programmeur lappui sur la touche Suivant de la bote. La bote de remplacement
lui ajoute un vnement nomm OnReplace.
Un exemple dutilisation consiste utiliser ces vnements en conjonction avec
la mthode FindText dun composant TRichEdit.

3.4.5 Exercice sur les botes de dialogue communes ( )


Enonc
Nous vous proposons de tester lutilisation des diffrentes botes de dialogue sur
le texte contenu dans un composant TRichEdit. Ce composant est trs proche de
TMemo dans le sens o il reprend la plupart de ses fonctionnalits en ajoutant celle de
lire un fichier .rtf et de le formater correctement. Malheureusement, il ne propose
pas ni proprit ni mthode permettant daccder la mise en forme de chaque
caractre. En revanche, il est possible de formater globalement le texte.
Les fonctionnalits suivantes devront tre accessibles partir dun menu :

Charger le texte du mmo (mthode LoadFromFile de la proprit Lines)


partir dun fichier slectionn laide dune bote commune douverture.
Les extensions possibles en lecture sont :

.obc (Fichier de type OBC en fait du texte !) par dfaut

Introduction C++ Builder

24

.txt (Fichier de type texte)


.cpp, .h et .hpp (Fichiers de type C++ Builder)

Sauvegarder le texte du mmo (mthode SaveToFile de la proprit


Lines) dans un fichier slectionn laide dune bote commune de
sauvegarde. Seule lextension .obc est disponible la sauvegarde
Manipuler lapparence visuelle du texte (proprit Font du mmo)

Changement de couleur (bote de slection de couleurs)


Changement de police (bote de slection de fonte)

Effectuer des recherches et des oprations de recherche / remplacement


grce aux botes idoines.
Quitter lapplication !

Rien dans cet exercice nest compliqu ! il y a juste beaucoup de code crire
Pour aller plus loin dans lexercice (

) :

Proposer de sauvegarder le texte sil a t modifi par des oprations de


recherche / remplacement ou par une saisie utilisateur avant den charger un nouveau
ou de quitter lapplication (lvnement OnCloseQuery de la fiche est considrer).
Solution partielle
La figure suivante illustre laspect de linterface construire :
Menu principal permettant
d'appeler les botes

Diffrentes botes de dialogue


permettant de modifier le texte

Composant TRichEdit
sur lequel appliquer les
modifications

Figure 3.7 Interface de lexercice sur les botes de dialogue

3.5 Les botes combo


Les botes combo permettent de rassembler en un seul composant les
fonctionnalits dune zone de saisie et dune bote de liste moyennant quelques
limitations :

Introduction C++ Builder

25

La zone ddition ne peut pas avoir de masque de saisie


La bote de liste est slection simple

Du coup, les proprits sont hybrides de celles de la bote de liste et de la zone


ddition, pour citer les plus importantes :
Items : liste des lments prsents dans la liste droulante
ItemIndex : numro de llment slectionn. Le texte de llment slectionn
est accessible via : Items->Strings[ItemIndex] ou plus simplement via
Text car le texte de llment slectionn est recopi dans la zone ddition
Text : texte slectionn dans la liste ou saisi dans la zone ddition
Sorted : linstar des botes de liste normales , il est possible de stipuler
que les diffrents lments de la liste soient tris dans lordre
lexicographique croissant.
Style : proprit dterminant le style de la bote combo

csSimple : la liste est visible en permanence


csDropDown : il sagit de la prsentation habituelle dune bote combo
o laffichage de la liste sobtient par activation dun bouton plac
droite de la zone ddition.
csDropDownList : identique la prcdente la diffrence que lon ne
peut slectionner quun lment dj prsent dans la liste. Cela permet
de crer une liste fixe que lon fait drouler laide du bouton.
csOwnerDrawFixed : laffichage de chaque cellule de la liste est sous la
responsabilit du programmeur qui doit fournir une rponse
lvnement OnDrawItem appel pour dessiner chacun des lments de
la liste. Ceci permet, par exemple, de crer une liste de couleurs ou de
styles de traits (voir exercice). Dans ce cas, les diffrents lments de la
liste sont tous de la mme hauteur, laquelle est fixe par la proprit
ItemHeight.
csOwnerDrawVariable : identique la prcdente la diffrence que
chaque lment peut avoir une hauteur diffrente. Lvnement
OnMeasureItem est lanc juste avant OnDrawItem afin de fixer la
hauteur de llment dessiner.

La possibilit offerte au programmeur de contrler totalement laffichage de


chacun des lments de la liste est dautant plus intressant que cela nempche pas
pour autant la saisie de nouveaux lments dans la zone de saisie. Cela permet, par
exemple dafficher un petit en regard des derniers lments saisis.
Il est important de noter que la saisie dun nouvel lment nentrane pas pour
autant son inclusion dans la liste des possibilits. Cette dernire est laisse la
Introduction C++ Builder

26

responsabilit du programmeur. Une fois de plus, cela savre particulirement


judicieux car lon a alors la possibilit de filtrer les inclusions.
A la conception, il est possible de fixer le texte initial dune bote combo grce
sa proprit Text mais pas en spcifiant un numro dindex dans la liste. Ceci est
seulement ralisable par programmation, par exemple dans lvnement OnCreate de
la liste.

3.5.1 Exercice rsolu n1 ( )


Enonc :
On dsire raliser une bote combo qui naccepte dinclure dans sa liste que des
nombres compris entre 0 et une limite indique dans une zone ddition. Raliser cette
interface sachant que la validation de la valeur se fait par lappui sur un bouton.
Solution partielle :
Puisque la validation de la saisie se fait grce un bouton, nous allons nous
concentrer sur le code de lvnement OnClick associ. La limite de saisie est situe
dans un attribut de la classe fiche nomm limiteSaisie.
void __fastcall TFSaisie::bnValideClick(TObject *Sender)
{
// Tout d'abord, on essaye de transformer la valeur chane en nombre entier
try
{
int valeur=cbSaisie->Text.ToInt();
// Ouf ! c'est un entier ! S'il est dans la limite on l'ajoute a la liste
if ((valeur > 0) && (valeur < valeurLimite))
{
cbSaisie->Items->Add(cbSaisie->Text);
meTrace->Lines->Add("La valeur "+cbSaisie->Text+" est ajoute");
}
else
meTrace->Lines->Add("Valeur "+cbSaisie->Text+" en dehors des limites");
}
// Test de l'erreur de conversion
// le texte saisi est effac aprs envoi d'un message
catch (EConvertError &e)
{
ShowMessage("Saisie Incorrecte : "+e.Message);
cbSaisie->Text="";
}
}

Programme 3.1 Ajout dune ligne saisie dans une bote combo
Commentaires :

Notez lutilisation de lexception EConvertError qui est lance chaque


conversion rate. La proprit Message contient un message derreur utile
des fins de diagnostique.

Introduction C++ Builder

27

La classe AnsiString contient des mthodes ToInt et ToDouble que lon


peut utiliser en lieu et place des fonctions de conversion StrToInt, et
StrToFloat.

Pour continuer lexercice :


Utiliser lvnement OnChange dune zone ddition coupl une gestion
dexception pour modifier la valeur limite dinclusion.
La solution se trouve dans lunit Usaisie du rpertoire Combos du
Power Bear Pack

3.5.2 Exercice rsolu n2 (

Enonc
On dsire crer une bote combo permettant de slectionner un style de trait
pour un dessin. En outre, chaque trait est dessin au milieu de son lment, lequel est
de taille fixe. On vrifiera pralablement dans laide que 6 styles sont disponibles : ils
correspondent des constantes numriques schelonnant de 0 5 (suivre
TPen
Proprit Style)

Solution partielle
Pour rsoudre cet exercice il convient de se rendre compte que la bote combo
doit contenir autant dlments que lon doit en tracer. Cela peut paratre une
vidence mais il faut tout de mme y penser. Aussi, lors de la phase de conception de
linterface, vous noublierez pas de poser 6 lments dans la proprit Items de votre
bote combo (par exemple, les nombres de 0 5).
Ensuite, il suffit de rpondre lvnement OnDrawItem comme le montre le
code suivant, non sans avoir au pralable fix le style de la bote combo
csOwnerDrawFixed !
void __fastcall TFComboTraits::cbStyleDrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
// Rcupration d'un pointeur sur la bote combo
TComboBox *cb=dynamic_cast<TComboBox *>(Control);
// On convertit en TPenStyle l'index pass en argument
TPenStyle leStyle=static_cast<TPenStyle>(Index);
// Rcupration d'un pointeur sur le canevas de dessin de la combo
TCanvas
*cv=cb->Canvas;
// Hauteur du trac
int
vert=(Rect.Top+Rect.Bottom) >> 1;
// Remplissage de toute la zone de trac avec un carr blanc
cv->Brush->Style=bsSolid;
cv->Brush->Color=clWhite;
cv->FillRect(Rect);
// Affichage du motif de dessin
cv->Pen->Color=clBlack;
cv->Pen->Style=leStyle;
cv->MoveTo(Rect.Left,vert);

Introduction C++ Builder

28

cv->LineTo(Rect.Right,vert);
}

Programme 3.2 Affichage de styles de traits dans une bote combo


Commentaires :
Etudions les paramtres du gestionnaire OnDrawItem :

TWinControl Control : bote combo ayant mis le message. Comme nous


voulons travailler le plus gnrique possible, nous allons transformer ce
paramtre en pointeur sur une bote combo. Le code le plus simple serait :
TComboBox *cb=(TComboBox *)Control

Hors, en bon programmeur objet, vous savez trs bien quil est trs
dangereux deffectuer des conversions de promotion (aussi appeles
downcast). Utiliser loprateur C++ dynamic_cast permet de scuriser
lopration.

int Index : numro de llment dessiner. Dans notre cas, nous nous
dpchons de le convertir en TPenStyle (lutilisation de static_cast vous
montre un second oprateur de conversion du C++) afin de lutiliser pour
positionner loption Style de loutil Pen du canevas de la bote combo.
TRect &Rect : zone rectangulaire o doit seffectuer laffichage. Celui-ci est
support par le canevas (contexte daffichage) de la bote combo, lequel est
fourni par la proprit Canvas de TComboBox. La zone rectangulaire est
caractris par les quatre coordonnes Top, Bottom, Left et Right qui se
passent de commentaire.
Le dernier paramtre indique si lon est vraiment sur quil faille redessiner.
Et contrairement au proverbe, dans le doute : redessine !

Vous noterez que lon a pris soin deffacer la zone de travail en la recouvrant
dun rectangle blanc (grce la mthode FillRect). Ceci permet de sassurer que lon
dmarre bien sur une surface vierge. En effet, lorsque vous faites dfiler la liste, les
diffrents lments doivent safficher au mme endroit ce qui occasionnerait des
collisions nfastes
Solution complte :
La solution se trouve dans lunit UComboTraits du rpertoire Combos du
Power Bear Pack

3.5.3 Exercice rsolu n3 (

Enonc
On dsire crer une bote combo permettant de slectionner lpaisseur du trait
pour un dessin. Il est galement stipul que la hauteur de chaque lment doit tre de
Introduction C++ Builder

29

5 fois lpaisseur du trait qui est dessin au milieu de son lment. Les paisseurs
tudies devront voluer de 0 10 compris. Que peut-on dire de lpaisseur 0 ?
Solution partielle :
Cet exercice se rsout facilement ds lors que lon a compris le prcdent. Il
suffit en effet de rajouter un gestionnaire lvnement OnMeasureItem afin de
calculer la hauteur de chaque lment, puis un gestionnaire OnDrawItem (trs peu
diffrent du prcdent) pour dessiner llment.
Notez au passage que lon utilise le fait que la coordonne verticale dun trait
est celle de son axe central.
Dans un soucis de gnricit, nous traons des traits dont lpaisseur
correspond la valeur entire du texte situ dans chaque lment de la bote combo.
void __fastcall TFComboTraits::cbEpaisseurMeasureItem(TWinControl *Control,
int Index, int &Height)
{
// Conversion du pointeur vers TComboBox*
TComboBox *cb=dynamic_cast<TComboBox *>(Control);
// Calcul de la hauteur : 5 fois la valeur de l'lment
Height=5*(cb->Items->Strings[Index].ToInt());
}

Programme 3.3 Lvnement OnMeasureItem de calcul de hauteur dun


lment de bote combo
Commentaire
Ici, le seul paramtre exotique est Height qui permet de renvoyer la hauteur
de llment dessiner.
Le trac du trait lui mme diffre peu de celui de lexercice prcdent et est
illustr par le code suivant.
void __fastcall TFComboTraits::cbEpaisseurDrawItem(TWinControl *Control,
int Index, TRect &Rect, TOwnerDrawState State)
{
// Conversion du pointeur vers TComboBox *
TComboBox *cb=dynamic_cast<TComboBox *>(Control);
// On rcupre le canevas (contexte d'affichage)
TCanvas
*cv=cb->Canvas;
// Coordonne verticale du trait
int
vert=(Rect.Top+Rect.Bottom) >> 1;
// Effacement de la zone par recouvrement avec un rectangle blanc
cv->Brush->Style=bsSolid;
cv->Brush->Color=clWhite;
cv->FillRect(Rect);
// Trac du trait avec la bonne paisseur
cv->Pen->Style=psSolid;
cv->Pen->Width=(cb->Items->Strings[Index].ToInt());
cv->MoveTo(Rect.Left,vert);
cv->LineTo(Rect.Right,vert);

Introduction C++ Builder

30

Programme 3.4 trac dun trait dpaisseur variable dans une bote combo
Solution complte :
La solution se trouve dans lunit UComboTraits du rpertoire Combos du
Power Bear Pack

3.5.4 Exercice n4 (

Etendre la liste de lexercice n1 de manire ce que les 4 derniers lments


entrs soient prcds dun point noir.
On utilisera la mthode TextOut de TCanvas pour afficher un texte.

3.6 Les menus


Il y a grosso modo deux grandes catgories de menus : le menu principal dune
application, qui saffiche en haut de la fentre principale et qui varie finalement trs
peu au cours de lexcution et les menus surgissants, activs par le bouton droit de la
souris ou la touche spciale du clavier de Windows qui eux dpendent trs fortement
du contexte. Ils partagent nanmoins de trs nombreuses caractristiques.

3.6.1 Mise en place dun menu principal

Figure 3.8 Mise en place du menu principal


Tout commence par linsertion dun composant non visuel TMainMenu sur la
fiche correspondant la fentre principale de votre application. Ensuite, il suffit de
double cliquer sur licne de celui-ci ou dactiver Concepteur de menus dans son
menu contextuel pour entrer dans lditeur de menu (commun au menu principal et
aux menus surgissants).
Par dfinition, le menu principal se loge toujours en haut de la fentre
principal, au dessus des composants possdant lalignement alTop sils sont prsents
(des barres doutils, par exemple). En mode conception, il napparat quaprs la
premire activation du concepteur de menus.
La proprit principale de chaque composant menu est Items, proprit
regroupant lensemble des lments prsents dans le menu, chaque lment tant lui
mme un objet de la classe TMenuItem.
Introduction C++ Builder

31

3.6.2 Lditeur de menus


La figure suivante illustre le fonctionnement de lditeur de menus. Celui ci
permet de construire un menu de faon trs intuitive. Comme le montre linspecteur
dobjets, tout lment de menu est dot dun identificateur particulier. Ceci a pour
consquence positive quil est trs facile daccder chacun dentre eux et comme
aspect malheureux la saturation de lespace de nommage des identificateurs lorsque
les menus regroupent de nombreux lments. Notons toutefois quil est possible, et
cest un cas unique ! de laisser la proprit Name en blanc pour un lment auquel lon
naccdera pas programmatiquement.
Icne du composant
menu principal
Emplacement du
prochain lment
horizontal

Raccourci clavier
associ au menu

Emplacement du prochain
lment vertical

Figure 3.9 Le concepteur (ou diteur) de menus


Quelques petites indications simposent :

Comme pour les boutons ou les labels de tout poil, il est possible dutiliser le
caractre & pour signaler la lettre active dun lment de menu. Si llment
en question fait partie de la barre horizontale du menu principal, la
combinaison Alt-lettre-active permettra daccder directement au
menu.
Lorsque vous saisissez le Caption dun lment, le concepteur le valide et
en ajoute automatiquement un nouveau du mme type. Il ne faut pas
sinquiter de la prsence des ces lments fantmes prsents en mode
conception : ils napparatront pas lors de lexcution.
Lorsque lon dsire ajouter un sparateur dans un menu vertical ,il suffit
de taper le caractre tiret dans son Caption.
Griser un menu sobtient en basculant sa proprit Enabled false.

Introduction C++ Builder

32

Positionner false la proprit Visible dun menu permet de le rendre


invisible et donc totalement inactif. Nous verrons que cette proprit est
particulirement utile car la structure dun menu est fige aprs la
conception : il nest pas possible dajouter ou de supprimer un lment dans
un menu lors de lexcution. Nous pourrons toutefois utiliser la proprit
Visible pour simuler un ajout ou une suppression.

3.6.2.1 Lutilisation de modles de menus


C++ Builder propose dutiliser des modles de menus dj prts. Vous pouvez y
accder par le menu contextuel attach au bouton droit de la souris dans le concepteur
de menus. La figure suivante illustre cette possibilit :

Figure 3.10 Le menu contextuel du concepteur de menus ( rpter trs vite


3 fois )

Les modles de menus sont trs efficaces car ils reprennent des menus
canoniques et trs complets. Il vous suffira alors dajouter les fonctionnalits qui vous
manquent et de supprimer (ou rendre invisibles) celles que vous ne souhaitez par voir
apparatre. La figure suivante montre la liste des modles de menus disponibles par
dfaut :

Figure 3.11 Les modles de menus

Introduction C++ Builder

33

Comme vous pouvez le constater, cette liste contient mme un menu MDI
complet prt lemploi ! La figure suivante montre un menu daide directement
obtenu aprs insertion du modle Aide.

Figure 3.12 Aprs insertion du menu daide par dfaut


3.6.2.2 Les sous menus
Il est trs simple de crer un sous menu attach un lment quelconque : il
suffit dactiver loption correspondante dans le menu contextuel (ou dactiver le
raccourci Ctrl-D).
Notez que, dans linspecteur dobjets, rien ne permet de diffrencier un item
auquel est attach un sous menu dun autre, ce qui peut paratre surprenant car ils
ont un comportement tout fait diffrent et sont reprsents avec une petite flche
vers la droite. La figure suivante montre la cration dun sous menu.

Figure 3.13 Cration dun sous menu


3.6.2.3 Les menus comportement radio
Il est possible de confrer certains des lments dun menu un comportement
rappelant celui des boutons radio dans le sens o seul lun dentre eux sera prcd
dun rond noir. Cela permet, par exemple, daffecter des options.
Pour transformer un ensemble dlments en lments radio, il faut commencer
par positionner leur proprit RadioItem true et leur affecter tous une mme
valeur de proprit GroupIndex, laquelle doit tre obligatoirement suprieure 7
afin dviter des conflits avec les valeurs prdfinies de groupes dlments de
Windows. La proprit Checked permet de spcifier lequel de ces boutons sera activ
par dfaut. Attention ! contrairement aux boutons radio, cliquer sur un lment ne
lactive pas immdiatement : ceci doit tre fait dans le gestionnaire de lvnement
OnClick.

Introduction C++ Builder

34

3.6.3 Lutilisation des menus


Les lments de menu nont quun seul vnement : OnClick auquel lon affecte
une mthode rpondant lvnement activation du menu . Il est ncessaire
daffecter la proprit Checked dun lment radio dans le gestionnaire si vous voulez
dplacer la marque radio dudit lment.

3.6.4 Un exemple de modification par programmation : la liste des


derniers fichiers ouverts
Comme nous lexpliquions quelques lignes auparavant, la structure (nombre des
lments de chaque partie de menu) est fige lors de la conception : la proprit Items
est en lecture seulement. Il nest donc pas possible dajouter ou de retirer un lment
du menu en cours dexcution. Heureusement, il est possible de jouer sur la proprit
Visible de chaque lment.
Nous allons profiter de cette aubaine pour construire une liste des 4 derniers
fichiers ouverts ayant les proprits suivantes :

Lorsque la liste nest pas vide, elle apparat en bas du menu fichier, juste
avant llment Quitter, divise du reste des lments par des sparateurs
Si la liste est vide, elle est totalement invisible
Llment le plus ancien est remplac par le nouveau lorsque la liste est
pleine

Afin dobtenir ce que nous dsirons, il est possible dutiliser la squence


dinstructions :
1. Nous commenons par rserver les emplacements ncessaires comme le
montre la figure suivante :

Quatre emplacements
vides et un sparateur
sont rservs

Figure 3.14 Rservation des emplacements de menu pour la liste des derniers
fichiers ouverts
2. Dans un second temps, nous basculons la proprit Visible des 4
emplacements et dun des sparateurs false. Attention ! si vous ne
spcifiez pas de Caption pour un lment, par dfaut son nom restera en
Introduction C++ Builder

35

blanc, effet dont nous ne voulons pas. Aussi, soit vous donnez un Caption
qui sera de toute faon remplac par la bonne valeur au moment de
laffichage, soit vous fournissez un nom au composant.
3. Afin de pouvoir accder facilement aux quatre emplacements, nous ajoutons
dans les dclarations prives de la classe Fiche :

un tableau de 4 TMenuItem qui sera affect aux adresses des 4 lments


dans le constructeur
une variable entire indiquant le nombre dlments prsents dans la
liste

4. Il ne reste plus qu rendre visibles les lments et leur affecter le bon


Caption. Lexemple qui suit remplit tout simplement cette liste grce un
bouton et une zone ddition.

// Variables affectes individuellement aux lments de menu


// destins la liste des derniers fichiers ouverts
TMenuItem *MenuFich1;
TMenuItem *MenuFich2;
TMenuItem *MenuFich3;
TMenuItem *MenuFich4;
private:
// Dclarations de l'utilisateur
// Dclaration d'une constante indiquant le nombre d'lments de la
liste
enum {NB_FICHIERS=4};
// Tableau permettant de manipuler facilement les lments de menu
// destins la liste des derniers fichiers ouverts
TMenuItem *MenuFichiers[NB_FICHIERS];
// Variable comptant le nombre d'lments prsents
int
nbFichiers;

Programme 3.5 Dclarations relatives la mise en place de la liste des


derniers fichiers ouverts
__fastcall TFPrinci::TFPrinci(TComponent* Owner)
: TForm(Owner)
{
// Remplissage (bourrin) du tableau des lments
MenuFichiers[0]=MenuFich1;
MenuFichiers[1]=MenuFich2;
MenuFichiers[2]=MenuFich3;
MenuFichiers[3]=MenuFich4;
nbFichiers=0;
}
//-------------------------------------------------------------------------void __fastcall TFPrinci::bnElementClick(TObject *Sender)
{
// Affichage du sparateur
N2->Visible=true;
// Mise en place du Caption et affichage de l'lment
MenuFichiers[nbFichiers]->Caption=editElement->Text;
MenuFichiers[nbFichiers]->Visible=true;
// Mise en place du cyclage
nbFichiers++;

Introduction C++ Builder

36

nbFichiers%=NB_FICHIERS;
}

Programme 3.6 Code dimplmentation du remplissage de la liste


Comme souvent, ce code rpte plusieurs fois la mme opration (mettre la
proprit Visible des lments true) car cela coterait aussi cher deffectuer le
test de visibilit.

3.6.5 Les menus surgissants


Les menus surgissants (popup menus) sont en tout point semblables (du moins
pour ce qui est de leur conception) au menu principal dapplication. La seule
diffrence rside dans leur activation qui est contrle par deux proprits.
AutoPopup est une proprit de TPopupMenu qui indique si ce menu est
activable par un clic sur le bouton droit de la souris (ou lenfoncement de la
touche idoine du clavier) ou sil est uniquement accessible par
programmation (mthode Popup). Cette proprit est par dfaut true, ce
qui correspond bien lutilisation la plus frquente de ces menus.
PopupMenu est une proprit dfinie par tous les contrles et qui indique
lidentificateur du menu surgissant actif dans ce contrle. Ainsi, il est
possible de spcifier un menu surgissant par contrle. Si cette proprit
nest pas renseigne, alors le menu surgissant est celui du parent.

3.7 Les botes droulantes


Le fonctionnement des ascenseurs est quelque peu trange en C++ Builder.
Nous allons donner un aperu des possibilits quils offrent.

3.7.1 Gnralits
Les botes droulantes TScrollBox (sur la palette Supplment) permettent de
faire dfiler des composants laide dascenseurs. Pour bien comprendre leur
fonctionnement, il nous faut dfinir un peu de vocabulaire laide de la figure
suivante :
Width

Etendue
Virtuelle

VertScrollBar->Range

Height

Partie visible

HorzScrollBar->Range

Figure 3.15 Partie visible et tendue virtuelle dun TScrollBox


Introduction C++ Builder

37

La partie visible dun composant TScrollBox est spcifie, comme


laccoutume par ses proprits Width et Height. Le nouveau concept est celui
dtendue virtuelle. En effet, le dfilement sert afficher les parties caches de
ltendue virtuelle du composant. La largeur et la hauteur de cette dernire sont
respectivement indiques par les proprits Range des ascenseurs horizontaux et
verticaux lesquels sont stocks dans les proprits HorzScrollBar et
VertScrollBar de la TScrollBox.
Ltendue virtuelle peut varier au cours de la vie de lapplication. Lorsquelle
devient infrieure ou gale la partie visible, les ascenseurs sont cachs.
Autre chose importante savoir : modifier la position des ascenseurs ne gnre
pas dvnement particulier. Vous ne pouvez donc pas savoir en temps rels si leur
position a chang. En consquence, vous devez prvoir laffichage complet de la zone
virtuelle.

3.7.2 Que peut on mettre dans une TScrollBox ?


Potentiellement, il est possible dintgrer dans une TScrollBox nimporte quel
type de contrle, ce qui peut savrer pratique si lon doit crer une interface
graphique la main en fonction dun fichier de configuration.
Supposons par exemple, que vous criviez une application dont certaines
options boolennes sont passes dans un fichier. Vous souhaitez associer une case
cocher chacune de ces options. Comme vous ne connaissez pas leur nombre
lavance, vous tes obligs de les construire la main lors de lexcution de votre
programme.
Afin de ne pas surdimensionner votre fentre, il est possible de les placer dans
une TScrollBox. Si vous activez la proprit AutoScroll, lespace virtuel sera
tendu automatiquement lorsque vous ajouterez des contrles dans votre bote
droulante. De toute faon, il vous est toujours possible de modifier les Range votre
guise.
Le plus souvent, les TScrollBox sont associes un contrle graphique ou un
contrle fentr unique dans le but dafficher un document de grande taille. Cest ce
que lon appelle une vue.

3.7.3 Exercice rsolu : affichage dun dessin avec facteur de zoom


)
(

Lexemple que nous allons traiter utilise un TImage plac dans une
TScrollBox pour afficher un dessin de taille variable en fonction dun certain facteur
de zoom. Afin de ne pas compliquer inutilement lexercice, nous afficherons une suite
de 25 cercles concentriques.
Le facteur de zoom (variant entre 1 et 20) est indiqu par un composant
TTrackBar lequel modlise un curseur plac le long dune rgle. Les proprits les
plus intressantes sont :

Introduction C++ Builder

38

Position

Valeur du curseur

Min

Valeur minimale du curseur, associe la position tout gauche

Max

Valeur maximale du curseur, associe la position tout droite

Frequency

Nombre dunits sparant deux graduations sur la rgle


Tableau 3.2 Quelques proprits du contrle TTrackBar

On dmarre avec une taille dimage de 50x50 correspondant au facteur de


zoom=1. A chaque fois que le facteur de zoom change, vous modifierez la taille du
TImage, (simplement en multipliant la taille de base par le facteur de zoom),
modifierez ltendue virtuelle de la TScrollBox si cela est ncessaire et mettrez
jour laffichage des cercles concentriques.
Pour bien excuter cet exercice, il est prfrable dinstancier manuellement le
composant TImage daffichage du dessin. En effet, lorsque lon modifie les proprits
Width et Height dun TImage, cela na pas de rpercussion directe sur la taille de la
zone cliente (ClipRect), laquelle est dans une proprit en lecture seulement. En
effet, cela reviendrait rallouer la zone de tampon mmoire associe la TImage.
Linterface crer ressemble :

Composant
TScrollBox

Composant
TMemo de trace

Composant TTrackBar
responsable des changements
de facteur de zoom

Figure 3.16 Utilisation dune TScrollBox pour le problme du dessin


Zoomer
Vous pouvez suivre les instructions suivantes :

Dtruire le composant TImage en place (delete)


Crer un composant TImage, le seul paramtre passer au constructeur est
le propritaire, cest dire la TScrollBox.
Modifier les proprits fondamentales de la TImage :

Introduction C++ Builder

39

Parent : identificateur de la TScrollBox, gre laxe Z


Width et Height : taille de limage afficher
Top et Left : positionns zro

Afficher le dessin

Cette technique, au demeurant fort simple souffre dun handicap colossal : il


faut allouer un TImage capable de contenir tout le dessin ce qui demande des
ressources mmoire consquentes. Aussi, pour des documents de grande taille, il
faudra recourir une autre technique qui elle nutilise plus des TScrollBox mais des
TScrollBar.
Pour aller plus loin dans lexercice (

) :

Centrez limage dans la TScrollBox si elle est plus petite que la taille
statique de la TScrollBox,
Ajoutez un composant zone ddition affichant en permanence le facteur de
zoom et permettant de le saisir. On effectuera tous les contrles derreur
ncessaires (valeurs en dehors de [Min, Max], saisie de valeur non
numrique, etc.)
Essayez datteindre les limites dallocation de C++ Builder et fixez la valeur
suprieure du zoom en consquence.

3.8 Les ascenseurs simples


3.8.1 Gnralits
Les ascenseurs simples sont encapsuls dans le composant TScrollBar
(palette standard). Une valeur numrique indiquant la position de leur curseur au
sein de leur tendue leur est associe :
Leurs proprits fondamentales sont les suivantes :
Min

Valeur minimale de ltendue du curseur

Max

Valeur maximale de ltendue du curseur

Position

Valeur courante du curseur

Kind

Spcifie si lascenseur est horizontal (valeur sbHorizontal) ou


vertical (sbVertical)

SmallChange

Valeur dincrmentation du curseur lorsque lutilisateur utilise les


flches.

LargeChange

Valeur dincrmentation du curseur lorsque lutilisateur clique dans


la barre dascenseur ou utilise PgUp ou PgDown

Introduction C++ Builder

40

Tableau 3.3 Proprits fondamentales des ascenceurs (TScrollBar)


Contrairement aux ascenseurs des TScrollBox, les TScrollBars gnrent un
vnements lorsque lon modifie leur valeur, il sagit de OnChange.

3.8.2 Exercice (

Enonc :
Reprendre lexercice prcdent mais en ralisant laffichage dans un TImage
fixe et en faisant dfiler limage avec des ascenseurs simples.
Solution partielle :
Il est relativement simple dadapter le code de lexercice prcdent celui-ci.
Aussi, je vous conseille de dupliquer tout le code du prcdent projet dans un nouveau
rpertoire et de modifier lapplication existante.
Premire chose : supprimer la TScrollBox et ajouter :

Un composant TImage que lon aura pris soin de poser sur un TPanel
Deux composants TScrollBar, un horizontal et un vertical situs de part et
dautre du TImage
Linterface obtenue est montre par la figure suivante :

TScrollBar
TImage

TScrollBar

Figure 3.17 Utilisation de TScrollBar

Introduction C++ Builder

41

La gestion du zoom et du dfilement est totalement diffrente dans le sens o,


dun ct, on construit compltement limage un document et les barres de dfilement
ne font que faire glisser une loupe dessus alors que de lautre ct, cest le
programmeur qui gre le scroll en rcuprant la position des barres de dfilement
pour construire limage de la partie visible dun document.
Cette solution est un peu plus complique mettre en uvre mais beaucoup
plus souple au sens o elle autorise des documents dune taille de visualisation
virtuellement illimite.
En effet, dans le cas prcdent, on utilise un composant TImage dans lequel
toute la scne est dessine. Aussi, la taille de se composant croit elle avec le facteur de
Zoom. Lorsque lon utilise les barres de dfilement simples, la taille du composant
TImage ne varie pas.

3.9 Les barres doutils de C++ Builder


La cration dune telle barre doutils se fait en utilisant la classe TToolBar. Par
dfaut, un objet de classe TToolBar se place en haut de sa fentre parent. Cest un
objet conteneur destin recevoir divers objets fils parmi lesquels on recense :

Nimporte quel type de contrle


Des sparateurs
Des boutons gadgets

Ces deux dernires classes tant plus spcifiquement lies aux barres de
contrles ou autres palettes flottantes.

3.9.1 Insertion de contrles standard dans une barre doutils


Si les contrles nexistent pas encore, il suffit de slectionner la barre de
contrle avant de les placer, il sinsreront directement leur place. On remarque,
que, par dfaut, les contrles sont colls les uns aux autres constituant des groupes.
Heureusement, il est possible de laisse de lespace en insrant des sparateurs avec
une commande de menu rapide (bouton de droite). Ceux-ci sont aisment
repositionnables et redimensionnables. La prsence de sparateurs constitue des
groupes de contrles.
En revanche, si les contrles existent dj, il faut les dplacer par des
oprations Couper / Coller, le collage devant seffectuer barre doutils slectionne.

3.9.2 Les boutons gadgets


Les boutons gadgets ressemblent sy mprendre aux anciens turbo boutons de
Delphi 2. Toutefois, il ne faut pas sy tromper, ce ne sont pas des contrles car ils ne
reposent pas sur une fentre. Ils ne peuvent donc pas recevoir et mettre des messages
Windows de leur propre chef mais doivent tre utiliss au sein dune fentre drivant
de TGadgetWindow, comme, par exemple, TToolBar.
Introduction C++ Builder

42

C++ Builder masque le travail de la GadgetWindow en proposant au


dveloppeur des gestionnaires dvnements au niveau de la fiche et qui semblent
directement lis aux boutons gadgets.
Ils sont crs en utilisant la commande New Button du menu rapide des objets
de classe TToolBar. A linstar des turbo boutons (qui taient prsents dans Delphi 2
pour les muler) ils peuvent tre de type commande ou settings et adopter un
comportement radio dans un groupe. Ici un groupe est un ensemble contigu de
boutons gadgets entour de sparateurs.
Les diffrents bitmaps associs aux boutons prsents dans une barre doutils
sont tous regroups au sein dune proprit de la barre doutils : ImageList. Chaque
bitmap est ensuite adress dans cette proprit via son index.
Voici donc la marche suivre pour crer une barre doutils avec des boutons
gadgets :
1. Crer tous les bitmaps en les enregistrant dans des fichiers .bmp. Vous
disposez pour cela, soit de lditeur intgr, soit de tout utilitaire capable de
gnrer des .bmp.
2. Rassembler tous les bitmaps dans un objet TImageList (on peut alors
dtruire les .bmp ...)
3. Crer lobjet TToolBar et lui associer la TImageList
4. Crer les boutons gadgets, leur adjoindre un style et leur associer leur
bitmap

Introduction C++ Builder

43

4. Utilisation minimaliste des bases de donnes


avec C++ Builder
Ce document na dautre prtention que de prsenter sommairement et par
ordre chronologique les fonctionnalits minimales permettant de travailler avec des
bases de donnes sous C++ Builder. Celles-ci sont gres par une couche logicielle
intitule BDE pour Borland Database Engine. Ce moteur de bases de donnes est
trs souple (car acceptant de nombreuses sources de donnes) et remplace lancien
Paradox Engine. Il est compatible avec les langages dinterrogation SQL ANSI et
QBE.
Nous allons raliser un exercice sur une base de donnes traitant douvrages de
science fiction.

4.1 Mise en place de la base de donnes


La premire tape consiste crer une base de donnes par lintermdiaire dun
alias de base de donnes.
Un alias de base de donnes est un identificateur unique permettant daccder
une base de donnes exploitable avec C++ Builder. Celle-ci peut tre de plusieurs
types en fonction des drivers installs sur votre systme :

Tout lien ODBC reconnu par votre environnement Windows (toujours


prsent)
Une base de donnes Access (option)
Une base de donnes SQL au format Interbase (option souvent prsente)
Un lien SQL vers un serveur Oracle, Sybase, DB2, SQL Server etc. (option).
Un rpertoire regroupant des fichiers DBASE ou PARADOX (option par
dfaut, donc toujours prsente )

La cration dun alias se fait trs simplement avec un outil nomm soit
Administrateur BDE
Dans le cas qui nous intresse, nous crons un alias pour lensemble de fichiers
au format Paradox situs dans le rpertoire c:\f2\Builder\donnees, alias que
nous nommerons TPF2ZZ2.

4.1.1 Loutil Administrateur BDE


Ladministrateur BDE est un outil la fois trs simple et trs complet. Il est
capable dafficher soit lensemble des alias dj prsents (slectionnez longlet Bases
de donnes) soit des informations concernant le systme telles que lensemble des
formats de bases de donnes disponibles ou le format des nombres (slectionnez
longlet Configuration .
Introduction C++ Builder

44

La fentre principale de ladministrateur BDE se dcompose en deux volets :

Dans le volet de gauche, vous slectionnez un objet (un alias de bases de


donnes en mode Bases de donnes)
Dans le volet de droite, vous obtenez la liste de ses caractristiques.

La figure suivante montre laspect typique de cet outil en


Configuration . La slection porte sur un pilote de bases de donnes natif.
ouvrir
une base

Annuler les
modifs

Revenir en
arrire

mode

Prendre en
compte les modifs

Onglets de
slection du
mode
Liste des alias
ou Configuration

Liste des pilotes


natifs (dpend
de l'installation
de C++ Builder
et ses Add ons

Liste des pilotes


ODBC (dpend
de l'installation
de Windows)

Fentre d'affichage des


paramtres concernant la
slection dans le volet de
gauche

Information sur
le systme (par
exemple nb de
bases ouvrables
simultanment)

Figure 4.1 Ladministrateur BDE en mode configuration


Contrairement ce que lon pourrait penser, les performances dun pilote natif
sont toujours suprieures celles dun pont ODBC. En effet, certains ponts ODBC
sont dexcellentes factures alors que lon trouve des pilotes excrables. Aussi, il est
prfrable deffectuer quelques tests.

4.1.2 Cration de lalias


La dmarche suivre est la suivante :

Lancement de lutilitaire Administrateur BDE

Introduction C++ Builder

45

Slection de longlet Bases de donnes Au passage, consultez les


informations concernant quelques alias afin de vous familiariser avec leur
format.

Nouveau dans le menu

Pour crer un nouvel alias, slectionnez Objet

Il faut ensuite slectionner le type de bases de donnes. Pour notre exemple,


choisissez STANDARD, ce qui correspond un ensemble de fichiers DBASE
ou Paradox.
Cette opration est illustre sur la figure suivante :
Liste des alias
dj prsents

Slection du type pour un


nouvel alias

Figure 4.2 Slection du type de la base de donnes

Une fois le type choisi, il vous reste remplir diverses rubriques


concernant votre nouvelle base, comme le montre la figure suivante :
Nom du nouvel
Alias

Slection du rpertoire de
donnes

Vrifiez la prsence de
vos fichiers ici !

Figure 4.3 Slection du nom de lalias et du chemin des donnes


Introduction C++ Builder

46

Vous devez renseigner absolument :

Le nom de lalias (le nom par dfaut est pouvantable

-)

Le chemin des donnes

En option, vous pouvez activer le traitement des nombres au format BCD


qui autorise une prcision infinie au dtriment des performances.
Finalement, il vous reste valider en activant la flche bleue. Une bote de
dialogue vous demande alors de confirmer. A partir de ce moment l, votre
base de donnes est accessible via C++ Builder.

Notons galement quun utilitaire nomm Module de base de donnes dcrit


dans un chapitre ultrieur permet de crer des fichiers de donnes au format
PARADOX ou DBASE ainsi que de tester des requtes SQL ou QBE simple.
Bien que rudimentaire, cet outil permet de crer simplement des tables et de
leur associer des clefs primaires ou secondaires, des fichiers dindex secondaires ou des
contraintes dintgrit.

4.2 Accs aux donnes dans C++ Builder


La premire chose faire est, bien entendu, de crer un projet C++ Builder.
Ensuite, il faut savoir que C++ Builder effectue une sgrgation forte entre les
variables qui reprsentent les donnes en tant que document et les lments visuels
(ou dinterface) qui permettent lutilisateur de les manipuler. Cest encore un bel
exemple dapplication du modle Document / Visualisation.
Il est prfrable de toujours regrouper les lments daccs aux donnes qui
sont des composants non visuels dans une unit spcialise connue sous le nom de
Module de Donnes. Celui-ci est cr par la commande Fichier
nouveau module de
donnes et se manipule ensuite comme une fiche / unit standard.

La base choisie comme exemple regroupe trois relations :

Oeuvre.db regroupe les donnes relative des ouvrages de Sciencefiction. Pour chaque livre, nous avons les champs suivants : lindex dans la
base (Clef primaire), le titre, une rfrence un auteur (clef trangre) et
une rfrence un diteur (clef trangre).
auteur.db contient les donnes dcrivant les auteurs, savoir un
index (clef primaire) et le nom
editeur.db a la mme structure quauteurs mais dcrit, comme son
nom lindique, les diteurs douvrages de science fiction (collections de
poche)
Dans un second temps, nous utiliserons une quatrime base nomme
assoc.db qui permettra dassocier plusieurs auteurs une mme
uvre.

Introduction C++ Builder

47

La premire chose faire consiste associer un composant TTable chacune


de ces relations. Pour ceci, nous choisissons un composant TTable dans la palette
Accs aux donnes que nous collons dans le module de donnes. Linspecteur
dobjets permet ensuite de lassocier un alias de base de donnes (champ Database
name) puis une relation (Table name). Il est recommand de donner ce composant
un nom en rapport avec celui de la relation. Dans cet exemple, nous choisirons
TableOeuvres, TableAuteurs et TableEditeurs.
A ce moment, il est possible douvrir la table en armant le flag active dans
linspecteur de donnes. Lindex utilis est bas sur la clef primaire sauf si lutilisateur
active un index secondaire en modifiant (par lintermdiaire dune bote combo
prsentant tous les index secondaires dfinis sur la relation) la proprit IndexName.
La figure suivante illustre un composant TTable plac sur un module de
donnes.
Palette des composants non
visuels d'accs aux donnes

Alias de base de
donnes, une
liste droulante
donne accs
tous les alias
disponibles

Composant TTable pos sur


le module de donnes

Ici, il est possible


de spcifier un
index diffrent
de la clef
primaire

Liste des tables disponibles.


Apparat une fois l'alias slectionn
Nom de la table
associe au
composant

Figure 4.4 Premire tape de la cration dun composant TTable : slection


dun alias de base de donnes

Introduction C++ Builder

48

Les principales proprits de TTable sont les suivants :

DatabaseName : nom de lalias de base de donnes ou du composant


TDatabase spcifiant la base de donnes au sein de laquelle nous allons
pcher une table. Cette proprit est commune TTable, TQuery et
TStoredProc.
TableName : nom de la relation reprsente par le composant. Une fois la
proprit DatabaseName renseigne, vous pouvez choisir le nom de la table
dans une liste droulante.
IndexName : nom de lindex actif sur la table. Par dfaut, cest--dire si le
champ est vide, il sagit de la clef primaire. Vous avez la possibilit de
slectionner un index dans une liste droulante une fois la proprit
TableName fixe.
Active : ce champ indique si la table est ouverte ou non. Vous ne pouvez le
basculer true quune fois les champs DatabaseName et TableName
renseigns.
En outre, Il faut savoir que toute modification sur la structure de la table
entrane irrmdiablement le passage de la proprit false.

FieldDefs contient la dfinition de chacun des champs de donnes de la


table.

Il est possible dinclure dautres composants non visuels dans un module de


donnes. Nous citerons en particulier :

Des composants reprsentatifs dune base de donnes (TDatabase). Ceux-ci


permettent dintercaler une couche supplmentaire entre les tables (ou les
requtes) et les alias de bases de donnes. En effet, si vous disposez de
plusieurs bases partageant la mme structure et que vous souhaitez pouvoir
utiliser votre code avec lune ou lautre indiffremment, il est possible
dutiliser une variable TDatabase qui pointera sur le bon alias. Les TTable
ou TQuery peuvent alors rfrencer ce composant dans leur proprit
DatabaseName.
Des requtes SQL (TQuery). Les requtes et les tables ont un anctre
commun nomm TDataSet dans le sens ou ces deux composant ont pour
rsultat des ensembles de donnes que lon pourra afficher. Les requte SQL
de C++ Builder sont paramtres et il est possible de rcuprer la valeur de
ces paramtres directement dans certains composants ou par jointure sur
une table ou le rsultat dune autre requte.
Des procdures stockes SQL (TStoredProc) cest dire du code SQL
prcompil pour une excution plus rapide. Il sagit habituellement de code
de maintenance et non pas de code dextraction.

Introduction C++ Builder

49

Des sources de donnes de type TDataSource. Ces composants (non


visuels) tablissent le lien entre les ensembles de donnes (Tables ou
Requtes) i.e. la partie Document du modle C++ Builder avec les
composants visuels chargs de permettre la manipulation des bases de
donnes i.e. la partie Visualisation du modle C++ Builder.

Bien que ce ne soit pas requis, il est prfrable de placer les TDataSource (ou
sources de donnes) dans le module de donnes. Personnellement, je recommande de
les placer la droite du composant TDataSet sur lequel ils travaillent.
Il est possible davoir plusieurs sources de donnes pour le mme ensemble de
donnes. On dispose ainsi de plusieurs visualisations sur un mme document. Le
placement des objets sur le module de donnes nayant pas dincidence sur le code
produit, il vous appartient de la structurer de la manire la plus cohrente possible.
La proprit la plus importante des composants TDataSource est DataSet. En
effet celle-ci indique sur quel ensemble travaille la source de donnes. Vous pouvez
spcifier dans cette proprit tout composant hritant de TDataSet, cest dire (pour
ce qui concerne les composants de base) TTable et TQuery.
Source de donnes connecte la table des oeuvres
Son nom semble indiquer qu'elle est destine une
prsentation tabulaire des donnes

Seconde source de donnes


connecte la table des
oeuvres, destine d'aprs son
nom la saisie des donnes

La proprit
DataSet indique
l'ensemble de
donnes raccord
la source

Figure 4.5 Les composants TDataSource

4.3 Les contrles orients bases de donnes


Ce sont des versions spcialises dans ldition des bases de donnes des
contrles standard de Windows ou dOWL. On retrouve ainsi, par exemple, des botes
ddition, des listes ou des boutons radio orients bases de donnes. Le contrle le plus
important est nanmoins celui qui permet de prsenter une relation ou le rsultat
dune requte sous forme tabulaire : TDBGrid. Tous ces composants se trouvent dans
la palette Contrle BD .
Les contrles orients bases de donnes se placent sur les fiches et non pas sur
le module de donnes : ils constituent la partie interface du modle
Document / Visualisation de C++ Builder.
Tous sont relis aux composants non visuels via les sources de donnes. Afin
daccder ces dernires, il ne faut pas oublier dinclure lentte du module de bases
de donnes dans la ficher de prsentation (Fichier
Inclure lentte dunit).

Introduction C++ Builder

50

4.3.1 Prsentation tabulaire dune table ou dune requte


Nous donnons ici lexemple de prsentation dune table mais ce qui suit
sapplique tout composant de type TDataSet, une requte par exemple. Le
composant TDBGrid prsente les donnes sous leur forme la plus naturelle celle dun
tableau o chaque colonne correspond un champ et chaque ligne un tuple.
Voici la marche suivre pour crer une reprsentation dun TDataSet :

Placer un composant TDBGrid sur la fiche.


Associer sa proprit DataSource une source de donnes prsente dans le
module de donnes (il sera sans doute ncessaire dinclure le fichier dentte
crer un lien uses depuis le module de donnes vers la fiche de prsentation
laide du menu Fichier Inclure lentte dunit ).

Aussitt cette dernire opration ralise, la grille se remplit des donnes


prsentes dans la relation. Si rien ne se passe, il faut vrifier la proprit Active de
la relation que lon souhaite prsenter. Le tableau cr compte autant de colonnes que
de champs dans la relation et autant de lignes que de tuples. Chaque colonne possde
un titre dont la valeur est prdfinie au titre du champ. La figure suivante illustre le
composant TDBGrid.
Titre de colonne

Source de donnes
faisant le lien avec une
table ou une requte
Ensemble des sources
de donnes
disponibles. Notez le
prfixe du module de
donnes d'origine !

Donnes sous
forme tabulaire

Figure 4.6 Prsentation tabulaire des donnes dans un composant TDBGrid


La proprit la plus importante dune TDBGrid est Columns qui est
principalement constitue dun tableau de TColumn dont chaque lment est
reprsentatif dune colonne du tableau.
A sa cration, un composant TDBGrid est dot de colonnes dynamiques, cest
dire de lensemble des champs de la relation avec les formats prdfinis. Il est
toutefois possible de crer des colonnes statiques permettant entre autre des
prsentations plus sophistiques des donnes. Toutefois, il faut garder lesprit que
Introduction C++ Builder

51

les colonnes dynamiques bougent avec lensemble de donnes. En particulier, si


vous ajoutez de nouveaux champs (ou si vous en supprimez ), les colonnes
dynamiques suivront cette progression alors quil vous faudra modifier les colonnes
statiques.

Le meilleur moyen de crer des colonnes statiques consiste double cliquer sur
la grille pour faire apparatre la liste des colonnes statiques (initialement vide).
Ensuite, on gagnera activer Tous les champs pour ajouter la listes des colonnes
statiques lensemble de champs actuellement prsents dans la Table. Les diffrents
boutons
Les diffrents boutons de la fentre des colonnes statiques permettent de
changer lordre des colonnes, de supprimer celles que lon veut exclure de laffichage,
ou bien dajouter de nouvelles colonnes si lon a touch la structure de la table (ou de
la requte) ou si lon a prcdemment supprim une colonne par inadvertance (ou
nervosit ).

Une fois la liste des colonnes statiques cre, il est possible de manipuler
chaque colonne dans linspecteur dobjets comme le montre la figure suivante.
Liste des colonnes statiques
Alignement des donnes
dans la colonne
Champ de donnes
affich dans la colonne
A choisir parmir les
champs actuellement
disponibles

Proprits du titre
Diverses oprations ralisables sur la liste des
colonnes statiques.
En particulier, "Tous les champs" tablit la liste
des colonnes dynamiques en colonnes
statiques

Figure 4.7 Manipulation des colonnes


La proprit Title est trs complexe et comprend tout ce qui est ncessaire la
manipulation dun titre, y compris une proprit Font permettant de spcifier un style
de caractres diffrent de celui de la colonne. En particulier, il est possible daligner
diffremment les donnes de la colonne et leur titre ou de choisir une fonte diffrente.
Initialement, le champ Title reprend le nom du champ de donnes ce qui nest
gure agrable, il est tout fait possible de le modifier !
A titre dexercice, changez le titre des colonnes de manire ce quil reprenne le
nom du champ mais en gras et en minuscules.

Introduction C++ Builder

52

4.3.2 Les autres contrles


Les autres contrles permettent essentiellement de modifier ou dajouter de
nouveaux lments dans la base de donnes. Par exemple, les composants liste
orients bases de donnes autorisent lutilisateur changer la valeur dun champ dans
un tuple existant ou en cours de cration.
A lusage, ils savrent relativement dangereux car ils effectuent des oprations
dinsertion ou de prise en compte automatique des modifications particulirement
nocives la sant. Aussi, je ne prconise lutilisation que de deux composants de saisie
orients donnes : TDBLookupComboBox (que nous tudierons un peu plus loin) et
TDBNavigator.
Les composants navigateur ou TDBNavigator permettent un utilisateur de se
dplacer dans un ensemble de donnes et dy effectuer des modifications si ceci est
possible. Sous sa forme la plus complte, ce composant se prsente ainsi :
Prendre en
compte les
modifications

Dernier tuple
Tuple prcdent

Supprimer le
tuple courant

Aller au
premier tuple

Rafrachir les
donnes

Ajouter un tuple
Tuple suivant

Annuler les modifications


Modifier les
donnes

4.4 Manipulations lmentaires sur les bases de donnes


C++ Builder autorise en direct quelques opration lmentaires de lalgbre
relationnelle, savoir :
Opration dalgbre
relationnelle

Vocabulaire et commande C++ Builder

Jonction

Ajout de champ Rfrence dans un


ensemble de donnes

Slection

Filtrage ou cration de relations


Matre / Dtail

Projection

Cration de colonnes statiques et suppression


des champs non dsirs dans les TDBGrid
(dj vu)

Tableau 4.1 Correspondance entre oprations dalgbre relationnel et


oprations C++ Builder

Introduction C++ Builder

53

4.4.1 Ralisation de jonctions


Dans notre exemple, nous aimerions voir apparatre les noms de lauteur et de
lditeur en lieu et place de leurs numros de rfrence dans la reprsentation
tabulaire de la relation uvres. Pour cela, nous allons ajouter des champs dits de
rfrence dans la relation. Ceux-ci ne sont pas autre chose que des jonctions limites.
Laccs aux champs dun ensemble de donnes est faussement similaire celui
des colonnes dun TDBGrid, aussi un avertissement solennel simpose. Il faut tout de
suite que vous fassiez la diffrence entre les champs prsents dans un TDataSet et la
liste des colonnes de prsentation prsentes dans un TDBGrid. Le premier reprsente
la liste des champs prsents dans lensemble de donnes, que soit des champs
endognes (prsents dans le fichier pour une table ou dans la dfinition pour une
requte) ou des champs exognes ajouts par jonction ou calcul. Le second ne dfinit
que des options daffichage de donnes. Le problme vient du fait que le vocabulaire
est trs similaire.
Une fois de plus, il nous faut distinguer entre champs dynamiques et statiques.
Afin daccder la liste des champs statiques prsents dans un ensemble de donnes,
il est ncessaire de double cliquer sur son icne ce qui finit daccentuer la confusion
possible avec la liste des colonnes dun TDBGrid.
Le menu contextuel possde deux options fort intressantes :

Ajouter champs permet dajouter dans la liste des champs statiques un


champ de donn prsent dans la structure du TDataSet.
Nouveau champ permet dajouter un nouveau champ par jonction ou
calcul.

Prcisons immdiatement que nous aurons le droit dajouter plusieurs types de


champs.

Les champs de donnes sont les champs endognes de la table, cette option
ne prsente que peu dintrt car vous pouvez faire la mme chose avec le
menu Ajouter champs
Les champs calculs permettent deffectuer des oprations arithmtiques ou
lexicographiques sur les diffrents champs. Par exemple, vous pourrez
effectuer une addition entre deux champs numriques ou une concatnation
de deux champs chanes de caractres.
Les champs de rfrence permettent deffectuer une jonction cest--dire une
mise en correspondance des valeurs de deux champs dans deux tables
diffrentes avec extraction dun rsultat.

Ajoutons un champ nomm NOM_AUTEUR et spcifiant le nom de lauteur en


partir de son numro. La jonction seffectuer entre les champs AUTEUR de uvre et
NUMERO de auteur avec NOM de auteur pour rsultat. Pour parler avec le
langage des bases de donnes, NUMERO est la clef primaire de la relation auteur
alors que AUTEUR est une clef trangre (ou externe) de uvre .
Introduction C++ Builder

54

La bote de dialogue obtenue aprs activation de Nouveau champ est la


suivante :
Taille (ventuelle)
des donnes

Nom (proprit Name) du


composant TField cr

Nom du champ
nouvellement cr

Slection du type
de donnes du
champ cr

Figure 4.8 cration dun champ de donnes


Les premires spcifications apporter sont :

Le nom du champ que vous dsirez ajouter. C++ Builder gre pour vous le
nom du composant TField gnr pour reprsenter votre nouveau champ.
Le type de donnes du champ et ventuellement sa taille. Dans le cas
dun champ calcul tout type et autoris. Dans le cas dun champ de donnes
ou dans le cas dun champ rfrence en provenance dun autre ensemble de
donnes, il faut faire attention nutiliser que des types compatibles avec
les donnes sources, par exemple, des donnes numriques entre elles.

Continuons notre jonction en choisissant de crer un champ rfrence. Le


rsultat de la manipulation est illustr par la figure suivante :
Champ de jonction
dans la table courante
(clef trangre)

Champ de jonction dans la


table externe (clef primaire)

Champ de type
rfrence, i.e. jonction

Table sur laquelle on


effectue la jonction

Champ rsultat de la jonction (dans la


table externe choisie ci-dessus)

Figure 4.9 Ralisation dune jonction : tape 2


Introduction C++ Builder

55

Choix du champ clef : Cest un champ existant dans la table actuelle et qui
doit tre une clef trangre, dans notre cas AUTEUR. Cest lun des deux
champs sur lesquels la jonction va tre opre.
Choix de lensemble de donnes : cest lensemble de donnes sur lequel va
tre effectue la jonction, ici auteurs .
Clef de rfrence : cest le deuxime champ de jonction. Il est prfrable que
ce soit la clef primaire ou, au minimum, un champ sur lequel est dfini un
index secondaire dans lensemble de donnes de jonction, ici NUMERO.
Champ rsultat : cest le rsultat de la jonction, un champ de lensemble
de donnes cible (projection), ici NOM.

Le champ nouvellement cr peut alors se traiter comme sil avait toujours


appartenu la table (champ endogne) quelques exceptions prs, comme, par
exemple, les oprations de filtrage.
Exercice (vident):
Raliser la mme opration pour le nom de lditeur.

4.4.2 Le filtrage
Le filtrage est une opration qui permet de restreindre les tuples dune table
ceux qui respectent une certaine condition nomme Filtre. Pour activer un filtre, il
faut spcifier dans la proprit Filter une chane de caractres spcifiant les critres
de filtrage et positionner la proprit Filtered true. Ces proprits tant
modifiables tout instant, cette opration pourra seffectuer trs facilement et sous le
contrle dlments dinterface.
Seuls les champs endognes dun ensemble de donnes peuvent tre filtrs.

4.4.3 Cration de fiches Matre / Dtail


Supposez dsormais que vous souhaitiez accder aux donnes dun ensemble en
fonction du tuple slectionn dans une grille. Le meilleur exemple est sans doute celui
des nomenclatures o vous disposez des trois tables.

La table produits finis reprsente lensemble des produits complexes


La table matires premires reprsente lensemble des composants
lmentaires que vous assemblez
La table composition associe sur une ligne, un produit complexe, un
composant simple et le nombre de composants simples entrant dans la
composition du produit complexe.

Vous pouvez alors dcider dafficher dans un premier TDBGrid lensemble des
produits complexes, puis, dans un second, la liste des pices le composant. Il sagit

Introduction C++ Builder

56

typiquement dune liaison matre / esclave. La table produits finis (le matre)
conditionnant laccs aux donnes de composition (lesclave).
Pour en revenir nous bouquins de science fiction, considrons dsormais que
chaque uvre puisse maintenant avoir plusieurs auteurs. Il nest plus alors question
dutiliser un simple champ permettant de rfrence lauteur : il nous faut utiliser une
nouvelle relation que nous appellerons assoc pour Association uvre / Auteurs et
qui associe sur une mme ligne une rfrence duvre une rfrence dauteur. Il
suffira dajouter autant de lignes pour un mme uvre quelle compte dauteurs.
Procdons la mise en place de la relation Matre / Esclave permettant
dafficher, pour une uvre slectionne dans un premier TDBGrid lensemble de ses
auteurs. Typiquement, le matre sera la table uvres , alors que lesclave sera
assoc .
Une fois les donnes cres, voici la marche suivre :

Prparation de la visualisation de la relation matre / esclave

Ajouter un nouveau composant TTable et une source de donnes la


relation assoc .
Ajouter le champ NOM_AUTEUR la table des associations par jointure
avec auteur sur le numro de lauteur.
Associer une grille la table des associations et ne prsenter que le nom
de lauteur.

Mise en place de la relation Matre / Dtail. Celle-ci se fait essentiellement


sur les proprits de la table esclave

Slectionner la proprit MasterSource de la TTable assoc et lui


donner pour valeur la source de donnes associe la TTable oeuvres.
Ceci indique clairement que nous nous baserons sur llment courant
de cette source de donnes comme matre.
Utiliser lditeur spcial pour choisir les MasterFields, opration qui
est similaire une jointure entre un champ de la table matre et un
champ de la table esclave

Choisir un index de assoc pour obtenir le champ joint ct


esclave, ici TITRE qui dnote un numro duvre.
Notez au passage que les relations matre / esclave ne peuvent avoir
lieu sans indexation correcte de la table esclave.

Choisir le champ de jointure ct uvres dans la case de droite,


ici NUMERO qui rfrence le numro de luvre (clef primaire)
Cliquer sur Ajouter , le tour est jou !

Introduction C++ Builder

57

Les figures suivantes illustrent en deux tapes la cration de la liaison


matre / esclave aussi nomme matre / dtails.
Champ de l'index sur
lequel va s'effectuer la
jonction

Index sur le champ de


jonction de la table
esclave

Champ de la table matre


sur lequel va s'effectuer
la jonction

La proprit
MasterSource
pointe sur une
DataSource
associe la
table Matre

Figure 4.10 Cration dune liaison Matre / Dtail : Mise en place


Appuyer sur le bouton Ajouter ajoute le couple slectionn la liste des
champs de jointure qui peut compter jusqu 16 couples !

Aprs appui sur


"Ajouter", le couple
slectionn se retrouve
dans la liste des champs
joints

Figure 4.11 Fin de cration dune liaison Matre / Dtail

4.4.4 Ajout dun tuple dans une ou plusieurs table


Pour ajouter un tuple dans une table, il suffit de passer la table dans le mode
insertion, ce qui a pour effet de crer un nouveau tuple vierge. Dans un deuxime
temps, on modifie les valeurs des champs par une instruction du style :

Introduction C++ Builder

58

IdentificateurTable.FieldByName(nom du champ) = Valeur ;


Cette opration peut tre ralise directement en affectant un contrle de
donnes un champ. Par exemple, une bote ddition de donnes TDBEdit est
connecte un champ endogne dune table via sa source de donnes. Cependant cette
opration est assez dangereuse et il vaut mieux utiliser des champs simples et confier
un bouton genre Valider le soin dincorporer les donnes dans la base.
Deux commandes principales permettent de passer en mode insertion : Append
et Insert. Il est toujours prfrable dutiliser la premire qui est moins
traumatisante pour la base de donnes. En effet, il nest gure intressant de rajouter
des tuples au milieu dune base lorsque lon peut les obtenir dans lordre que lon veut
en utilisant un index appropri, nest ce pas ?
Certains contrles permettent de slectionner des champs en effectuant une
jonction, cest le cas, par exemple des deux composants TDBLookupListBox et
TDBLookupComboBox.
Replaons nous dans le cas o chaque uvre peut navoir quun seul auteur,
nous allons effectuer lopration de saisie :

Il est possible de saisir librement le titre de luvre et le nom de lauteur, ce


qui se fera par lintermdiaire de simples composants TEdit.

Si lauteur est dj prsent dans la base auteur , alors son numro


est extrait de cette dernire et incorpor dans uvre
Sinon, un nouvel auteur est rajout dans auteur avant que son
numro ne soit ajout uvre

Il est interdit de rajouter un nouvel diteur : celui-ci devra tre choisi parmi
ceux dj prsents dans la base editeur . Nous utiliserons pour cela une
TDBLookupComboBox.

Nous allons construire une fiche sur le modle suivant :


La partie de gauche est ddie au titre de luvre, elle est compose dun
TDBEdit permettant de saisir le titre, dun bouton nomm ajouter validant cette
action et dun bouton nomm annuler .
Une fois le titre valid, il sera possible de rajouter autant dauteurs que
ncessaire en les slectionnant un par un dans une liste (TDBLookupListBox) et en
appuyant sur un bouton nomm ajouter . Il ne sera pas possible dannuler avant
davoir ajout au moins un auteur.
Le rsultat de linterface est prsent sur la figure suivante :

Le composant TDBEdit est fort simple, il suffit de le connecter sur le bon champ
via une source de donnes (en loccurrence, la source de donnes est DSOeuvres et le
Introduction C++ Builder

59

champ TITRE). En revanche la TDBLookupListBox est plus difficile utiliser car elle
utilise deux ensembles de donnes diffrents mais devant appartenir la mme base
de donnes, la figure suivant rsume ses principales proprits :

Les proprits DataSource et DataField sont respectivement relies la


source de donnes et au champ dans lequel on souhaite crire une valeur.
Les proprits ListSource et ListField sont elles lies la source de
donnes et au champ lister.
Quand la proprit KeyField, cest un champ en provenance de
ListSource et qui correspond la seconde partie de la jonction. Sa valeur
sera recopie dans celle de DataField. Ainsi, cest ListField qui est
prsent et KeyField la valeur recopie dans le champ en cours de
modification.

Les mthodes Post et Cancel de TTable permettent respectivement


dappliquer des changements ou de les annuler.
Exercice : (

Rajouter la possibilit davoir plusieurs auteurs.

Introduction C++ Builder

60

5. Utilisation du Module de Bases de Donnes


5.1 Le module de bases de donnes
Cest un utilitaire trs pratique fourni en standard avec les outils de
dveloppement de chez Inprise et qui remonte la lointaine poque de Borland.
Cet utilitaire permet, dditer les donnes prsentes dans des tables dj
existantes laide dune interface minimaliste. Ce nest toutefois pas l quil exprime
tout son potentiel.
En effet, il permet de crer des tables avec leurs index ventuels et mme, dans
certains cas, de gnrer des contraintes dintgrit rfrentielle. Ceci permet de
retrouver dans C++ Builder certaines des fonctionnalits qui lui manquaient par
rapport Access. Il faut toutefois insister sur le fait que le Module de Bases de
Donnes nest quun utilitaire qui ne saurait en aucun cas se comparer un systme
complet de gestion de bases de donnes tel quAccess.
Nous tudierons par la suite deux des fonctionnalits les plus utiles du MDD :
la cration de tables et la cration de requtes SQL.

5.2 Prsentation de linterface


Cest assurment la fonctionnalit la plus utilise du MDD. En effet, elle permet
de crer les tables sur lesquelles on veut travailler, fonctionnalit que C++ Builder
nest pas capable de raliser sans programmation.
La cration est lance par le menu Fichier

Table Nouveau

La premire tape consiste slectionner le type de table dans la bote combo


qui apparat lcran (voir la figure suivante) Si la portabilit des donnes nest pas
votre proccupation premire, je vous conseille le format Paradox 7 pour lequel BDE
(Borland Database Engine, le moteur de bases de donnes de C++ Builder) est
optimis.
La liste des formats
disponibles diffre
selon votre
installation de BDE

Figure 5.1 Liste des formats disponibles en cration de table


Une fois le type de table slectionn, le MDD vous affiche sa fentre principale
telle quelle est prsente par la figure suivante :

Introduction C++ Builder

61

Figure 5.2 Fentre principale du MDD


Cette fentre se divise en deux grandes parties. A gauche, vous avez la liste des
champs de la table, dans leur ordre de stockage, accompagns de leur type, de la taille
si elle sapplique ainsi que dune colonne nomme Index et occupe par une toile si le
champ fait partie de la clef primaire.
La partie droite est plus versatile et dpend de loption choisie. La figure
suivante regroupe les diffrentes rubriques accessibles auxquelles il faut rajouter
Langage de Table .

Figure 5.3 liste des options disponibles


Les rubriques les plus utilises sont :
Contrles de validit : permet de spcifier des contraintes sur lattribut, en
particulier, imposer que sa valeur soit instancie. Il est galement possible
de fournir des valeurs extrmes pour les attributs.
Index secondaires : permet dajouter des index secondaires sur la table. Cette
fonctionnalit sera traite plus en dtail dans une section ultrieure.
Intgrit rfrentielle : permet de fixer des contraintes dintgrit
rfrentielle (on sen doutait un peu ) entre eux tables. Pour rsumer, la

Introduction C++ Builder

62

valeur dun champ dans une table B doit correspondre une valeur
existante de la clef primaire dune autre table A.

5.3 Ajout de champs


Lajout de champs se fait tout simplement en renseignant les rubriques de la
partie gauche de la fentre, cest dire, dans lordre : le nom, le type, ventuellement
la taille pour finir par la prsence dans la clef primaire.

5.3.1 Le nom
La premire donne saisir concerne le nom du champ. Les conventions de
nommage dpendent du type de table que vous avez choisi. En rgle gnrale, et
mme si certains systmes le permettent, il vaut mieux ne pas utiliser despaces dans
le nom dun champ.

5.3.2 Le type
La figure suivante montre les diffrents types de donnes disponibles pour les
tables de type Paradox 7. Cette liste sobtient en tapant espace dans la case
rserve au type des donnes.

Figure 5.4 Types de donnes disponibles


La plupart des types de donnes prsents ne pose aucun problme. Je voudrai
toutefois revenir sur les suivants :
Incrmentation auto : la valeur de ce champ est calcule automatiquement
partir de la dernire valeur prsente dans la table. Aussi, vous navez pas la
possibilit de la fixer vous mme. Ce type est parfait pour crer des clefs
Introduction C++ Builder

63

primaires numriques si la structure de votre table nadmet pas de clef


primaire naturelle.
Mmo / Mmo Format / Binaire / Graphique ces diffrents types sont
destins stocker des quantits importantes de donnes. Contrairement
aux autres champs, ils ne sont pas stocks leur place dans la table mais
tous ensemble, soit dans un fichier spar, soit tout la fin du fichier. Leur
accs est ainsi soumis des rgles prcises.

5.3.3 La taille
Certaines donnes, telle que les chanes de caractres et les donnes
numriques en virgule fixe ncessitent une taille. Elle se prsente soit sous la forme
dun entier, soit dune paire dentiers (taille et prcision pour les rels en virgule fixe)

5.3.4 La prsence dans la clef primaire


Si vous souhaitez quun champ soit prsent dans la clef primaire, il faut saisir
une toile dans la dernire colonne de la fentre comme prsent par la figure
suivante. Attention aux bugs du MDD, nessayez surtout pas de saisir un autre
caractre, cela peut faire planter sauvagement Windows (GPF ). Bien entendu, il est
possible de faire figurer plusieurs champs dans la clef primaire.

Figure 5.5 la case Index

5.4 Dfinir des index secondaires


Les index secondaires permettent daccder trs rapidement aux donnes en
fonction dun certain critre sur les donnes. La figure suivante montre laspect de la
fentre du MDD lorsque lon slectionne Index secondaires dans les options.

Figure 5.6 la liste des index secondaires


La liste sur la droite indique quels index secondaires sont dj disponibles. Il
est possible dajouter des index, de modifier ou de supprimer les index dj existants.

Introduction C++ Builder

64

La fentre suivante est associe aux oprations dajout ou de modification


dindex secondaire.
Liste des champs de la
table.
Les champs griss sont
dj dans lindex

Boutons dajout ou de
suppression de champs
dans lindex

Champs dj prsents
dans lindex

Boutons permettant de
modifier lordre des
champs dans lindex

Figure 5.7 Dfinition des index secondaires


Les champs apparaissant en gris dans la liste de gauche sont dj inclus dans
lindex et ne peuvent donc plus y tre ajouts.
Lorsque lon spcifie plusieurs champs dans un index, celui-ci est multicritres
hirarchique. Les tuples sont ordonns dabord en fonction du premier champ, puis,
pour chaque valeur du premier champ, en fonction du second, puis pour chaque valeur
identique du couple (premier champ, second champ) en fonction du troisime et ainsi
de suite.
Les options de cette fentre sont trs simples comprendre :
Unique : spcifie que cest un index sans collision : pour une mme valeur
dindex, il ne peut y avoir quun seul tuple
Maintenu : indique que lindex est mis jour chaque opration sur la table.
Ceci peut savrer coteux si de nombreuses oprations sont effectues mais
garantit les meilleurs temps daccs aux donnes.
Dcroissant : par dfaut, les tuples sont rangs par ordre croissant sur lindex,
moins que cette option ne soit coche !
Diffrence MAJ/min : introduit une diffrenciation des mots selon la casse.
Rappelons que les Majuscules sont alors prioritaires par rapport aux
minuscules (dans lordre croissant)

Introduction C++ Builder

65

6. Utilisation des contrles ActiveX


Ce chapitre a pour objet linclusion et lutilisation de contrles ActiveX
lintrieur dune application C++ Builder. Comme vous allez le voir, hormis quelques
phases prliminaires et la redistribution des applications, leur utilisation est
absolument identique celle des contrles VCL standard.

6.1 Mise en place


La premire opration consiste vrifier linstallation du contrle dans la base
de registres de Windows. Ceci peut se faire grce une bote de dialogue spcialise
de C++ Builder active par le menu Composant
Importer un contrle ActiveX.

6.1.1 Edition de la liste des contrles disponibles

Composant
slectionn

Liste de classes
associes au composant
slectionn

Palette dinstallation du
composant

Rpertoire de cration
des units associes aux
contrles ActiveX

Chemin de recherche
des units associes aux
contrles ActiveX dj
rfrencs

Figure 6.1 La bote de dialogue des composants Active X


La premire partie de la fentre est occupe par la liste des composants ActiveX
installs sur votre ordinateur. Lorsque vous slectionnez un composant, deux cas
peuvent se produire :

Une unit est dj associe au composant, auquel cas, un ou plusieurs noms


de classes lui sont associes et apparaissent au centre de la bote de
dialogue.

Introduction C++ Builder

66

Dans ce cas, le composant est prs tre utilis et vous pouvez vous rendre
sereinement la section 2 !

Aucune classe napparat il vous faut alors associer un nom de classe au


composant et crer une unit rfrenant ses capacits. Cette activit est
commente en dtails dans la section Cration dune unit .
Nanmoins, il se peut que votre composant soit dj prt lemploi mais que
C++ Builder nait pas t en mesure de trouver vos units si le chemin de
recherche (spcifi par la bote de saisie en bas de la fentre de dialogue) est
erron. Il est donc ncessaire de vrifier ce dernier si vous pensez quun
autre utilisateur de votre systme a dj effectu le travail de cration dune
unit.

Si le composant que vous dsirez utiliser napparat pas dans la liste, cela
signifie tout simplement quil nest pas rfrenc dans la base de registre ; opration
que nous allons maintenant expliciter.

6.1.2 Recensement dans la base de registres dun nouveau


composant
Linstallation dun nouveau composant se fait en appuyant sur le bouton
Ajouter de la bote de dialogue prcdente. Une nouvelle bote de dialogue vous invite
alors slectionner le fichier contenant votre contrle, ce dernier a pour extension
.ocx.
A titre dexemple, nous allons installer le contrle standard de calendrier de
Microsoft associ au fichier c:\activex\mscal\mscal.ocx. Une fois le fichier slectionn
et valider, la bote de dialogue prcdente prsente laspect suivant :

Le nouveau composant est


slectionn par dfaut

Nom de la classe par dfaut

Figure 6.2 Fentre des composants ActiveX aprs enregistrement dun


composant
Vous noterez que le nouveau composant est dornavant prsent dans la liste. Le
nom est celui denregistrement dans le fichier .ocx accompagn du numro de version
Introduction C++ Builder

67

simplifi. Le numro de version complet peut tre obtenu grce lutilitaire Ole2View
disponible sur le site ouaib de qui vous savez.
C++ Builder propose toujours un nom de classe finissant par Proxy. En effet,
en terminologie OLE, on appelle classe Proxy, toute classe reprsentant un objet
Automate OLE ou ActiveX et masquant lutilisation des diverses interfaces. Utiliser le
nom par dfaut prsentes les avantages de la clart et de lauto-documentation ;
toutefois, rien ne vous empche de le changer.
La prochaine tape consiste ajouter votre systme une unit (i.e. une
combinaison dun fichier .h et du fichier .cpp associ) qui permettront dutiliser
facilement votre composant dans une application.

6.1.3 Cration dune unit


Cette tape permet de crer deux fichier : un fichier dentte et un fichier
dimplmentation mme de faciliter lutilisation dun composant ActiveX dans une
application. En outre, nous allons ajouter le composant dans une palette afin de
pouvoir lutiliser facilement. Par dfaut, C++ Builder vous propose dinstaller le
composant dans la palette intitule ActiveX, ce qui parat naturel. Toutefois, il vous
est possible de spcifier une autre palette dans la bote de saisie Page de palette .
La localisation des fichiers units est dfinie par la bote de saisie intitule
Nom du rpertoire unit . Celle-ci pointe naturellement sur le rpertoire o C++
Builder stocke ces fichiers de librairie. Personnellement, je recommande de crer un
autre rpertoire (par exemple, c:\activex\imports) o vous logerez toutes vos
nouvelles units ActiveX. Afin que C++ Builder sy retrouve, noubliez pas dajouter ce
rpertoire au chemin de recherche des units situ dans la bote de saisie du dessous.
Le processus de cration de lunit est lanc par lactivation du bouton
Installer de la bote de dialogue. Une fois le bouton enfonc, la bote de dialogue
ActiveX est ferme pour tre remplace par la bote de modifications des paquets.

Figure 6.3 Installation du composant dans un paquet


La notion de paquet est quelque peu complique pour tre explique ici. Pour
lheure il vous suffit de valider systmatiquement toutes les options qui vous sont
prsentes.

Introduction C++ Builder

68

La nouvelle unit sera alors compile et enregistre dans un paquet , la


dernire bote de message vous indiquant que lopration a t ralise avec succs
du moins, je lespre et que votre composant a t recense avec le nom de classe que
vous aviez spcifi.
Lorsque toutes les botes de dialogue successives ont t fermes, deux
nouveaux fichiers apparaissent dans la fentre ddition. Leur nom est compos pour
partie du nom du composant ActiveX suivi dun tiret bas et du mot TLB. Ce dernier
signifie Type Library et indique ainsi que les fichiers crs contiennent la librairie de
type du composant ActiveX.
Rappelons brivement que la librairie de type contient la liste des interfaces
associes un composant, et, pour chaque interface :

Lensemble des mthodes chacune accompagne de la liste de ses


paramtres avec leurs types
Lensemble des proprits avec leurs types

La consultation du fichier .cpp nest habituellement daucune utilit. En


revanche, lutilisateur curieux peut se lancer non sans stre pralablement muni
daspirine et dAlka Seltzer en quantit suffisante dans ltude du .h qui ne
manquera pas de lui montrer ltendue des interfaces de son composant.
En outre, vous pourrez noter la prsence dune nouvelle icne dans la palette de
composants que vous avez choisie pour recenser votre composant.
Notez la prsence de votre composant dans la palette !

Figure 6.4 mise jour de la palette

6.2 Utilisation dun contrle ActiveX


Une fois lopration prliminaire ralise, vous tes pour ainsi dire sortie
daffaire. En effet, le contrle ActiveX sutilise comme nimporte quel composant de la
VCL. Il est muni dune reprsentation visuelle, et ces proprits saffichent tout fait
normalement dans linspecteur dobjet.
Dans la plupart des cas, vous pourrez lui associer des vnements utilisateurs.
Les figures suivantes montrent respectivement laspect du composant Calendrier pos
sur une fiche et les vnements qui lui sont associs. Les proprits les plus
intressantes ont pour nom Day, Month, Year et Value. Je vous laisse les examiner
vous mme.
A partir de ces informations, je vous encourage crer un petit programme
mettant en scne ce composant !

Introduction C++ Builder

69

Mois slectionn
Anne courante

Liste des jours du mois

Date courante

Figure 6.5 le composant Calendrier plac sur une fiche


Evnements respectivement
appels aprs et avant le
redessin du composant lorsque
lon clique sur un bouton de
jour

Evnements lancs lorsque


lutilisateur slectionne
respectivement un nouveau
mois ou une nouvelle anne
dans les botes combo

Figure 6.6 Evnements associs au contrle calendrier

6.3 Dploiement dun programme utilisant un contrle ActiveX


Lutilisation dun programme contenant un composant ActiveX ncessite
linstallation de ce dernier. Aussi, il ne faut surtout pas oublier dembarquer ledit
composant lorsque vous dployez votre programme.
Dordinaire, les fichiers associes un composant sont les suivants :

Un fichier .ocx qui contient le code du composant


Un fichier .hlp et un fichier .cnt, supports de laide relative au composant
Un fichier .dep de dpendances sur dautres composants ActiveX

Introduction C++ Builder

70

7. Lcriture de nouveaux composants


Nous abordons l lutilisation avance de C++ Builder. Tout dabord, nous
allons voir comment ajouter des composants lenvironnement et les adjoindre une
palette. Le chapitre suivant indiquera comment les transformer en composants
ActiveX.

7.1 Gnralits
Les composants sont des instances de classes drivant plus ou moins
directement de TComponent. Si leur forme la plus habituelle est celle des composants
que lon dpose dune palette vers une fiche, ils englobent plus gnralement la notion
de brique logicielle rutilisable. Bien que non dclare virtuelle pure2 la classe
TComponent nest pas destine tre instancie. Compulsons sa documentation ;nous
y apprenons que la plupart des mthodes sont protgs, cest dire inaccessibles
lutilisateur, cest une technique courante en Pascal Orient Objet : dfinir le cadre de
travail laide de mthodes virtuelles protges, lesquelles seront dclares publiques
dans les classes drives.
Autre aspect particulirement intressant : la prsence des mthodes AddRef,
Release et QueryInterface ce qui dnote limplmentation de linterface OLE
IUnknown. Ainsi, lorsque lon transformera un composant VCL en composant ActiveX,
la gestion dIUnknown sera directement prise en compte au niveau de TComponent.
De la mme manire, TComponent implmente linterface principale dautomation
IDispatch (mthodes GetIDsOfNames, GetTypeInfo, GetTypeInfoCount et
Invoke). Nous aurons loccasion de revenir plus en dtails sur ces mcanismes
spcifiques OLE dans un prochain chapitre.
Pour finir, notons que les composants de Delphi et de C++ Builder sont
compatibles : autrement dit, il est tout fait possible dutiliser dans C++ Builder un
composant cr avec Delphi et rciproquement.

7.2 Cration dun nouveau composant


La cration dune nouvelle classe de composants se dcompose globalement en
les tapes suivantes :
1) Drivation dune classe existante
2) Implmentation de la classe
a) Redfinition des mthodes

En effet, la classe TComponent, linstar de toutes les autres classes de la VCL est
implmente en langage Pascal Objet, lequel saccommode assez mal de la notion de classe virtuelle
pure.
2

Introduction C++ Builder

71

b) Modification de rgles de visibilit


c) Ajout de proprits et dvnements
3) Test de la classe
4) Eventuellement, ajout dun fichier daide pour les utilisateurs
5) Enregistrement dans le registre
6) Ajout dans une palette
Le processus de cration dun nouveau composant tant, par dfinition, trs
dpendant du concepteur, trs peu dtapes sont automatisables et ralisables par les
fameux experts dInprise.
Toutefois, il est possible de gagner un tout petit peu de temps en invoquant
lexpert composant.
Nous allons tayer notre propos par la ralisation de trois nouveaux
composants. Le premier, (volontairement trs simple) consiste redfinir le
comportement de la classe TListBox, le deuxime crer un composant dactualit
permettant de transformer les Euros en Francs et rciproquement. Le troisime
composant sera de type graphique, spcialis dans laffichage de graphes. Nous
montrerons galement comment encapsuler une fiche dintrt gnral dans un
composant afin de pouvoir la rutiliser plus facilement.

7.2.1 Lexpert composant


Le dbut du processus consiste demander la cration dun nouveau
composant, via le menu Fichier
Nouveau puis choisir Composant dans la fentre.
La bote de dialogue de lexpert composant est illustre par la Figure 7.1

Classe dont va driver


le nouveau composant

Nom de classe choisi pour


le nouveau composant

Palette dinstallation

Chemin utilis par


C++ Builder lors de la
recherche du source
des composants

Emplacement et nom des


fichiers .h et .cpp gnrs

Figure 7.1 Expert composant


Lutilisation de cette fentre dassistant est particulirement limpide. Seul le
bouton installer rclame notre attention et les options parlent delles mmes.
Introduction C++ Builder

72

Type Anctre : spcifie de quelle classe drive votre composant, cest le propos
de la prochaine section
Nom de classe : saisissez le nom que vous souhaitez donner votre classe de
composant.
Page de palette : nom de la palette dans laquelle vous souhaitez inclure votre
composant. Il est possible de crer de nouvelles palettes avec dautres
fonctionnalits de C++ Builder. Pour des raisons videntes (embrouille des
utilisateurs, manque de cohrence des composants prsents, etc.) je
dconseille de rajouter un composant personnalis dans une palette
standard de C++ Builder
Nom de fichier unit : typiquement le nom des fichiers .h et .cpp gnrs
reprend celui de la classe ce qui me parat tre une bonne ide. Plus
intressant, il vous est possible de choisir le rpertoire dans lequel vous
souhaitez installer ces fichiers. Par dfaut, il sagit dun des rpertoires
appartenant larborescence interne de C++ Builder. Je vous conseille de
les positionner ailleurs afin dviter leur destruction lors dune
dsinstallation manu militari de C++ Builder. Auquel cas, il convient de
vrifier que votre nouveau rpertoire est bien inclus dans le chemin de
recherche spcifi dans la bote de saisie suivante.
Finalement, seul le bouton Installer pose problme, son invocation amne la
fentre suivante :

Figure 7.2 Spcification du paquet d'installation d'un nouveau composant


Son rle est de spcifier le paquet dans lequel sera install le composant.
Brivement, il suffit de savoir que les paquets correspondent des DLL dans lesquels
sont rassembls les composants. Par dfaut, tout nouveau composant est rajout dans
un paquet nomm DCLUSR3, cest dire paquet utilisateur gnr par la version 3
de C++ Builder (ou, en Anglais Delphi Cluster User Version 3), lequel est situ dans
les rpertoires de larborescence de C++ Builder. Il vaut mieux utiliser un paquet situ
dans un rpertoire propre lutilisateur afin dviter toute dsinstallation
intempestive. De mme, si vous dsirez exporter votre composant, il sera
probablement ncessaire de crer un nouveau paquet (vous disposez pour cela dun
onglet spcialis) recueillant uniquement les composants destins votre client.
Nous verrons dans une prochaine phase que les paquets se manipulent trs
facilement la manire des projets. En outre, si vous tes dans le projet
Introduction C++ Builder

73

correspondant un paquet lorsque vous fates nouveau composant ce dernier est


automatiquement plac dans le paquet associ au projet.

7.2.2 De quel composant driver ?


La premire question se poser est la suivante : De quelle classe doit driver
mon composant ?
En effet, une grande partie du travail de conception dpend de cette phase
initiale. Driver dune classe trop gnrale va vous contraindre crire normment
de code et rinventer la roue. En revanche, driver dune classe trop spcialise
risque dtre coteux en ressources Windows et prvoir des comportements pour des
proprits ou des vnements sans intrt pour vous. Le schma de la Figure 7.3
permet de guider votre choix :
Comportement spcialis
d'un composant existant ?

oui

Driver du
composant
spcialiser ou de
sa forme abstraite

oui

non

Composant visuel ?
non

oui

Destin recevoir la
focalisation ?

Driver de
TWinControl

non

Driver de
TComponent

Driver de
TGraphicControl

Figure 7.3 dtermination de la classe de base dun nouveau composant


Si vous souhaitez spcialiser ou modifier le comportement dun composant dj
existant, la rponse est trs simple : il suffit de driver ce dernier. Dans tous les
autres cas, la rponse est un peu plus complique.
7.2.2.1 Custom ou pas Custom ?
Si vous observez la spcification de la VCL, vous verrez que la plupart des
composants directement utilisables drivent dun autre composant dont le nom
contient en plus le mot Custom. Par exemple, TControl drive de TCustomControl.

Introduction C++ Builder

74

Les classes contenant Custom sont lquivalent des classes de base virtuelles
pures dans le sens o elles ne sont pas destines tre directement instancies mais
laissent ce soin leurs classes drives qui implmentent les comportement quelles
dcrivent dans leur interface.
La plupart des fonctionnalits (proprits ou mthodes) dune classe Custom
sont protges. Il vous appartient alors de rendre publiques (ou publies) uniquement
celles que vous souhaitez rendre visibles lutilisateur ce qui vous fournit un excellent
contrle sur lutilisation de la classe.
7.2.2.2 Crer un composant non visuel
Rsolvons en premier lieu le cas des composants non visuels, cest dire ceux
dont le placement sur une fiche nentrane que laffichage dune icne. Ils peuvent
avoir plusieurs rles. Citons notamment :
La rservation de ressources Windows : cest en particulier le cas, des
botes de dialogue communes de Windows qui apparatront sur leur forme
normale lors de leur invocation par le programme
Les composants nayant aucune reprsentation graphique. Dans cette
catgorie se retrouvent, par exemple, les composants permettant de lier
votre application des lments de bases de donnes ou des sockets de
rseau.
Reposez vous alors la question, suis-je bien certain que mon composant na
aucun lien avec lun de ceux existants ? si la rponse est oui , alors il vous faut
driver directement de TComponent, dans tous les autres cas essayez de trouver dans
larborescence de la VCL un anctre convenable qui permette de vous simplifier la
tche.
Rappelons galement que si votre composant non visuel est destin tre
dpos sur une fiche, il faudra fournir une icne de reprsentation.
7.2.2.3 Crer un composant visuel
Les composants visuels sont ceux dont la reprsentation sur une fiche reflte
exactement laspect lexcution. Bien quils drivent toujours de TControl, on peut
les discriminer en deux grandes catgories laide dun critre simple : le composant
doit il tre capable de recevoir la focalisation Windows ?
Si, oui, cest un composant actif et le plus simple consiste les driver de
TCustomControl et, travers ce dernier de TWinControl.
A loppos, si votre composant nest pas destin recevoir la focalisation, il vaut
mieux driver de TGraphicControl. Le principal intrt est de ne pas consommer
trop de ressources. En effet, loppos des TCustomControl, les TGraphicControl
ne drivent pas de TWinControl et donc ne disposent pas dun handle de fentre, ce
qui permet de prserver ce type de ressources. Par exemple, un TButton drive de
TWinControl alors quun TToolButton drive de TGraphicControl.

Introduction C++ Builder

75

Lautre diffrence important rside dans la gestion de laspect. En effet,


lapparence gnrale dun TWinControl est mmorise par Windows lorsquil est
masqu, ainsi, lorsquil rapparat au premier plan cest le systme qui le redessine
sans appel WM_PAINT. En revanche, les TGraphicControl ne sont pas mmoriss,
aussi, lorsque leur aspect doit tre remis jour, il y a gnration dun vnement
WM_PAINT lequel doit tre intercept par lutilisateur. Dans la VCL, cet vnement
appelle toujours la mthode Paint que vous devrez redfinir pour que votre
composant se redessine correctement.

7.3 Exercice rsolu : cration du composant TListBoxCool


7.3.1 Motivation et droulement gnral de lexercice
Les composants TListBox encapsulent les composants botes de listes
classiques de Windows.
Le mode de slection de ces composants est rgi par deux proprits :

lorsque MultiSelect est false, la bote est en mode de slection simple :


un seul lment peut tre slectionn la fois, son rang est indiqu par la
proprit ItemIndex. Si aucun lment nest slectionn ItemIndex vaut 1.
Lorsque MultiSelect est true, la bote est en mode de slection multiple
si ExtendedSelect est false ou en mode de slection tendue si
ExtendedSelect est true. La principale diffrence entre les modes
multiple et tendu tient au fait que ce dernier autorise la slection et lajout
de plages une slection dj existante. En pratique, il nest pas de cas o
le mode tendu ne soit pas prfrable au mode multiple.

Hors, il est particulirement pnible daccder aux index des lments


slectionns en mode multiple ou tendu :

Le nombre dlments slectionns est stock dans la proprit SelCount


(jusquici tout va bien )

Il faut ensuite vrifier le statut slectionn de chaque lment de la liste


grce la proprit indice Selected qui sutilise comme un tableau sur
lensemble des lments (numrots de 0 ItemCount 1)

Lexemple de code suivant monte la gymnastique ncessaire pour afficher la


liste des index des lments slectionns accompagns des lments eux mmes. Les
lments dune bote de liste sont stocks dans la proprit Strings de sa proprit
Items.
int indiceSelected=0;
for (int compteur=lbc->SelCount-1;compteur>=0;compteur--)
{
while (!lbc->Selected[indiceSelected])
indiceSelected++;
meStd->Lines->Add(IntToStr(indiceSelected)+" "+

Introduction C++ Builder

76

lbc->Items->Strings[indiceSelected]);
indiceSelected++;
}

Programme 7.1 Programme daffichage des index et des lments


slectionns dune bote de liste
Le rsultat visuel est illustr par la figure suivante o vous pourrez vrifier que
cela fonctionne !

Figure 7.4 Affichage des index et des lments slectionns dune bote de
liste par le Programme 7.8
Le but est dajouter une proprit nomme Indices qui permette daccder
directement aux indices des lments slectionns comme dans lexemple de code
suivant :
meCool->Lines->Clear();
for (int compteur=0;compteur < lbc->SelCount;compteur++)
{
meCool->Lines->Add(IntToStr(lbc->Indices[compteur])+" "+
lbc->Items->Strings[lbc->Indices[compteur]]);
}

Programme 7.2 Vers une utilisation plus simple des botes de listes

me

Pour rsumer, on souhaite que Indices[i] nous renvoie le numro dindex du


lment slectionn.

7.3.2 Mise en place


7.3.2.1 Cration dun nouveau paquet
Lutilisation dun nouveau paquet simplifie considrablement la gestion des
composants car elle a lavantage de les associer un projet : celui du paquet. Lorsque
vous voudrez modifier votre composant, nous le ferez en chargeant le projet associ
votre paquet (extension .bpk).
Voici la marche suivre :
Introduction C++ Builder

77

1. Crez un nouveau paquet (Fichier


Nouveau
Paquet). Cest une
opration trs simple o lon ne vous demande que de saisir un nom de
fichier et, ventuellement une description comme le montre la figure
suivante :

Figure 7.5 Cration dun nouveau paquet


A ce moment l, le paquet est vide. Toutefois, un nouveau projet nomm
MonPaquet.bkp a t cr et il vous est possible de le construire, ce dont
vous ne vous privez surtout pas ! (Projet
construire MonPaquet)

2. La prochaine tape consiste inclure le paquet nouvellement cr dans la


liste des paquets chargs automatiquement par C++ Builder. Ceci se fait
grce la fentre active par le menu Composant
Installer des paquets.

Figure 7.6 le gestionnaire de paquets


Les fonctionnalits de cette bote de dialogue sont multiples. Tout dabord, le
volet principal vous donne la liste des paquets reconnus par le systme. Les
boutons Ajouter et Retirer vous permettent respectivement dajouter et de
supprimer un des paquets. Attention ! retirer ne supprime pas
physiquement le fichier contenant le paquet (fichier .bpl) mais seulement sa
rfrence de la liste des paquets reconnus et chargs automatiquement dans
la palette !.

Introduction C++ Builder

78

Le bouton composants fait apparatre la liste des composants contenus dans


un paquet, par exemple, la figure suivante illustre le contenu du paquet
Composants Internet de C++ Builder .

Figure 7.7 Liste des composants dun paquet


Aussi pratique soit-elle, cette fentre ne permet toutefois que de visualiser
le contenu dun paquet. Pour supprimer un composant dun paquet, il faut
en effet diter le projet et supprimer la rfrence de lunit lie au
composant comme on le ferait pour supprimer un fichier source du projet
dun excutable.
3. Utilisez le bouton ajouter pour ajouter votre paquet la liste des paquets
actifs.
Par dfaut, un nouveau paquet est uniquement utilis en conception. En
dautres mots, il est utilis par lenvironnement de C++ Builder 3 lorsque vous ajoutez
vos composants sur les fiches. Il vite aussi dutiliser de trop nombreux fichiers .h car
le fichier dinclusion .bpi du paquet est utilis.
Toutefois, lors de la cration de lexcutable le code de vos composants est ajout
intgralement augmentant dautant la taille de lexcutable. Lautre solution consiste
ajouter votre paquet la liste des paquets dexcution. Ainsi, lexcution, le fichier
.bpl cr sera utilis en tant que DLL permettant de partager le code de votre
composant entre les diverses applications qui lutilisent. Ce mcanisme est
particulirement agrable utiliser mais ncessite que le fichier .bpl soit plac dans
un rpertoire du PATH ou bien dans le rpertoire standard des paquets de C++
Builder.
7.3.2.2 Cration du composant

Si vous avez ferm le projet correspondant au paquet, rouvrez ce dernier.


En effet, crer le composant alors que vous avez ouvert un projet
correspondant un paquet garantit que le composant sera install dans ce
dernier. En outre, lorsque vous voudrez modifier votre composant, il vous
suffira douvrir le projet associ au paquet.
Drivez un composant de TListBox, nommez le TlistBoxCool (en effet,
la gestion des botes de liste de cette manire sera nettement plus cool,
non ? ) , logez le dans la palette Exemples. Comme vous tes dans le

Introduction C++ Builder

79

projet associ un paquet, il sera automatiquement log dans ce dernier (je


sais, je me rpte, mais dans ce cas l cest ncessaire)
Les fichiers TListBoxCool.h et TListBoxCool.cpp (si vous ne les avez
pas renomms ) sont automatiquement crs pour vous et contiennent le
squelette de votre composant. Notez lutilisation dun espace de nommage
dans le fichier .cpp pour isoler la fonction Register charge dinclure dans
le registre les informations concernant votre nouveau composant.

7.3.2.3 Amnagement du composant


Lamnagement du composant TListBox vers TListBoxCool est des plus
simples. En effet, il suffit de lui adjoindre une proprit de type entier index que
nous allons appeler Indices.
Afin de nous simplifier la vie, cette proprit sera du type sans attribut de
stockage . Lorsque nous tenterons daccder la proprit Indices, nous relirons la
proprit Selected, automatiquement mise jour par les messages Windows. En
outre, nous ne donnerons accs cette proprit qu lexcution (elle est donc en accs
public) et en lecture seulement. Le code de dclaration de la classe TListBoxCool est
le suivant :
//--------------------------------------------------------------------------#ifndef ListBoxCoolH
#define ListBoxCoolH
//--------------------------------------------------------------------------#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
#include <StdCtrls.hpp>
//--------------------------------------------------------------------------class PACKAGE TListBoxCool : public TListBox
{
private:
// Methode de lecture des indices
int __fastcall getIndices(int index);
protected:
public:
__fastcall TListBoxCool(TComponent* Owner);
// Creation d'une proprit indexe permettant d'accder directement aux
// indices des lments slectionnes
__property int Indices[int index] = {read=getIndices};
__published:
};
//--------------------------------------------------------------------------#endif

Programme 7.3 Dclaration de la code TListBoxCool


Un petit commentaire simpose quand ces dclarations. En effet, une proprit
doit tre scalaire : il nest pas possible de renvoyer un tableau en proprit. La parade
Introduction C++ Builder

80

consiste crer une proprit indexe : lindexation est gre par la mthode daccs
getIndices qui prend lindex en paramtre.
Ce comportement est bien accord lesprit des proprits qui peuvent tre
modifies tout instant par un message Windows.
Le code dimplmentation de la mthode getIndices est alors :
int __fastcall TListBoxCool::getIndices(int index)
{
// vrification de l'adquation aux bornes
if (index >=0 && index < SelCount)
{
int indiceSelected=0;
// parcours de la liste des lments slectionns
// jusqu'au moment ou l'on arrive au index_ime
for (int compteur=0;compteur<=index;compteur++)
{
while (!Selected[indiceSelected])
indiceSelected++;
indiceSelected++;
}
return indiceSelected-1;
}
else
return -1;
}

Programme 7.4 Implmentation de la mthode daccs getIndices


A chaque appel sur la proprit Indices, on effectue un parcours sur la
proprit Selected, laquelle envoie un message Windows au composant liste, ce qui
nest gure efficace mais garantit la justesse des informations !
Le programme suivant indique comme fonctionne notre nouvelle proprit.
Vous y retrouvez galement lutilisation de Selected, notez la simplification !
void __fastcall TForm1::Button2Click(TObject *Sender)
{
meStd->Lines->Clear();
// Utilisation de Selected
int indiceSelected=0;
for (int compteur=lbc->SelCount-1;compteur>=0;compteur--)
{
while (!lbc->Selected[indiceSelected])
indiceSelected++;
meStd->Lines->Add(IntToStr(indiceSelected)+" "+
lbc->Items->Strings[indiceSelected]);
indiceSelected++;
}
// Utilisation de Indices
meCool->Lines->Clear();
for (int compteur=0;compteur < lbc->SelCount;compteur++)
{
meCool->Lines->Add(IntToStr(lbc->Indices[compteur])+" "+
lbc->Items->Strings[lbc->Indices[compteur]]);
}
}

Introduction C++ Builder

81

Programme 7.5 Utilisation de la proprit Indices


7.3.2.4 Compilation du paquet
Lancez maintenant la compilation du paquet Ctrl-F9 . Le message de la
figure suivants apparat pour vous avertir de la reconstruction du paquet. Une fois
que vous aurez bien saisi les mcanismes sous-jacents, vous pourrez cocher la case
Ne plus afficher ce message afin de supprimer cette notification visuelle.

Figure 7.8 Avertissement de recompilation dun paquet


La premire fois que vous compilez un paquet contenant un ou plusieurs
nouveaux composants, C++ Builder vous avertit de leur recensement par la fentre
suivante :
En fait, C++ Builder a non seulement lanc la procdure de compilation et
ddition de lien du paquet mais de surcrot lanc automatiquement lexcution des
fonctions Register spcialises dans le recensement des composants.

Figure 7.9 Avertissement de mise jour du registre des composants


Ce message napparat que lors du premier recensement dun composant.
Lorsquun composant est connu, les informations qui lui sont relatives sont seulement
mises jour et lavertissement nest pas reconduit.
7.3.2.5 Vrification de la palette
Vous pouvez dornavant vrifier que votre composant est prsent sur la palette
Exemples comme le montre la figure suivante :

Introduction C++ Builder

82

Figure 7.10 Mise jour de la palette !


Comme nous navons pas fourni de nouvelle icne pour ce composant, il reprend
celle de son anctre le plus rcent : TListBox.

7.3.3 Utilisation du composant


A partir de son installation sur la palette, vous pouvez utiliser votre composant
comme bon vous semble et comme sil sagissait dun composant natif de Delphi.

7.3.4 Utilisation dun composant non install sur la palette


Il est possible dutiliser un composant non encore recens sur la palette. Il sagit
alors de procder comme sil sagissait dun objet tout ce quil y a de plus normal :
cration manuelle avec appel new, affectation des diverses proprits (noubliez pas
daffecter la proprit parent, sinon le composant ne saffichera pas ) et destruction
laide de delete. Toutes ces oprations vont tre vues plus en dtail dans la section
suivante ddie la cration du composant Calculette Francs
Euros.

7.4 Exercice Rsolu n2 : La calculette Francs Euros


Il sagit ici de crer une calculatrice qui permette de convertir des Francs en
Euros et rciproquement. Dans ce cas l, nous nous simplifions lexistence en utilisant
le paquet des composants utilisateur : dclusr35.
Nous allons raliser un nouveau composant qui en inclut lui mme 5 autres :

Un label indiquant dans quelle bote saisir / afficher une somme en Francs
Un label indiquant dans quelle bote saisir / afficher une somme en Euros
Un label indiquant le taux de conversion Francs / Euros
Une bote de saisie affichant une somme en Francs et o lutilisateur peut
saisir un montant qui sera converti en Euros
Une bote de saisie affichant une somme en Euros et o lutilisateur peut
saisir un montant qui sera converti en Francs
Un bouton qui permettra, dans un second temps, dinvoquer une bote de
dialogue permettant de saisir un nouveau taux pour lEuro.

Une fois dpos sur une fiche, le rsultat final ressemble la Figure 7.11
Voici le droulement du projet :
Introduction C++ Builder

83

5. Crer le composant
6. Crer des proprits
7. Grer laspect visuel du composant
8. Grer les vnements internes
9. Associer une icne au composant
10. Ajouter la bote de saisie du taux de change
Les diffrents
widgets inclus
dans le composant

Proprits
spcifiques
au nouveau
composant

Fond du composant
sur lequel sont greffs
les widgets

Figure 7.11 Le composant calculette avec ses proprits associes

7.4.1 Crer le composant


1. Ouvrez le projet associ au paquet des composants exemples. Il se nomme
dclusr35.bpk et se trouve dans le rpertoire lib de linstallation de C++
Builder.
2. La cration du composant lui mme peut trs bien se faire laide de
lexpert composant. Le composant Calculette ntant la version spcialise
daucun composant prsent sur la palette, nous allons lui donner
TCustomControl comme classe de base (pour plus dclaircissements sur le
choix de la classe de base, vous pouvez vous reporter la Figure 7.3).
3. Donnez un nom quelconque au composant, dans toute la suite de cet expos,
le type du composant est TCCBruno.
4. Affectez le la palette Exemples

7.4.2 Crer des proprits


Les proprits sont trs importantes pour un composant car elles permettent de
spcifier des valeurs pour les attributs fondamentaux lors de la conception sur fiche.
Recensons les proprits inhrentes au fonctionnement de notre calculatrice :
Taux : Le taux de conversion Francs
Introduction C++ Builder

Euros
84

Francs : La somme courante en Francs


Euros : La somme courante en Euros
Chacune de ses proprits tant fondamentalement de type double, nous allons
crer trois attributs private double qui ne serviront qu stocker les valeurs de ces
proprits. Notons immdiatement (avant que quelquun nen fasse la remarque )
que deux attributs seulement taient ncessaires : la valeur des Euros se dduisant de
celles des Francs et du Taux et rciproquement. Cette solution est dailleurs laisse en
exercice.

Par convention, les noms des attributs de stockage des proprits commencent
tous par la lettre F suivie du nom de la proprit, nous obtenons donc :
private:
double FTaux;
// Attribut de stockage du taux de change
double FFrancs; // Attribut de stockage de la somme en Francs
double FEuros; // Attribut (redondant) de stockage de la somme en Euros

Programme 7.6 Mise en place dattributs de stockage des proprits


Reste spcifier la politique daccs aux proprits. Dans notre cas, le plus
simple est dutiliser des mthodes dcriture sophistiques qui assurent la cohrence
des donnes entre elles ainsi que des vnements chargs de mettre jour les valeurs
des proprits lorsque du texte est saisi dans les botes ddition. Ainsi, on peut lire
directement la valeur des proprits dans lattribut de stockage.
Le reste des dfinitions inhrentes aux proprits devient :
private:
__fastcall
__fastcall
__fastcall

__published:
__property

void SetTaux
(double value);
void SetFrancs (double value);
void SetEuros (double value);

double Taux

= {read
write
default
stored
__property double Francs = {read
write
default
stored
__property double Euros = {read
write
default

= FTaux,
= SetTaux,
= 6,
= true};
= FFrancs,
= SetFrancs,
= 0,
= true};
= FEuros,
= SetEuros,
=0};

Programme 7.7 Dclaration de mthodes daccs et des proprits


Quelques points dexplications :
Les proprits sont publies (clause de visibilit __published), ce qui permet
de les modifier dans linspecteur dobjet et leur confre une visibilit de type public.
En revanche, les mthodes daccs sont private, linstar des attributs de stockage

Introduction C++ Builder

85

Laccs en lecture se fait directement sur lattribut de stockage


Il est possible de fournir des valeurs par dfaut grce la clause
default = valeur
Seules les valeurs des proprits Francs et Taux sont stockes sur disque
(stored = true). En effet, la valeur de Euros est immdiatement
dductible des deux autres.

7.4.3 Grer laspect visuel du composant


Dans notre cas prcis, laspect visuel du composant est compos de trois grandes
parties :

Le style du composant, proprit commune tous les descendants de


TControl.
Le positionnement et laffichage de composants inclus (TLabel et TEdit)
La publication de proprits masques

7.4.3.1 Le style du composant


Laspect visuel et comportemental des composants drivs de TControl est gr
par leur proprit ControlStyle qui est un Set dlments numrs. Daprs la
documentation officielle, les diffrentes caractristiques prsentes par dfaut
dpendent fortement de la classe du composant. Voici leur liste exhaustive :

csAcceptsControls : Le contrle devient le parent de tout contrle plac


dedans au moment de la conception. Ce style est activ par dfaut pour
TForm, TGroup, TToolBar, TPanel et leurs homologues et dsactiv pour
les autres.
csCaptureMouse :Le contrle capture les vnements de la souris quand
on clique dessus. La plupart des contrles visuels activent cette option.
csDesignInteractive : Au moment de la conception, le contrle redirige
les clics du bouton droit de la souris en clics du bouton gauche de la souris
manipulant le contrle.
csClickEvents : Le contrle peut recevoir et rpondre aux clics de la
souris.
csFramed :Le contrle a un cadre 3D, en creux par dfaut (linverse dun
TPanel standard dessin en relief)
csSetCaption :Le contrle doit changer son libell pour correspondre la
proprit Name si le libell n'a pas t dfini explicitement avec une autre
valeur. Cette option est particulirement nervante lorsque lon travaille en
mode conception. Elle est active par dfaut pour tout ce qui est TLabel,

Introduction C++ Builder

86

TGroupBox, TButton etc. Dans le cas des TEdit, cest la proprit Text qui
est modifie !

csOpaque : Le contrle remplit entirement son rectangle client par un


rectangle dont la couleur est clBtnFace par dfaut.
csDoubleClicks : Le contrle peut recevoir et rpondre aux messages de
double-clic. Sinon, les doubles clics sont traits comme des simples clics.
csFixedWidth : La largeur du contrle ne varie pas et ne fait pas l'objet
d'une mise l'chelle, notamment dans le cas du redimensionnement des
fentres. Typiquement, cette option est toujours active, il ne faut la
dsactiver que lorsque vous savez exactement ce que vous faites !
csFixedHeight : Le pendant pour la hauteur de csFixedWidth pour la
largeur.
csNoDesignVisible : Le contrle est invisible au moment de la
conception. Dans la pratique, cette option na que trs peu dintrt sauf
pour les paranoaques qui fournissent des fiches avec des composants
personnaliss quils ne veulent pas faire apparatre. En effet, le propre du
composant est tout de mme de faciliter la programmation et dapparatre
sur les fiches !
csReplicatable : Le contrle peut tre copi en utilisant la mthode
PaintTo pour dessiner son image dans un canevas arbitraire. A ma
connaissance, cette option est trs peu utilise lexception du composant
TShape dont le but est prcisment de dfinir des sprites de conception.
csNoStdEvents : Les vnements standard (souris, clavier, clic de la
souris) sont ignors. Sil est possible dutiliser cet indicateur pour acclrer
votre application lorsquun composant n'a pas besoin de rpondre ces
vnements, il est tout de mme prfrable dutiliser directement des
composants de type gadget ou des formes fixes.
csDisplayDragImage : Le contrle peut afficher une image extraite d'une
liste d'images quand l'utilisateur fait glisser le pointeur de la souris audessus du contrle. Cest typiquement le cas des boutons dans les barres
doutils qui se mettent clignoter ou changent de couleur de fond.
csReflector : Le contrle rpond aux messages de dialogue Windows, aux
messages de focalisation ou aux messages de changement de taille. Utilisez
ce paramtre si le contrle peut tre utilis comme un contrle ActiveX, de
telle sorte qu'il recevra la notification de ces vnements.

Sachez galement que le constructeur de la classe TControl inclut par dfaut


les options suivants dans ControlStyle : csCaptureMouse, csClickEvents,
csSetCaption et csDoubleClicks. Bien entendu, il vous est toujours possible de
modifier ces valeurs, mais ceci doit uniquement tre fait dans un constructeur.

Introduction C++ Builder

87

Maintenant que nous connaissons la liste des options, intressons nous au type
Set qui permet de les manipuler dans la proprit ControlStyle.
7.4.3.2 Complment sur lutilisation des classes Set
Les classes de type Set ont t ajouts au C++ afin de simuler le type set of
du Pascal utilis pour modliser un ensemble non ordonn de valeurs numriques
distinctes. De telles constructions sont trs pratiques pour modliser les ensembles
doptions, telles que, par exemple, lensemble des boutons prsents sur une bote de
dialogue de Windows.
Pour simplifier, la dclaration de la classe Set est trs similaire :
template<class T, unsigned char valMin, unsigned char valMax>
class Set;

Programme 7.8 dclaration simplifie de la classe Set


o :

T est un type homologue unsigned char, la plupart du temps un type


numr.
valMin et valMax sont les valeurs extrmes autorises pour les lments de
lensemble.

Du fait de lutilisation de valMin et valMax dans le template, deux classes


bases sur le mme type T mais de valeurs extrmes diffrentes ne sont pas
compatibles.
La classe Set est pourvue des mthodes prsentes dans le tableau suivant.
Afin de gagner de la place, le spcificateur __fastcall3 prsent pour chacune des
mthodes nest pas prsent.
Set(void)

Constructeur par dfaut, conoit un ensemble vide

Set(const Set&)

Constructeur par copie

Set &operator=(const Set&)

Affectation brutale

Set &operator *=(const Set& )


Set &operator +=(const Set& )
Set &operator =(const Set& )

Lensemble courant devient respectivement


lintersection, la diffrence ensembliste et la
runion entre lui mme et un autre ensemble
pass en argument

bool operator==(const Set&) const


bool operator!=(const Set&) const

Comparaisons entre ensembles. Seules les


oprations tous lments identiques et son

Ce spcificateur traduit le mcanisme dappel rapide : les paramtres ne sont pas empils
mais placs dans des registres. Ceci permet de gagner un temps considrable lorsque de nombreux
appels sont ncessaires.
3

Introduction C++ Builder

88

oppos sont fournies. Il nest pas prvu de pouvoir


ordonner des ensembles !
bool contains(const T) const

Teste la prsence dun lment dans lensemble

Set & operator<<(const T)

Ajoute un lment dans lensemble

Set & operator>>(const T)

Retire un lment de lensemble. La classe ne


bronche pas si lon tente de retirer un lment non
prsent

Set operator *(const Set& ) const


Set operator +(const Set& ) const
Set operator (const Set& ) const

Ralisent respectivement lintersection, la


diffrence ensembliste et la runion de lensemble
courant et dun autre ensemble pass en argument

Tableau 7.1 Les mthodes de la classe Set


Vous noterez au passage que les gens de chez Borland nont pas du lire Coplien
car ils ont programm de nombreux oprateurs dyadiques en fonction membre ! En
outre, ils savent trs bien manipuler les fonctions externes comme le prouvent les
oprateurs dentres / sorties suivants :
friend ostream& operator <<(ostream& os, const Set& arg);
friend istream& operator >>(istream& is, Set& arg);

Les entres / sorties sur les ensembles sont assez spciales dans le sens o elles
travaillent sur un mapping de la prsence de chaque valeur entre minVal et maxVal
vers [0, 1]. Pour clarifier, si la valeur i est prsente dans lensemble, cela sera signal
par un 1 lemplacement i-minVal dans la suite de 0 et 1 construite par
loprateur <<. Rciproquement loprateur >> construit en ensemble partir dune
suite de 0 et de 1 en ajoutant la valeur correspondant chaque fois quil trouve un 1.
Le code du constructeur du composant Calculette (Programme 7.9) contient
linstruction suivante :
(((ControlStyle >> csAcceptsControls)
>> csSetCaption)
<< csFramed)
<< csOpaque;

Nous y apprenons donc que, par rapport au style standard, notre composant :

Nadmet pas de composants enfants (retrait de csAcceptsControls)


Ne met pas son Caption jour partir de Name (retrait de csSetCaption)
ce qui tombe bien car nous nallons pas lui fournir de proprit Caption
Est entour dun cadre en creux (ajout de csFramed)
Est dessin de la couleur dun bouton (ajout de csOpaque)

Rappelons que par dfaut, il accepte les vnements de la souris (y compris les
doubles clics), et du clavier.
Introduction C++ Builder

89

7.4.3.3 Placer les composants inclus


Il nest malheureusement pas possible dutiliser lditeur de fiche ou un autre
diteur de ressources Windows pour dcrire lemplacement, le titre et autres
caractristiques des composants inclus dans la calculette : toutes ces proprits
doivent tre instancies la main dans le constructeur de la calculette !
En pratique il est agrable dutiliser le concepteur pour raliser une fiche qui a
le mme aspect que le composant que lon souhaite crer pour en dduire les valeurs
gomtriques des composants inclus.
__fastcall TCCBruno::TCCBruno(TComponent* Owner) : TCustomControl(Owner)
{
(((ControlStyle >>
>>
<<
<<

csAcceptsControls)
csSetCaption)
csFramed)
csOpaque;

Style visuel du
composant en cours de
cration

Height=200;
Width=230;
labelFrancs = new TLabel(this);
labelFrancs->Top=10;
labelFrancs->Left=10;
labelFrancs->Caption="Les Francs :";
labelFrancs->Parent=this;

Ajout des diffrents


composants inclus

labelEuros = new TLabel(this);


labelEuros->Top=40;
labelEuros->Left=10;
labelEuros->Caption="Les Euros :";
labelEuros->Parent=this;
labelTaux = new TLabel(this);
labelTaux->Top=70;
labelTaux->Left=10;
labelTaux->Caption="Le taux vaut : "+FloatToStr(Taux);
labelTaux->Parent=this;
saisieFrancs = new TEdit(this);
saisieFrancs->Top=10;
saisieFrancs->Left=100;
saisieFrancs->Text="0";
saisieFrancs->Parent=this;
saisieFrancs->Text=FloatToStr(Francs);
saisieFrancs->OnChange=OnSaisieFrancs;

Affichage des la
proprit Francs

saisieEuros = new TEdit(this);


saisieEuros->Top=40;
saisieEuros->Left=100;
saisieEuros->Text="0";
saisieEuros->Parent=this;
saisieEuros->OnChange=OnSaisieEuros;
saisieEuros->Text=FloatToStr(Euros);
boutonSaisieTaux=new TButton(this);
boutonSaisieTaux->Top=100;
boutonSaisieTaux->Left=40;
boutonSaisieTaux->Caption="Saisie";
boutonSaisieTaux->OnClick=OnClickBoutonSaisieTaux;

Introduction C++ Builder

90

boutonSaisieTaux->Parent=this;
}

Programme 7.9 Constructeur du composant Calculette


Ce code dinstanciation est facile comprendre mais vraiment pnible taper !
Pensez que vous auriez raliser le code entirement de cette manire si les
composants ntaient pas disponibles sur les palettes et dans linspecteur dobjet !
Quelques petites remarques simposent :

Les composants crs ont tous pour propritaire (owner) le composant


courant (paramtre this pass au constructeur).
Le propritaire est dconnect du pre. En effet, si vous naffectez pas la
proprit Parent, votre composant ne saffichera jamais.
Les caractristiques gomtriques ne sont pas toutes fournies : la largeur et
la hauteur des widgets est :

la valeur par dfaut


dduite dautres caractristiques, telles que le Caption dun TLabel
(auquel sassocie la fonte etc.)

7.4.3.4 Publication des proprits caches


La classe TCustomControl nest pas destine tre utilise directement par
les utilisateurs mais bel et bien tre drive comme nous le faisons afin de fournir
des composants utiles.
A ce titre elle est pourvue dun nombre impressionnant de proprits, qui, pour
la plupart sont dclares protected. Autrement dit, elle napparatraient pas dans
linspecteur dobjet des classes drives moins dtre publies par lhritier !
Grce ce mcanisme, seules les proprits utiles pour un composant seront
mises disposition de lutilisateur. Dans notre exemple, nous avons publi les
proprits suivantes :
__published:
__property
__property
__property
__property
__property
__property
__property
__property
__property
__property

Align ;
Ctl3D ;
DragCursor ;
DragMode ;
Enabled ;
ParentCtl3D ;
ParentShowHint ;
PopupMenu ;
ShowHint ;
Visible ;

Programme 7.10 Publication des proprits caches

Introduction C++ Builder

91

En effet, ces proprits sont assez standard et permettent lutilisateur de


position facilement son composant (Align), de lui apporter des enrichissements
(Ctl3D, ParentCtl3D, ShowHint, ParentShowInt) et de spcifier ds la conception
son aptitude recevoir des vnements (Enabled) ou tre visible (Visible).
7.4.3.5 Codage des mthodes daccs en criture aux proprits
Maintenant que nous disposons des contrles daffichage des proprits, il nous
est possible de spcifier du code pour les mthodes daccs en criture des proprits.
En effet, ces dernires ne manqueront pas de mettre jour laffichage du composant
lorsque les sommes ou le taux change. Notons que pour viter tout conflit, lorsque le
taux change, les sommes en Francs et en Euros sont remises zro.
void __fastcall TCCBruno::SetTaux(double value)
{
// Affectation des valeurs aux proprits
FTaux=value;
FEuros=0;
FFrancs=0;

// Mise jour de l'affichage


saisieFrancs->Text=FloatToStr(FFrancs);
saisieEuros->Text=FloatToStr(FEuros);
labelTaux->Caption="Le taux vaut :"+FloatToStr(FTaux);
}
void __fastcall TCCBruno::SetFrancs(double value)
{
// Affectation des valeurs aux proprits
FFrancs = value;
FEuros = FFrancs / FTaux;

// Mise jour de l'affichage


saisieEuros->Text=FloatToStr(FEuros);
saisieFrancs->Text=FloatToStr(FFrancs);
}
void __fastcall TCCBruno::SetEuros(double value)
{
// Affectation des valeurs aux proprits
FEuros = value;
FFrancs = FEuros * FTaux;

// Mise jour de l'affichage


saisieFrancs->Text=FloatToStr(FFrancs);
saisieEuros->Text=FloatToStr(FEuros);
}

Programme 7.11 code dimplmentation des mthodes daccs en criture


aux proprits financires
Quelques remarques simposent (mais si

-) :

Les mthodes daccs aux proprits (que ce soit en lecture ou en criture)


ne sont toujours de type __fastcall ce qui implique en particulier quelles
ne sont jamais inline.

Introduction C++ Builder

92

En effet, il est important que ce soient de vritables mthodes et non pas du


code inline car ces mthodes sont susceptibles dtres appeles via les
mcanismes dOLE.
Rappelons galement que le protocole __fastcall remplace lempilement
traditionnel des paramtres par leur placement dans des registres ce qui
permet de gagner un temps considrable lors de lappel, le mcanisme de
stack call tant, par dfinition, assez lent.

Il faut faire attention ne pas introduire de mcanisme en boucle lors de


lcriture des mthodes daccs en criture. Ainsi, vous remarquerez que les
proprits sont utilises via leur attribut de stockage dans ce type de code.
Ceci est destin viter des mcanismes dappel infini.
En effet, supposez
linstruction :

que

dans la

mthode

SetFrancs,

vous ayez

Euros= ;

Cette ligne aurait pour effet dinvoquer la mthode SetEuros


Et, si, pour couronner lensemble, la mthode SetEuros contient une ligne
du style :
Francs= ;

qui invoque son tour la mthode SetFrancs, on se retrouve dans un


cas de cercle vicieux o chaque mthode passe son temps invoquer lautre !
Moralit : faites bien attention lutilisation des proprits par leurs
mthodes daccs en criture lorsque vous crivez lune dentre elles !

7.4.4 Gestion des vnements internes


Tel quel, notre composant est capable de safficher et dafficher correctement le
taux de conversion ainsi que les sommes passes dans ses proprits lors de la
conception. Toutefois, il nest pas totalement fonctionnel. En effet, il devrait ragir la
frappe de valeurs dans les botes ddition, ce qui revient mettre en place des
mthodes de gestion des vnements OnChange des composants TEdit. Nous parlons
ici dvnements internes car ils mettent en jeu des composants internes notre
Calculette. Un chapitre ultrieur traitera des vnements externes.
La mise en place de gestionnaires dvnements se fait en trois temps :
1. Dclarer une mthode du composant Calculette qui contient le code de
gestion
2. Affecter cette mthode une proprit du composant cens gnrer
lvnement.
3. Implmenter le gestionnaire
Introduction C++ Builder

93

Nous allons dsormais dtailler chacune de ces oprations.


7.4.4.1 Dclaration dun gestionnaire dvnement
Bien entendu, chaque gestionnaire dvnement a une signature particulire
quil va falloir respecter. Le meilleur moyen pour connatre la signature dun
vnement est encore de consulter laide.
Par exemple, si lon dsire grer les changements de texte dun TEdit, on
recherche la rubrique vnements du TEdit et lon choisit OnChange comme le
montre le code suivant :
__property Classes::TNotifyEvent OnChange = {read = FOnChange,
write = FOnChange};

Nous y apprenons que les vnements sont des proprits ( accs direct de
surcrot). On sen doutait un peu car il est possible dassocier un gestionnaire un
vnement lors de la conception.
Poursuivons notre investigation par la lecture de laide associe au type
TNotifyEvent.
typedef void __fastcall (__closure *TNotifyEvent)(System::TObject* Sender);

Comme lon pouvait sy attendre, il sagit dun type pointeur de fonction.


Lorsque la proprit est affecte, la mthode rfrence par le pointeur est appele
lors du dclenchement de lvnement.
Le mot clef __closure est un modificateur interne C++ Builder qui permet
daffecter des pointeurs de mthodes une classe diffrente de celle spcifie. Cette
magouille tait ncessaire pour simplifier le mcanisme daffectation des
proprits. Il nest pas ncessaire de le comprendre pour grer les vnements .

Il suffit de retenir que dans notre cas, la mthode doit avoir le prototype spcifi
par le type TNotifyEvent lexception du __closure, soit :
void __fastcall NomMethode(TObject *Sender);

Programme 7.12 Prototype des vnements de type Notification


La plupart des gestionnaires dvnements rpondent cette signature ; en
particulier tous les gestionnaires de type OnClick. Le paramtre Sender permet
didentifier par son adresse lobjet qui a mis le message. Cest tout particulirement
utile lorsque vous associez le mme code plusieurs objets, par exemple, des boutons
radio dun mme groupe.
Il existe toutefois de nombreux autres types de gestionnaires dvnements, en
particulier, ceux des vnements clavier :
void __fastcall OnKeyDown (TObject* Sender, Word &Key, TShiftState Shift);
void __fastcall OnKeyUp
(TObject* Sender, Word &Key, TShiftState Shift);
void __fastcall OnKeyPress(TObject* Sender, char &Key);

Introduction C++ Builder

94

Programme 7.13 Prototypes des vnements associs au clavier


Examinons plus en dtail ces vnements :
OnKeyDown est gnr lorsquune touche quelconque du clavier est enfonce
OnKeyUp est gnr lorsquune touche quelconque du clavier est relche
Leurs paramtres communs sont :

Sender : adresse du composant metteur de lvnement


Key : code clavier virtuel (gographique

-) de la touche

Shift : paramtre de type Set pouvant contenir trois valeurs associes


aux trois modificateurs du clavier : ssShift, ssCtrl et ssAlt. Leur
prsence dans Shift indique que la touche correspondante du clavier est
enfonce.

OnKeyPress signale quune touche alphanumrique a t active. Ici cest le


caractre correspondant la touche qui est renvoy.
Pour conclure cette section, signalons quil existe de nombreux vnements
associs la souris qui seront plus ou moins disponibles selon le type de composant
OnMouseDown gnr lors de lenfoncement dun des boutons
OnMouseUp gnr lorsque lutilisateur relche un bouton (lequel tait
prcdemment enfonc )

OnClick : gestion dun cycle enfoncement relchement complet


OnDblClick : gestion dun double clic. Notez bien que si vous fournissez une
gestion OnClick et OnDblClick, et quun double clic se produit, OnClick
sera appel avant OnDblClick. Moralit : laction associe un double clic
doit prolonger celle associe un clic simple !
OnMouseMove : gestion des mouvements de la souris.
Une fois les mthodes dclares avec le bon prototype, il ne reste plus qu
crire le code correspondant. Nous donnons ici, titre dexemple, le code associ
lvnement OnChange de la bote ddition de la somme en Francs.
7.4.4.2 Implmentation dun gestionnaire dvnement
void __fastcall TCCBruno::OnSaisieFrancs(TObject *Sender)
{
// Tentative de conversion du texte de la bote dditions en
// valeur numrique
try
{
Francs=StrToFloat(saisieFrancs->Text);
}

Introduction C++ Builder

95

catch (...)
{
// En cas dchec : affichage dun message derreur
ShowMessage("Saisie invalide");
}
}

Programme 7.14 implmentation dun gestionnaire dvnement interne


Bien entendu, ce gestionnaire est simpliste et ne saurait tre adapt
directement une utilisation dans un cas rel. Remarquons quune grande partie du
travail est dlgu la mthode daccs en criture de la proprit Francs. Ce
comportement est assez gnralis, car il permet dviter de la duplication de code. En
effet, saisie dune valeur dans la bote ou laffectation dune valeur par programmation
la proprit Francs sont des fonctionnalits quivalentes qui ncessitent toujours la
mise jour de laffichage du composant.
7.4.4.3 Affectation dun gestionnaire un vnement
Cest la partie la plus simple de notre discours : il suffit daffecter ladresse de la
mthode la proprit responsable de lvnement. Voir ce sujet le code du
constructeur (Programme 7.9).

7.4.5 Ajouter la saisie du taux


Nous dsirons dsormais ajouter la possibilit de saisir un nouveau taux de
change. Pour cela, lutilisateur devra appuyer sur le bouton, ce qui entranera
lapparition dune bote de dialogue lui permettant deffectuer sa saisie.
7.4.5.1 Cration de la bote de dialogue
La bote de dialogue est cre en tant que fiche ordinaire et prsentera laspect
illustr par la Figure 7.12. Veillez ce que le projet courant soit celui associ au
paquet lorsque vous crez la fiche !

Figure 7.12 Bote de saisie du taux de lEuro


7.4.5.2 Utilisation de la bote de dialogue
Il nous faut maintenant utiliser notre nouvelle bote de dialogue lintrieur de
notre composant. Cette tape seffectue de manire classique 2 exceptions prs.

Introduction C++ Builder

96

Tout dabord, vous noterez que le menu Fichier


Inclure Entte dUnit est
dsactiv lorsque vous ditez le code dun composant. Aussi il vous faudra
ajouter la directive #include manuellement, ce qui nest gure compliqu.
Si nous navez pas besoin des dclarations contenues dans le Header de la
classe Bote de Dialogue, je vous conseille de tout positionner dans le .cpp
du composant Calculette de la manire suivante :
#include "CCBruno.h"
#include "UTauxEuro.h"
#pragma link "UTauxEuro.obj"

// Header du composant Calculette


// Header de la bote de dialogue
// Fichier objet de la bote de dialogue

Notez la prsence de la directive pragma link dans le code prcdent.


Cette dernire force le lieur incorporer le fichier fourni en argument dans
lexcutable fourni.
En effet, lorsque vous incorporez un composant dans un projet, par dfaut,
le lieur nincorpore dans lexcutable que le code intrinsque au composant.
Ainsi, dans le cas qui nous intresse, le code de la bote de dialogue ne serait
pas inclus. La directive pragma link pallie ce manque.
Notons quil existait un autre possibilit : ajouter le fichier .cpp de la bote
de dialogue au projet utilisant la Calculette. Cette solution, bien que
correcte du point de vue de ldition de liens souffrait toutefois dun dfaut
majeur : elle ncessite de connatre le nom du fichier source de la bote de
dialogue et par l mme la structure du composant Calculette alors que tout
composant doit tre vu comme une bote noire.

Chaque unit dcrivant une fiche dfinit une variable externe qui est
habituellement cre au lancement de lapplication. Lorsque lon utilise une
fiche uniquement dans le cadre dun composant, cette instance nest pas
cre automatiquement. Aussi, vous devrez le faire vous mme, comme dans
le fragment de code suivant o vous noterez que nous passons au
constructeur de la fiche la variable Application comme composant pre.
Cette variable est dfinie par toute application VCL.

void __fastcall TCCBruno::OnSaisieEuros(TObject *Sender)


{
int resultat;
try
{
FSaisieTaux = new TFSaisieTaux(Application);
FSaisieTaux->editTaux->Text=FloatToStr(FTaux);
resultat=FSaisieTaux->ShowModal();
if (resultat==mrOk)
{
try
{
Taux=StrToFloat(FSaisieTaux->editTaux->Text);
saisieFrancs->Text="0";
saisieEuros->Text="0";
}
// Gestion des erreurs lies la conversion de la chane
// en nombre rel
catch (...)
{

Introduction C++ Builder

97

if (FMemoTrace)
FMemoTrace->Lines->Add("Conversion impossible du taux");
}
}
}
// Rcupre les erreurs inhrentes la cration et lexcution
// de la bote de dialogue
catch (...)
{
if (FMemoTrace)
FMemoTrace->Lines->Add("Erreur lors de la saisie du taux");
}
delete FSaisieTaux;
}

Programme 7.15 Utilisation de la bote de dialogue de saisie du taux de


lEuro

7.5 Exercice rsolu n3 ralisation dun composant de saisie de


date
Le but de cet exercice est de raliser un composant permettant de saisir une
date. Ce dernier aura laspect visuel suivant :
TCSpinEdit de
saisie de l'anne
Bote combo de
saisie du mois

Bote d'dition de rcapitulation de la date


(lecture seulement)

Track Bar de
slection du jour

Label indiquant le nb
de jours du mois
courant

Figure 7.13 Composant de saisie de date


Le composant exporte 4 proprits : Annee, Mois, Jour et Date (lecture seule)
qui contiennent respectivement le numro de lanne indique par le composant, le
numro du mois, le numro du jour ainsi que la date complte compile sous forme
dune chane de caractres.
Comme dans le cas prcdent, les mthodes daccs en criture aux proprits
sont charges de mettre jour les proprits internes des composants inclus. Afin de
faciliter les mises jour, on utilisera une mthode nomme ReconstructionDate et
qui sera charge de mettre jour la valeur compile dans la date dans la bote
ddition idoine.
Introduction C++ Builder

98

Le mode de cration est similaire celui du composant calculette Francs / Euros


un dtail prs : ici il y a un composant Bote Combo et celui-ci ncessite un
traitement prfrentiel.
En effet, il serait tentant de vouloir initialiser le contenu de la bote combo dans
le constructeur du composant. Toutefois, ceci est irrmdiablement sanctionn par une
erreur de violation de mmoire lorsque lon tente de poser le composant sur une fiche.
Aussi, faut-il passer par une astuce.
Rflchissons ensemble, quelle est la premire mthode qui sera appele aprs
le constructeur ? bien videmment, il sagit de Paint afin de mettre jour laspect
visuel du contrle !
Aussi, il nous sera possible de procder des initialisations dans la mthode
Paint. Toutefois, nous ne voulons procder ces initialisations que lors de la
premire invocation de Paint, il tait possible dajouter un attribut boolen servant
de drapeau dans la dfinition de la classe mais nous prfrons utiliser une astuce :
juste aprs sa construction, la bote combo ne contient aucun lment ! aussi, nous
nentrons dans ce code dinitialisation que si cette condition est vrifie.
De manire gnrale, il sera impossible de toucher aux proprits tableau dans
le constructeur du composant. Ceci est spcialement vrai pour toutes les proprits
nommes Lines ou Items.
En outre, le code dinitialisation du composant la date courante (ou une date
quelconque) qui ne pouvait tre fait dans le constructeur toujours cause de cette
maudite bote combo, est galement dplac dans Paint. Vous noterez au passage que
nous utilisons allgrement le fait que Paint est galement appele lorsque lon dpose
un composant sur une fiche.
Finalement, les codes du constructeur et de Paint deviennent :
__fastcall TBrunoDate::TBrunoDate(TComponent* Owner)
: TCustomControl(Owner)
{
// Style du contrle
(((ControlStyle >> csAcceptsControls)
>> csSetCaption)
<< csFramed)
<< csOpaque;
// Proprits gomtriques
Width=675;
Height=250;
// Construction des diffrents contrles
editAnnee=new TCSpinEdit(this);
editAnnee->Parent=this;
editAnnee->Left=16;
editAnnee->Top=8;
editAnnee->MinValue=1980;
editAnnee->MaxValue=2100;
editAnnee->OnChange=OnChangeAnnee;
editDate=new TEdit(this);

Introduction C++ Builder

99

editDate->Parent=this;
editDate->Left=16;
editDate->Top=160;
// On construit normalement la bote combo
// Il faut nanmoins se garder de toucher la proprit Items
comboMois=new TComboBox(this);
comboMois->Parent=this;
comboMois->Left=16;
comboMois->Top=48;
comboMois->Style=csDropDownList;
comboMois->OnChange=OnChangeMois;
tbJour=new TTrackBar(this);
tbJour->Parent=this;
tbJour->Left=16;
tbJour->Top=88;
tbJour->Width=650;
tbJour->Min=1;
tbJour->Max=31;
tbJour->OnChange=OnChangeJour;
labelPremier=new TLabel(this);
labelPremier->Parent=this;
labelPremier->Left=16;
labelPremier->Top=136;
labelPremier->Caption="1";
labelDernier=new TLabel(this);
labelDernier->Parent=this;
labelDernier->Left=650;
labelDernier->Top=136;
}

Programme 7.16 Code du constructeur


void __fastcall TBrunoDate::Paint(void)
{
TCustomControl::Paint();
// Appel de Paint du parent
if (comboMois->Items->Count==0)

// Test sur le nb dlments de


// la bote combo

{
// Remplissage de la bote combo
comboMois->Items->Add("Janvier");
comboMois->Items->Add("Fvrier");
comboMois->Items->Add("Mars");
comboMois->Items->Add("Avril");
comboMois->Items->Add("Mai");
comboMois->Items->Add("Juin");
comboMois->Items->Add("Juillet");
comboMois->Items->Add("Aout");
comboMois->Items->Add("Septembre");
comboMois->Items->Add("Octobre");
comboMois->Items->Add("Novembre");
comboMois->Items->Add("Dcembre");
// Rcupration de la date courante par un appel systme Windows
SYSTEMTIME toutDeSuite;
GetLocalTime(&toutDeSuite);
// Modification des proprits du composant en consquence

Introduction C++ Builder

100

Annee=toutDeSuite.wYear;
Mois=toutDeSuite.wMonth;
Jour=toutDeSuite.wDay;
}
ReconstructionDate(); // Mise jour de la bote ddition
}

Programme 7.17 Code de Paint

7.6 Gestion des vnements externes


Au paragraphe 7.4.4 nous avons vu comment grer des vnements internes
notre composant. Nous allons dsormais nous intresser aux vnements externes cest
dire les vnements fournis par notre composant Calculette lutilisation.

7.6.1 Motivation et mise en uvre


Il est important de fournir des vnements au programmeur qui utilise votre
composant. Le choix des vnements est assez dlicat. En effet, les vnements que
vous publiez doivent faciliter les oprations suivantes :

Obtenir des indications (on parle habituellement de notifications) sur les


oprations subies par le composant, par exemple, lutilisateur modifi la
date courante
Interagir avec lutilisateur final du produit en lui permettant dajouter ses
propres commandes en rponse des vnements standard.

La premire chose savoir est quun vnement est avant tout une proprit de
type closure. Comme nous lavons vu un peu plus haut, ce type est associ des
pointeurs de mthodes dans un objet fiche.
Il existe deux grands types dvnements externes :

Ceux qui sont dj prvus par C++ Builder mais qui sont masqus, il suffira
de les rendre accessibles par le mcanisme de publication des proprits
protected que nous avons dj utilis afin de rendre visibles les proprits
standard des contrles.
Les vnements que vous souhaiterez ajouter vous mme.

Que vous publiiez un vnement standard ou personnalis, il apparatra


toujours dans la page vnements de linspecteur dobjet.

7.6.2 Un exemple simple


Nous allons ajouter trois vnements utilisateur notre composant de saisie de
date.

Le premier consistera rendre visible lvnement standard OnClick

Introduction C++ Builder

101

Les deux autres sont spcifiques au composant de saisie de date et seront


respectivement mis avant et aprs les oprations de changement de date.

Afin de rendre les choses simples, ces deux derniers vnements seront de type
notification : cest dire avec un seul paramtre correspondant lmetteur du
message. On se rfrera au chapitre pour de plus amples renseignements sur les
notifications.
Il faut galement penser donner des noms loquents aux vnements. En
effet, ils doivent clairement indiquer dans quelles circonstances ils seront invoqus.
En outre, la tradition veut que leur nom commence systmatiquement par On. Suivant
ces recommandations, nous appellerons nos vnements OnAvantChangementDate et
OnApresChangementDate.
Leur dclaration obit au code suivant :
class PACKAGE TBrunoDate : public TCustomControl
{
...
// Attributs de stockage des proprits associes aux vnements spcifiques
TNotifyEvent FAvantChangementDate;
TNotifyEvent FApresChangementDate;
...
__published:
// Publication de OnClick auparavant en protected
__property OnClick;
// Publication des deux vnements spcifiques
__property TNotifyEvent OnAvantChangementDate= read = FAvantChangementDate,
write = FAvantChangementDate};
__property TNotifyEvent OnApresChangementDate={read = FApresChangementDate,
write = FApresChangementDate};
...
};

Programme 7.18 Dclaration et publication dvnements utilisateur


Une fois ces dclarations ralises, les vnements apparaissent dans
linspecteur dobjet (comme le montre la figure suivante) et se manipulent exactement
de la mme manire que les vnements associs aux composants standard.
A titre indicatif, le code dvnements trs simple est fourni juste en dessous de
la figure, les diffrentes affichages de la date permettront de vrifier que lvnement
OnAvantChangementDate a bien lieu avant les modifications effectives des proprits
alors que OnApresChangementDate a lieu aprs.

Introduction C++ Builder

102

Evenements et gestionnaires
associs

Composant de
saisie de date

Figure 7.14 Manipulation des vnements externes du composant de saisie


de date
void __fastcall TFPrinci::EvAvant(TObject *Sender)
{
memoTrace->Lines->Add("Attention : la date va changer ! " +
IntToStr(BrunoDate1>Jour)+"/" +
IntToStr(BrunoDate1->Mois)+"/" +
IntToStr(BrunoDate1->Annee));
}
//--------------------------------------------------------------------------void __fastcall TFPrinci::EvApres(TObject *Sender)
{
memoTrace->Lines->Add("Attention : la date a chang ! " +
IntToStr(BrunoDate1>Jour)+"/" +
IntToStr(BrunoDate1->Mois)+"/" +
IntToStr(BrunoDate1->Annee));
}
//--------------------------------------------------------------------------void __fastcall TFPrinci::EvClick(TObject *Sender)
{
memoTrace->Lines->Add("Attention : l'utilisateur clique sur le composant");
}

Programme 7.19 Code associ aux vnements externes du composant de


saisie de date

7.6.3 Prendre en compte les vnements


Maintenant que nous avons permis lutilisateur de fournir ses propres
gestionnaires dvnements, il faut en tenir compte et ce en appelant le gestionnaire
fourni par lutilisateur au moyen de la proprit.
Il ny a jamais se proccuper des vnements standard genre OnClick. En
effet, par dfaut ils appellent des mthodes standard (Click pour OnClick) que vous
avez toutefois la possibilit de surcharger.

Introduction C++ Builder

103

Pour ce qui est des vnements spcifiques, il vous appartient de les activer au
bon moment en appliquant la lettre une rgle dor :
Aucune hypothse ne doit tre faite sur le contenu du gestionnaire fourni par
votre utilisateur.
En particulier, votre code doit fonctionner que lutilisateur fournisse ou non un
gestionnaire pour votre vnement. Aussi, le gestionnaire utilisateur se rajoute au
code par dfaut et ne doit jamais le remplacer. Lappel un gestionnaire utilisateur
doit ressembler :
if (Propriete)
Propriete(arguments)

Programme 7.20 Code gnrique de prise en compte dun gestionnaire


utilisateur
La proprit contenant le gestionnaire est 0 si celui-ci est vide, dans un
deuxime temps, vous utilisez la proprit comme tout pointeur de mthode pour
appeler le code de votre utilisateur en lui fournissant les bons paramtres.
Dans notre cas, il suffit dappeler les gestionnaires dans chaque mthode
associe aux vnements internes de changement des composants comme le montre le
code suivant :
void __fastcall TBrunoDate::OnChangeAnnee(TObject *Sender)
{
if (OnAvantChangementDate)
OnAvantChangementDate(this);
Annee=editAnnee->Value;
if (OnApresChangementDate)
OnApresChangementDate(this);
}
void __fastcall TBrunoDate::OnChangeMois(TObject *Sender)
{
if (OnAvantChangementDate)
OnAvantChangementDate(this);
Mois=comboMois->ItemIndex+1;
if (OnApresChangementDate)
OnApresChangementDate(this);
}
void __fastcall TBrunoDate::OnChangeJour(TObject *Sender)
{
if (OnAvantChangementDate)
OnAvantChangementDate(this);
Jour=tbJour->Position;
if (OnApresChangementDate)
OnApresChangementDate(this);
}

Programme 7.21 Prise encompte des vnments spcifiques


Il est possible dinteragir avec le code de votre utilisateur en utilisant des
paramtres en entre sortie comme le prouve lexercice suivant :
Introduction C++ Builder

104

7.6.4 Exercice : interdire la modification de la date (

Utilisez un argument boolen pour le gestionnaire OnAvantChangementDate


afin de pouvoir interdire la modification de la date. On pourra se rfrer aux
vnements OnBeforeClose.

7.7 Conversion dune bote de dialogue gnrique en composant


La manipulation des botes de dialogue standard de Windows au travers de
composants est particulirement pratique. En effet, elle permet de positionner
facilement des proprits avant excution du dialogue, de rcuprer le code de retour
modal ainsi que des donnes dexcution dans des proprits.

7.7.1 Motivation
Dans cette section, nous allons montrer comment encapsuler une bote de
dialogue dans un composant. Pour cela, nous allons nous appuyer sur lexemple dune
bote de saisie gnrique.
En effet, la plupart des botes de dialogue orientes saisie obissent la
structure suivante :
Titre de la bote
Texte explicatif sur les
donnes taper

Composant bote de
saisie destin la
saisie proprement dite

Boutons standard de
fermeture de la fentre

Figure 7.15 Bote de dialogue de saisie gnrique


Lencapsulation dans un composant prsente les avantages suivants :
Manipulation facilite : il suffira de dposer une icne depuis la palette de
C++ Builder sur une fiche pour utiliser une instance de la bote de dialogue.
Possibilit de spcifier des proprits : Cest sans doute le plus important
car il permettra de personnaliser (je serai tenter de dire customiser )
facilement chaque instance de notre composant, le rendant ainsi agrable
utiliser. Prenons le cas de notre dialogue de saisie, les lments qui devront
tre modifis sont les suivants :

Le titre de la fentre : proprit Caption de la bote de dialogue


Le texte explicatif : proprit Caption dun composant Label de la
bote de dialogue

Introduction C++ Builder

105

Le texte initial de la bote de saisie : proprit Text dun composant


Edit de la bote de dialogue. Cest galement au travers de ce dernier
que vous pourrez rcuprer le rsultat de votre saisie.

Sil est possible de raliser toutes ces oprations relativement facilement, vous
voyez quelles impliquent tout de mme dutiliser des proprits de composants de la
bote ce qui impose de connatre la structure du dialogue.
En crant des proprits dun composant englobant cette bote, vous nauriez
qu connatre ceux-ci. Nous allons donc crer 3 proprits de type texte pour notre
dialogue :

Caption : associ au titre de la bote de dialogue


Label : associ au texte explicatif
Text : associ au texte de la bote de saisie elle mme.

Vous noterez que nous avons respect les conventions habituelles de la VCL sur
les noms des proprits de texte. La figure suivante rcapitule cet tat de fait.
Caption
Label
Text

Figure 7.16 les proprits de notre composant saisie

7.7.2 Fonctionnement de lencapsulation


Considrez les composants associs aux botes de dialogue standard de
Windows. Ils sont tous munis de la mthode bool __fastcall Execute(). Cest
prcisment elle qui ralise la plupart des oprations :
1. Cration de la bote de dialogue sous jacente
2. Mise en place de son aspect visuel grce aux proprits du composant
3. Affichage modal de la bote de dialogue
4. Rcupration du statut de retour modal
5. Modification des proprits du composant en fonction des actions de
lutilisateur sur la bote
6. Destruction de la bote de dialogue et libration des ressources

Introduction C++ Builder

106

Il est trs important de noter que la bote de dialogue sous jacente nest pas
active lors de la conception sur fiche. Le lien avec les proprits du composant nest
ralis que lors de lactivation de la mthode Execute.

7.7.3 Ralisation
La premire opration consiste crer la fiche gnrique comme nimporte
quelle fiche. Veillez toutefois lajouter au projet dans lequel vous allez crer votre
composant. Dans notre cas, nous lajoutons au paquet des exemples et nous nommons
lunit USaisieGenerale.
Comme dordinaire, il convient de crer le composant que nous allons ajouter
la palette et au paquet des exemples pour raison de simplicit. Bien que vous ayez
dsormais lhabitude de cette opration, reprenons ensemble le modus operandi.

Ouvrez le projet associ au paquet des exemples (dclusr35.bpk)


Lancez lexpert composant

Drivez de TComponent
Choisissez la palette exemples
Le nom de classe utilis dans lexemple est TComposantSaisie

Comme dans le cas prcdent dutilisation dune bote de dialogue par le


composant calculette, il est ncessaire dinclure manuellement lentte de la bote de
dialogue et les informations ddition de lien dans le fichier .cpp associ votre
nouveau composant. On retrouvera, par exemple, les lignes :
#include "ComposantSaisie.h"
#include "USaisieGenerale.h"
#pragma link "USaisieGenerale.obj"

Programme 7.22 Mise en place du composant

7.7.4 Mise en place des proprits


Les proprits que nous utilisons sont toutes des chanes de caractres donc
du type AnsiString. En outre ce sont des proprits en accs direct ; en effet,
rappelez vous (section 7.7.2) que la bote de dialogue nest construite quau moment de
lappel de la mthode Execute, laquelle est charge de la mise en place des
proprits, aussi, dans notre cas, il nest point utile de crer des mthodes daccs
compliques. Le code obtenu est le suivant :
private:
AnsiString FTitre;
AnsiString FLabel;
AnsiString FTexte;
__published:
__property AnsiString Caption = {read=FTitre, write=FTitre, stored=true};

Introduction C++ Builder

107

__property AnsiString Label = {read=FLabel, write=FLabel, stored=true};


__property AnsiString Text = {read=FTexte, write=FTexte, stored=true};

Programme 7.23 Cration des proprits du nouveau composant

7.7.5 Codage de la mthode Execute


Comme nous lavons vu au dessus, la mthode Execute est au centre du
processus. Rappelons succinctement quelle va crer la bote de dialogue, mettre en
place laspect visuel au travers de ses proprits, afficher la bote en mode modal,
rcuprer le code de sortie, mettre jour ses proprits en fonction des actions de
lutilisateur avant de dtruire la bote rendant ainsi de prcieuses ressources au
systme.
En outre, elle est souvent responsable des erreurs qui pourraient se produire et
gre les exceptions. Le code suivant traduit cet tat de fait :
bool __fastcall TComposantSaisie::Execute(void)
{
bool resultat;
// Creation de la bote, notez que le parent est l'application
// elle mme
TFSaisieGenerale *boite=new TFSaisieGenerale(Application);
// Mise en place des proprits
boite->Caption=FTitre;
boite->labelEdition->Caption=FLabel;
boite->boiteEdition->Text=FTexte;
// Execution modale et rcupration du rsultat
resultat=(boite->ShowModal()==mrOk);
// Mise jour de la proprit lie la saisie
FTexte=boite->boiteEdition->Text;
// Destruction et libration des ressources
delete boite;
return resultat;
}

Programme 7.24 la mthode Execute

7.8 Ralisation dun composant graphique


Le problme est ici totalement diffrent car lon ne construit plus un composant
capable de recevoir la focalisation. Pour parler plus technique, il ne sagit plus dun
Widget mais bel et bien dun Gadget.
La premire diffrence tient la classe de base. En effet, on ne drivera plus de
TCustomControl mais de TGraphicControl. Notons bien quil tait tout fait
possible de driver de TCustomControl, mais il faut lviter si le composant na pas
besoin de recevoir la focalisation du clavier afin de minimiser le nombre de ressources

Introduction C++ Builder

108

Windows utilises (on peut revoir la section 7.2.2 pour une plus ample discussion ce
sujet).
La principale proccupation du concepteur de composant graphique rside dans
laspect visuel de ce dernier. En effet, contrairement aux composants fentrs dont
ltat est sauvegard par le systme, les composants graphiques ne peuvent compter
que sur leur mthode virtuelle Paint (automatiquement appele par lvnement
Windows ON_PAINT) ainsi que sur un ventuel gestionnaire dvnement OnPaint
fourni par lutilisateur pour mettre jour leur aspect visuel aprs, par exemple, un
redimensionnement de leur zone client ou leur retour au premier plan.

7.8.1 Le composant Affichage de Graphe


Le composant graphique que nous nous proposons de raliser va permettre
dafficher sommairement un graphe partir du nom dun fichier pass en proprit.
Les sommets sont matrialiss par un rond bleu et les arcs (non orients) par
un trait vert.
La figure suivante indique le format dun tel fichier :
Nombre de sommets

5
7
1.0
2.0
1.0
4.0
5.0
0 1
1 2
2 3
3 4
4 0
4 2
3 1

Nombre d'arcs

2.0
4.0
6.0
4.0
2.0

Un sommet : coordonnes x et y

Un arc :index des sommets origine et destination

Figure 7.17 Format dun fichier de graphe

7.8.2 Mise en uvre


Nous allons proposer les proprits suivantes :

Le nombre darcs et le nombre de sommets : entiers (NbSommets et NbArcs)


en lecture seulement
La marge daffichage : espace en pixels (Marge) entre la frontire du
composant et lenveloppe convexe du graphe. Cest un entier en lecture et

Introduction C++ Builder

109

criture. La marge est mise en vidence sur la figure suivante ou le


composant Graphe occupe la zone client dun TPanel.

Le nom du fichier qui contient le graphe : cest une chane ANSI en lecture
et criture (Fichier).

Bien entendu, la majeure partie du travail est accomplie par 2 mthodes :

Laffectation dun nom de fichier (partie write de la proprit Fichier) qui


alloue de lespace mmoire pour stocker les informations relatives au graphe
(coordonnes des sommets, origine et destination de chaque arc)
La mthode Paint daffichage du composant qui est charge de mettre
jour laspect visuel du composant

Enveloppe convexe
(fictive) du graphe

Marge

Panel sur lequel est pos


le composant Graphe

Figure 7.18 Visualisation du composant Graphe

7.9 Exercices supplmentaires


1. Modifier le composant TListBoxCool afin que la proprit Indices
fonctionne
galement
en
criture.
On
distinguera
le
cas
index < SelCount : un lment slectionn est remplac par un autre du
cas index = SelCount un lment est ajout la slection. Quelle autre
modification est elle ncessaire ? (
)

Introduction C++ Builder

110

2. Modifier le composant TListBoxCool pour quil utilise un composant de


stockage pour la proprit Indices. Celui-ci devra tre mis jour lorsquun
utilisateur clique sur la liste. Indication : il faudra redfinir la mthode
WndProc. (
)

3. Modifier le composant Calculette pour quil nutilise pas dattribut de


stockage pour la proprit Euros. ( )

4. Modifier le composant Calculette pour quil utilise TComposantSaisie en


lieu et place de sa bote ddie. Est il toujours ncessaire dutiliser un
pragma link ? ( )

5. Modifier la bote de saisie TSaisieGenerale et le composant


TComposantSaisie pour quils intgrent la notion de masque de saisie et
traitent les exceptions qui y sont lies (
)

Introduction C++ Builder

111

8. En guise de conclusion
Jespre que ce poly (qui ne donne, rappelons-le, quun bref aperu des
nombreuses possibilits offertes par C++ Builder) vous donnera envie dexploiter
fond ce logiciel que, personnellement, japprcie beaucoup bien que regrettant
certaines des fonctionnalits offertes par son anctre Borland C++. Il ne fait aucun
doute quau bout de 6 mois de travail intensif sur cet outil, cest vous qui viendrez me
donner des cours !
Tout retour est videmment le bienvenu et je vous encourage me lenvoyer par
mel : bruno.garcia@lemel.fr ou bruno.garcia@francemel.com .
En outre, jaimerais ddicacer ce travail la promo 1999 de F2 de lISIMA qui a
du se coltiner Borland C++ / OWL en 2me anne puis C++ Builder en 3me anne. Leur
comptence et leur curiosit ma oblig me remettre en cause en permanence et fait
du cours de C++ Builder un dfi permanent (et responsable de nombreuses veilles
tardives). Finalement, leur gentillesse et leur humour a rendu ce cours
particulirement agrable quelques pisodes resteront dfinitivement gravs dans
ma mmoire. Aussi, pour toutes ces raisons, merci, merci Florence, Ashwin, Cedrick,
Chness, Cyril, Didou, Ecom, Elkine, Fonzy, Fred, Fufu, Goontar, Izno, JD, Jrme,
Jesz, Kal, Laurent, Oumph, Rmi, Roubech, Serge, Totov et Ubik.

Introduction C++ Builder

112

Vous aimerez peut-être aussi