Vous êtes sur la page 1sur 112

Introduction C++ Builder

OURS BLANC DES CARPATHES

ISIMA 1988-1999

Introduction C++ Builder 1


Table des matires

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

1.1 UN ENVIRONNEMENT RAD 7


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

2. LENVIRONNEMENT DE DVELOPPEMENT C++ BUILDER 10

LINTERFACE DE C++ BUILDER 10


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

3. ETUDE DE LA VCL 17

3.1 ORGANISATION DE LA VCL 17


3.2 LES COMPOSANTS 17
3.3 LES CONTRLES 18
3.3.1 LES CONTRLES FENTRS 18
3.3.2 LES CONTRLES GRAPHIQUES 19
3.4 LES BOTES DE DIALOGUE STANDARD DE WINDOWS 19
3.4.1 LES BOTES DE DIALOGUE DE MANIPULATION DE FICHIERS 20
3.4.2 LA BOTE DE SLECTION DE COULEURS 22
3.4.3 LA BOTE DE SLECTION DE FONTE 23
3.4.4 LES BOTES DE RECHERCHE ET RECHERCHE / REMPLACEMENT 23
3.4.5
EXERCICE SUR LES BOTES DE DIALOGUE COMMUNES ( ) 24
3.5 LES BOTES COMBO 25
3.5.1
EXERCICE RSOLU N1 ( ) 27
3.5.2 EXERCICE RSOLU N2 ( ) 28
3.5.3 EXERCICE RSOLU N3 ( ) 29
3.5.4 EXERCICE N4 ( ) 31
3.6 LES MENUS 31
3.6.1 MISE EN PLACE DUN MENU PRINCIPAL 31
3.6.2 LDITEUR DE MENUS 32
3.6.3 LUTILISATION DES MENUS 35
3.6.4 UN EXEMPLE DE MODIFICATION PAR PROGRAMMATION : LA LISTE DES DERNIERS FICHIERS
OUVERTS 35
3.6.5 LES MENUS SURGISSANTS 37
3.7 LES BOTES DROULANTES 37
3.7.1 GNRALITS 37

Introduction C++ Builder 2


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

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

4.1 MISE EN PLACE DE LA BASE DE DONNES 44


4.1.1 LOUTIL ADMINISTRATEUR BDE 44
4.1.2 CRATION DE LALIAS 45
4.2 ACCS AUX DONNES DANS C++ BUILDER 47
4.3 LES CONTRLES ORIENTS BASES DE DONNES 50
4.3.1 PRSENTATION TABULAIRE DUNE TABLE OU DUNE REQUTE 51
4.3.2 LES AUTRES CONTRLES 53
4.4 MANIPULATIONS LMENTAIRES SUR LES BASES DE DONNES 53
4.4.1 RALISATION DE JONCTIONS 54
4.4.2 LE FILTRAGE 56
4.4.3 CRATION DE FICHES MATRE / DTAIL 56
4.4.4 AJOUT DUN TUPLE DANS UNE OU PLUSIEURS TABLE 58

5. UTILISATION DU MODULE DE BASES DE DONNES 61

5.1 LE MODULE DE BASES DE DONNES 61


5.2 PRSENTATION DE LINTERFACE 61
5.3 AJOUT DE CHAMPS 63
5.3.1 LE NOM 63
5.3.2 LE TYPE 63
5.3.3 LA TAILLE 64
5.3.4 LA PRSENCE DANS LA CLEF PRIMAIRE 64
5.4 DFINIR DES INDEX SECONDAIRES 64

6. UTILISATION DES CONTRLES ACTIVEX 66

6.1 MISE EN PLACE 66


6.1.1 EDITION DE LA LISTE DES CONTRLES DISPONIBLES 66
6.1.2 RECENSEMENT DANS LA BASE DE REGISTRES DUN NOUVEAU COMPOSANT 67
6.1.3 CRATION DUNE UNIT 68
6.2 UTILISATION DUN CONTRLE ACTIVEX 69
6.3 DPLOIEMENT DUN PROGRAMME UTILISANT UN CONTRLE ACTIVEX 70

7. LCRITURE DE NOUVEAUX COMPOSANTS 71

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

Introduction C++ Builder 3


7.3.1 MOTIVATION ET DROULEMENT GNRAL DE LEXERCICE 76
7.3.2 MISE EN PLACE 77
7.3.3 UTILISATION DU COMPOSANT 83
7.3.4 UTILISATION DUN COMPOSANT NON INSTALL SUR LA PALETTE 83
7.4 EXERCICE RSOLU N2 : LA CALCULETTE FRANCS EUROS 83
7.4.1 CRER LE COMPOSANT 84
7.4.2 CRER DES PROPRITS 84
7.4.3 GRER LASPECT VISUEL DU COMPOSANT 86
7.4.4 GESTION DES VNEMENTS INTERNES 93
7.4.5 AJOUTER LA SAISIE DU TAUX 96
7.5 EXERCICE RSOLU N3 RALISATION DUN COMPOSANT DE SAISIE DE DATE 98
7.6 GESTION DES VNEMENTS EXTERNES 101
7.6.1 MOTIVATION ET MISE EN UVRE 101
7.6.2 UN EXEMPLE SIMPLE 101
7.6.3 PRENDRE EN COMPTE LES VNEMENTS 103
7.6.4
EXERCICE : INTERDIRE LA MODIFICATION DE LA DATE ( ) 105
7.7 CONVERSION DUNE BOTE DE DIALOGUE GNRIQUE EN COMPOSANT 105
7.7.1 MOTIVATION 105
7.7.2 FONCTIONNEMENT DE LENCAPSULATION 106
7.7.3 RALISATION 107
7.7.4 MISE EN PLACE DES PROPRITS 107
7.7.5 CODAGE DE LA MTHODE EXECUTE 108
7.8 RALISATION DUN COMPOSANT GRAPHIQUE 108
7.8.1 LE COMPOSANT AFFICHAGE DE GRAPHE 109
7.8.2 MISE EN UVRE 109
7.9 EXERCICES SUPPLMENTAIRES 110

8. EN GUISE DE CONCLUSION 112

Introduction C++ Builder 4


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 5


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 6


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 7


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 8


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 9


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 Palette de composants
Palette doutils de composants active

Inspecteur dobjets Code associ aux Fentre dinterface en


lments dinterface 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.
Nom de la
Liste des vnements mthode
disponibles associe cet
vnement

Objet TImage
slectionn
Liste de mthodes que
lon pourrait affecter
lvnement

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.

1En 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.

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
spcialise
Ouverture dans les Slection Recherche
de fichier fichiers d'images de couleur Impression de texte

Sauvegarde Sauvegarde Slection Configuration Recherche/


de fichier spcialise de police de l'impression Remplacement
dans les
fichiers d'images

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 mrAbort


mrRetry mrIgnore mrYes

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
Icne de la
dfaut des
bote sur
fichiers
une fiche
rechercher

Filtre
Rpertoire d'ouverture
initial
l'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
Extensions
description
associes
du filtre

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 Icne de la
l'utilisateur 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
Icne de la bote de
slection de police
Nom de la 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 Diffrentes botes de dialogue


d'appeler les botes 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
VertScrollBar->Range
Height

Partie visible
Etendue
Virtuelle

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
Composant TMemo de trace
TScrollBox

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 mode


Configuration . La slection porte sur un pilote de bases de donnes natif.
ouvrir Annuler les Revenir en Prendre en
une base modifs arrire 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

Fentre d'affichage des


Liste des pilotes paramtres concernant la
ODBC (dpend slection dans le volet de
de l'installation gauche
de Windows)

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.

Pour crer un nouvel alias, slectionnez Objet Nouveau dans le menu


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 Slection du type pour un


dj prsents 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 Slection du rpertoire de Vrifiez la prsence de


Alias donnes 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 Science-


fiction. 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 Composant TTable pos sur
liste droulante le module de donnes
donne accs
tous les alias
disponibles

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 Seconde source de donnes


Son nom semble indiquer qu'elle est destine une connecte la table des
prsentation tabulaire des donnes 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
Dernier tuple modifications

Tuple prcdent Supprimer le


tuple courant

Aller au Rafrachir les


premier tuple donnes

Ajouter un tuple Annuler les modifications

Tuple suivant 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 Vocabulaire et commande C++ Builder


relationnelle

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) Nom (proprit Name) du
des donnes 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 Champ de type Table sur laquelle on
(clef trangre) rfrence, i.e. jonction effectue la jonction

Champ de jonction dans la Champ rsultat de la jonction (dans la


table externe (clef primaire) 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 Index sur le champ de Champ de la table matre
lequel va s'effectuer la jonction de la table sur lequel va s'effectuer
jonction esclave 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. Champs dj prsents
Les champs griss sont dans lindex
dj dans lindex

Boutons permettant de
modifier lordre des
Boutons dajout ou de champs dans lindex
suppression de 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

Rpertoire de cration
Palette dinstallation du des units associes aux
composant 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

2En 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.

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
Nom de classe choisi pour Classe dont va driver
le nouveau composant le nouveau composant

Palette dinstallation
Chemin utilis par
C++ Builder lors de la
Emplacement et nom des recherche du source
fichiers .h et .cpp gnrs des composants

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
oui non
d'un composant existant ?

Driver du
composant
spcialiser ou de
sa forme abstraite
oui Composant visuel ?
non

Destin recevoir la Driver de


focalisation ? TComponent
oui non

Driver de Driver de
TWinControl 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

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


i me 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 ! (Projetconstruire 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 Fond du composant


spcifiques sur lequel sont greffs
au nouveau les widgets
composant

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 Euros


Introduction C++ Builder 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 void SetTaux (double value);
__fastcall void SetFrancs (double value);
__fastcall void SetEuros (double value);

__published:
__property double Taux = {read = FTaux,
write = SetTaux,
default = 6,
stored = true};
__property double Francs = {read = FFrancs,
write = SetFrancs,
default = 0,
stored = true};
__property double Euros = {read = FEuros,
write = SetEuros,
default =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 au-
dessus 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& )
Lensemble courant devient respectivement
Set &operator =(const Set& ) 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

3 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.

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
Ralisent respectivement lintersection, la
Set operator (const Set& ) const 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) Style visuel du


>> csSetCaption) composant en cours de
<< csFramed) cration
<< csOpaque;

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

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; Affichage des la
saisieFrancs->Text="0"; proprit Francs
saisieFrancs->Parent=this;
saisieFrancs->Text=FloatToStr(Francs);
saisieFrancs->OnChange=OnSaisieFrancs;

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 Align ;
__property Ctl3D ;
__property DragCursor ;
__property DragMode ;
__property Enabled ;
__property ParentCtl3D ;
__property ParentShowHint ;
__property PopupMenu ;
__property ShowHint ;
__property 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 que dans la mthode SetFrancs, vous ayez


linstruction :

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" // Header du composant Calculette


#include "UTauxEuro.h" // Header de la bote de dialogue
#pragma link "UTauxEuro.obj" // 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 Track Bar de
slection du jour

Label indiquant le nb
Bote d'dition de rcapitulation de la date
(lecture seulement) 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 Composant de
associs 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 Composant bote de


donnes taper 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 Nombre d'arcs
7
1.0 2.0
2.0 4.0 Un sommet : coordonnes x et y
1.0 6.0
4.0 4.0
5.0 2.0
0 1 Un arc :index des sommets origine et destination
1 2
2 3
3 4
4 0
4 2
3 1

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 Panel sur lequel est pos


(fictive) du graphe Marge 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