Vous êtes sur la page 1sur 112

Introduction C++ Builder

OURS BLANC DES CARPATHES

ISIMA 1988-1999

Introduction C++ Builder

Table des matires


1. C++ BUILDER : UN ENVIRONNEMENT RAD BAS SUR C++ 1.1 UN ENVIRONNEMENT RAD 1.1.1 PHILOSOPHIE 1.1.2 LIMITATIONS 1.2 C++ BUILDER VIS VIS DE LA CONCURRENCE 1.2.1 C++ BUILDER VS DELPHI O LES FRRES ENNEMIS ! 1.2.2 DIFFRENCES PAR RAPPORT BORLAND C++ 1.2.3 C++ BUILDER CONTRE VB 1.3 POUR CONCLURE 2. LENVIRONNEMENT DE DVELOPPEMENT C++ BUILDER LINTERFACE DE C++ BUILDER 2.2 LES COMPOSANTES DE C++ BUILDER 2.3 CRATION DUNE APPLICATION SIMPLE C++ BUILDER 2.4 LINSPECTEUR DOBJETS ET LES PROPRITS 2.5 LA PROPRIT NAME 2.6 MANIPULER LES VNEMENTS 2.7 C++ BUILDER ET LES EXCEPTIONS 2.8 UTILISEZ LA FENTRE DHISTORIQUE ! 3. ETUDE DE LA VCL 3.1 3.2 3.3 3.3.1 3.3.2 3.4 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.6 3.6.1 3.6.2 3.6.3 3.6.4 ORGANISATION DE LA VCL LES COMPOSANTS LES CONTRLES LES CONTRLES FENTRS LES CONTRLES GRAPHIQUES LES BOTES DE DIALOGUE STANDARD DE WINDOWS LES BOTES DE DIALOGUE DE MANIPULATION DE FICHIERS LA BOTE DE SLECTION DE COULEURS LA BOTE DE SLECTION DE FONTE LES BOTES DE RECHERCHE ET RECHERCHE / REMPLACEMENT EXERCICE SUR LES BOTES DE DIALOGUE COMMUNES ( ) LES BOTES COMBO EXERCICE RSOLU N1 ( ) ) EXERCICE RSOLU N2 ( ) EXERCICE RSOLU N3 ( ) EXERCICE N4 ( LES MENUS MISE EN PLACE DUN MENU PRINCIPAL LDITEUR DE MENUS LUTILISATION DES MENUS UN EXEMPLE DE MODIFICATION PAR PROGRAMMATION : LA LISTE DES DERNIERS FICHIERS OUVERTS 35 3.6.5 LES MENUS SURGISSANTS 3.7 LES BOTES DROULANTES 3.7.1 GNRALITS 7 7 7 7 8 8 8 9 9 10 10 11 11 12 12 13 14 15 17 17 17 18 18 19 19 20 22 23 23 24 25 27 28 29 31 31 31 32 35

[[[

[ [[ [[

37 37 37

Introduction C++ Builder

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

[[[)

[[

38 38 40 40 41 42 42 42 44 44 44 45 47 50 51 53 53 54 56 56 58 61 61 61 63 63 63 64 64 64 66 66 66 67 68 69 70 71 71 71 72 74 76

4. UTILISATION MINIMALISTE DES BASES DE DONNES AVEC C++ BUILDER 4.1 4.1.1 4.1.2 4.2 4.3 4.3.1 4.3.2 4.4 4.4.1 4.4.2 4.4.3 4.4.4 MISE EN PLACE DE LA BASE DE DONNES LOUTIL ADMINISTRATEUR BDE CRATION DE LALIAS ACCS AUX DONNES DANS C++ BUILDER LES CONTRLES ORIENTS BASES DE DONNES PRSENTATION TABULAIRE DUNE TABLE OU DUNE REQUTE LES AUTRES CONTRLES MANIPULATIONS LMENTAIRES SUR LES BASES DE DONNES RALISATION DE JONCTIONS LE FILTRAGE CRATION DE FICHES MATRE / DTAIL AJOUT DUN TUPLE DANS UNE OU PLUSIEURS TABLE

5. UTILISATION DU MODULE DE BASES DE DONNES 5.1 5.2 5.3 5.3.1 5.3.2 5.3.3 5.3.4 5.4 LE MODULE DE BASES DE DONNES PRSENTATION DE LINTERFACE AJOUT DE CHAMPS LE NOM LE TYPE LA TAILLE LA PRSENCE DANS LA CLEF PRIMAIRE DFINIR DES INDEX SECONDAIRES

6. UTILISATION DES CONTRLES ACTIVEX 6.1 MISE EN PLACE 6.1.1 EDITION DE LA LISTE DES CONTRLES DISPONIBLES 6.1.2 RECENSEMENT DANS LA BASE DE REGISTRES DUN NOUVEAU COMPOSANT 6.1.3 CRATION DUNE UNIT 6.2 UTILISATION DUN CONTRLE ACTIVEX 6.3 DPLOIEMENT DUN PROGRAMME UTILISANT UN CONTRLE ACTIVEX 7. LCRITURE DE NOUVEAUX COMPOSANTS 7.1 GNRALITS 7.2 CRATION DUN NOUVEAU COMPOSANT 7.2.1 LEXPERT COMPOSANT 7.2.2 DE QUEL COMPOSANT DRIVER ? 7.3 EXERCICE RSOLU : CRATION DU COMPOSANT TLISTBOXCOOL

Introduction C++ Builder

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

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

[[

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

8. EN GUISE DE CONCLUSION

Introduction C++ Builder

Table des illustrations


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

Introduction C++ Builder

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

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

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

Introduction C++ Builder

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


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

1.1 Un environnement RAD 1.1.1 Philosophie


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

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

Inspecteur dobjets

Code associ aux lments dinterface

Fentre dinterface en cours de composition

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

La classique barre de menu La barre doutils qui se dcompose en 2 grandes parties :

La palette doutils permettant deffectuer les oprations les plus courantes (sauvegarde, ouverture de fentres, etc.) Les palettes de composants disposes accessibles par des onglets 10

Introduction C++ Builder

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: br : cc : pl :

bouton daction bouton radio case cocher panel

lb : gb : edit : me :

label bote de groupe bote ddition mmo

Tableau 2.1 Quelques prfixes de nommage pour les composants VCL

2.6 Manipuler les vnements


La manipulation des vnements est quelque peu plus complexe. La figure suivante illustre quelques principes.
Liste des vnements disponibles Nom de la mthode associe cet vnement

Liste de mthodes que lon pourrait affecter lvnement

Objet TImage slectionn

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

Introduction C++ Builder

13

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

Les positions de la souris Ltat des touches de modification du clavier

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

2.7 C++ Builder et les exceptions


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

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

En plus de fournir de nombreuses options de configuration du dbogueur, cette page nous permet de spcifier le comportement des exceptions lorsquun programme C++ Builder est lanc depuis lEDI.

Introduction C++ Builder

14

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

Option activer pour viter lEDI nintercepte les exceptions que vous grez

Indique si, la sortie de la fentre de lEDI, lexception est gre ou non

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

2.8 Utilisez la fentre dhistorique !


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

Introduction C++ Builder

15

Figure 2.6 Options de la fentre dhistorique Deux grands types doptions sont grables :

La taille de lhistorique

Illimit Nombre de lignes spcifiable par lutilisateur

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

) Le rcepteur du message ) Les paramtres (WPARAM et LPARAM)


Attention, si ce comportement peut se rvler trs pratique, il peut crer des traces normes. En effet, on imagine rarement le volume considrable de messages traits par les applications Windows.

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

Introduction C++ Builder

16

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

3.2 Les composants


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

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

Introduction C++ Builder

17

3.3 Les Contrles


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

Les contrles fentrs Les contrles graphiques

3.3.1 Les contrles fentrs


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

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

Leur tat visuel est sauvegard par le systme. Lorsquils redeviennent visibles, leur apparence est restaure automatiquement sans que le programmeur nait sen soucier. Consquence ngative : il est plus lent de dessiner dans un contrle fentr que dans un contrle graphique.

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

Introduction C++ Builder

18

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

3.3.2 Les contrles graphiques


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

3.4 Les botes de dialogue standard de Windows


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

Introduction C++ Builder

19

Ouverture de fichier

Ouverture spcialise dans les fichiers d'images

Slection de couleur

Impression

Recherche de texte

Sauvegarde de fichier

Sauvegarde spcialise dans les fichiers d'images

Slection de police

Configuration de l'impression

Recherche/ Remplacement

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

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

3.4.1 Les botes de dialogue de manipulation de fichiers


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

Introduction C++ Builder

20

Extension par dfaut des fichiers rechercher

Icne de la bote sur une fiche

Rpertoire initial l'ouverture Titre de la bote de dialogue

Filtre d'ouverture

Figure 3.2 Proprits des dialogues orients fichier Quelques proprits mritent plus ample discussion :

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

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

Nom et description du filtre

Extensions associes

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

Introduction C++ Builder

21

3.4.2 La bote de slection de couleurs


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

Couleur initiale puis slection de l'utilisateur Dfinitions des couleurs utilisateur

Icne de la bote sur une fiche

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 24

Introduction C++ Builder

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

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

Changement de couleur (bote de slection de couleurs) Changement de police (bote de slection de fonte)

Effectuer des recherches et des oprations de recherche / remplacement grce aux botes idoines. Quitter lapplication !

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

) :

Proposer de sauvegarder le texte sil a t modifi par des oprations de recherche / remplacement ou par une saisie utilisateur avant den charger un nouveau ou de quitter lapplication (lvnement OnCloseQuery de la fiche est considrer). Solution partielle La figure suivante illustre laspect de linterface construire :
Menu principal permettant d'appeler les botes Diffrentes botes de dialogue permettant de modifier le texte

Composant TRichEdit sur lequel appliquer les modifications

Figure 3.7 Interface de lexercice sur les botes de dialogue

3.5 Les botes combo


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

Introduction C++ Builder

25

La zone ddition ne peut pas avoir de masque de saisie La bote de liste est slection simple

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

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

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

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

3.5.1 Exercice rsolu n1 ( )


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

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

Notez lutilisation de lexception EConvertError qui est lance chaque conversion rate. La proprit Message contient un message derreur utile des fins de diagnostique.

Introduction C++ Builder

27

La classe AnsiString contient des mthodes ToInt et ToDouble que lon peut utiliser en lieu et place des fonctions de conversion StrToInt, et StrToFloat.

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

3.5.2 Exercice rsolu n2 (


Enonc

[[)

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

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

Introduction C++ Builder

28

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

Programme 3.2 Affichage de styles de traits dans une bote combo Commentaires : Etudions les paramtres du gestionnaire OnDrawItem :

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

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

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

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

3.5.3 Exercice rsolu n3 (


Enonc

[[)

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

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

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

Introduction C++ Builder

30

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

3.5.4 Exercice n4 (

[[[)

Etendre la liste de lexercice n1 de manire ce que les 4 derniers lments entrs soient prcds dun point noir. On utilisera la mthode TextOut de TCanvas pour afficher un texte.

3.6 Les menus


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

3.6.1 Mise en place dun menu principal

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

3.6.2 Lditeur de menus


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

Raccourci clavier associ au menu

Emplacement du prochain lment vertical

Figure 3.9 Le concepteur (ou diteur) de menus Quelques petites indications simposent :

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

Introduction C++ Builder

32

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

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

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

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

Figure 3.11 Les modles de menus

Introduction C++ Builder

33

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

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

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

Introduction C++ Builder

34

3.6.3 Lutilisation des menus


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

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

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

Afin dobtenir ce que nous dsirons, il est possible dutiliser la squence dinstructions : 1. Nous commenons par rserver les emplacements ncessaires comme le montre la figure suivante :

Quatre emplacements vides et un sparateur sont rservs

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

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

un tableau de 4 TMenuItem qui sera affect aux adresses des 4 lments dans le constructeur une variable entire indiquant le nombre dlments prsents dans la liste

4. Il ne reste plus qu rendre visibles les lments et leur affecter le bon Caption. Lexemple qui suit remplit tout simplement cette liste grce un bouton et une zone ddition.
// Variables affectes individuellement aux lments de menu // destins la liste des derniers fichiers ouverts TMenuItem *MenuFich1; TMenuItem *MenuFich2; TMenuItem *MenuFich3; TMenuItem *MenuFich4; private: // Dclarations de l'utilisateur // Dclaration d'une constante indiquant le nombre d'lments de la liste enum {NB_FICHIERS=4}; // Tableau permettant de manipuler facilement les lments de menu // destins la liste des derniers fichiers ouverts TMenuItem *MenuFichiers[NB_FICHIERS]; // Variable comptant le nombre d'lments prsents int nbFichiers;

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

Introduction C++ Builder

36

nbFichiers%=NB_FICHIERS; }

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

3.6.5 Les menus surgissants


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

3.7 Les botes droulantes


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

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

VertScrollBar->Range

Figure 3.15 Partie visible et tendue virtuelle dun TScrollBox Introduction C++ Builder 37

Height

Partie visible Etendue Virtuelle

HorzScrollBar->Range

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 Min Max Frequency

Valeur du curseur Valeur minimale du curseur, associe la position tout gauche Valeur maximale du curseur, associe la position tout droite Nombre dunits sparant deux graduations sur la rgle Tableau 3.2 Quelques proprits du contrle TTrackBar

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

Composant TScrollBox

Composant TMemo de trace

Composant TTrackBar responsable des changements de facteur de zoom

Figure 3.16 Utilisation dune TScrollBox pour le problme du dessin Zoomer Vous pouvez suivre les instructions suivantes :

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

Introduction C++ Builder

39

Parent : identificateur de la TScrollBox, gre laxe Z Width et Height : taille de limage afficher Top et Left : positionns zro

Afficher le dessin

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

) :

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

3.8 Les ascenseurs simples 3.8.1 Gnralits


Les ascenseurs simples sont encapsuls dans le composant TScrollBar (palette standard). Une valeur numrique indiquant la position de leur curseur au sein de leur tendue leur est associe : Leurs proprits fondamentales sont les suivantes : Min Max Position Kind Valeur minimale de ltendue du curseur Valeur maximale de ltendue du curseur Valeur courante du curseur Spcifie si lascenseur est horizontal (valeur sbHorizontal) ou vertical (sbVertical) Valeur dincrmentation du curseur lorsque lutilisateur utilise les flches. Valeur dincrmentation du curseur lorsque lutilisateur clique dans la barre dascenseur ou utilise PgUp ou PgDown 40

SmallChange

LargeChange

Introduction C++ Builder

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

La figure suivante montre laspect typique de cet outil en Configuration . La slection porte sur un pilote de bases de donnes natif.
ouvrir une base Annuler les modifs Revenir en arrire Prendre en compte les modifs

Onglets de slection du mode Liste des alias ou Configuration

Liste des pilotes natifs (dpend de l'installation de C++ Builder et ses Add ons Fentre d'affichage des paramtres concernant la slection dans le volet de gauche

Liste des pilotes ODBC (dpend de l'installation 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 45

Introduction C++ Builder

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 dj prsents Slection du type pour un nouvel alias

Figure 4.2 Slection du type de la base de donnes

Une fois le type choisi, il vous reste remplir diverses rubriques concernant votre nouvelle base, comme le montre la figure suivante :
Nom du nouvel Alias Slection du rpertoire de donnes Vrifiez la prsence de vos fichiers ici !

Figure 4.3 Slection du nom de lalias et du chemin des donnes Introduction C++ Builder 46

Vous devez renseigner absolument :

Le nom de lalias (le nom par dfaut est pouvantable Le chemin des donnes

-)

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

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

4.2 Accs aux donnes dans C++ Builder


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

La base choisie comme exemple regroupe trois relations :

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

Introduction C++ Builder

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

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

Composant TTable pos sur le module de donnes

Ici, il est possible de spcifier un index diffrent de la clef primaire

Liste des tables disponibles. Apparat une fois l'alias slectionn Nom de la table associe au composant

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

Introduction C++ Builder

48

Les principales proprits de TTable sont les suivants :

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

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

Il est possible dinclure dautres composants non visuels dans un module de donnes. Nous citerons en particulier :

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

Introduction C++ Builder

49

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

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

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

Figure 4.5 Les composants TDataSource

4.3 Les contrles orients bases de donnes


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

Introduction C++ Builder

50

4.3.1 Prsentation tabulaire dune table ou dune requte


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

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

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

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

Donnes sous forme tabulaire

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

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

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

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

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

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

Introduction C++ Builder

52

4.3.2 Les autres contrles


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

Dernier tuple Tuple prcdent

Aller au premier tuple

Ajouter un tuple Tuple suivant

Annuler les modifications Modifier les donnes

4.4 Manipulations lmentaires sur les bases de donnes


C++ Builder autorise en direct quelques opration lmentaires de lalgbre relationnelle, savoir : Opration dalgbre relationnelle Jonction Slection Projection Vocabulaire et commande C++ Builder

Ajout de champ Rfrence dans un ensemble de donnes Filtrage ou cration de relations Matre / Dtail Cration de colonnes statiques et suppression des champs non dsirs dans les TDBGrid (dj vu)

Tableau 4.1 Correspondance entre oprations dalgbre relationnel et oprations C++ Builder

Introduction C++ Builder

53

4.4.1 Ralisation de jonctions


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

Ajouter champs permet dajouter dans la liste des champs statiques un champ de donn prsent dans la structure du TDataSet. Nouveau champ permet dajouter un nouveau champ par jonction ou calcul.

Prcisons immdiatement que nous aurons le droit dajouter plusieurs types de champs.

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

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

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


Taille (ventuelle) des donnes Nom (proprit Name) du composant TField cr

Nom du champ nouvellement cr

Slection du type de donnes du champ cr

Figure 4.8 cration dun champ de donnes Les premires spcifications apporter sont :

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

Continuons notre jonction en choisissant de crer un champ rfrence. Le rsultat de la manipulation est illustr par la figure suivante :
Champ de jonction dans la table courante (clef trangre) Champ de type rfrence, i.e. jonction Table sur laquelle on effectue la jonction

Champ de jonction dans la table externe (clef primaire)

Champ rsultat de la jonction (dans la table externe choisie ci-dessus)

Figure 4.9 Ralisation dune jonction : tape 2 Introduction C++ Builder 55

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

Le champ nouvellement cr peut alors se traiter comme sil avait toujours appartenu la table (champ endogne) quelques exceptions prs, comme, par exemple, les oprations de filtrage. Exercice (vident): Raliser la mme opration pour le nom de lditeur.

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

4.4.3 Cration de fiches Matre / Dtail


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

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

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

Introduction C++ Builder

56

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

Prparation de la visualisation de la relation matre / esclave

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

Mise en place de la relation Matre / Dtail. Celle-ci se fait essentiellement sur les proprits de la table esclave

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

Choisir un index de assoc pour obtenir le champ joint ct esclave, ici TITRE qui dnote un numro duvre. Notez au passage que les relations matre / esclave ne peuvent avoir lieu sans indexation correcte de la table esclave.

Y Y

Choisir le champ de jointure ct uvres dans la case de droite, ici NUMERO qui rfrence le numro de luvre (clef primaire) Cliquer sur Ajouter , le tour est jou !

Introduction C++ Builder

57

Les figures suivantes illustrent en deux tapes la cration de la liaison matre / esclave aussi nomme matre / dtails.
Champ de l'index sur lequel va s'effectuer la jonction Index sur le champ de jonction de la table esclave Champ de la table matre sur lequel va s'effectuer la jonction

La proprit MasterSource pointe sur une DataSource associe la table Matre

Figure 4.10 Cration dune liaison Matre / Dtail : Mise en place Appuyer sur le bouton Ajouter ajoute le couple slectionn la liste des champs de jointure qui peut compter jusqu 16 couples !

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

Figure 4.11 Fin de cration dune liaison Matre / Dtail

4.4.4 Ajout dun tuple dans une ou plusieurs table


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

Introduction C++ Builder

58

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

Il est possible de saisir librement le titre de luvre et le nom de lauteur, ce qui se fera par lintermdiaire de simples composants TEdit.

Si lauteur est dj prsent dans la base auteur , alors son numro est extrait de cette dernire et incorpor dans uvre Sinon, un nouvel auteur est rajout dans auteur avant que son numro ne soit ajout uvre

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

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

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

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

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

Les mthodes Post et Cancel de TTable permettent respectivement dappliquer des changements ou de les annuler. Exercice : (

Rajouter la possibilit davoir plusieurs auteurs.

Introduction C++ Builder

60

5. Utilisation du Module de Bases de Donnes


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

5.2 Prsentation de linterface


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

Table Nouveau

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

Figure 5.1 Liste des formats disponibles en cration de table Une fois le type de table slectionn, le MDD vous affiche sa fentre principale telle quelle est prsente par la figure suivante :

Introduction C++ Builder

61

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

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

Introduction C++ Builder

62

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

5.3 Ajout de champs


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

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

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

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

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

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

5.3.4 La prsence dans la clef primaire


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

Figure 5.5 la case Index

5.4 Dfinir des index secondaires


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

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

Introduction C++ Builder

64

La fentre suivante est associe aux oprations dajout ou de modification dindex secondaire.
Liste des champs de la table. Les champs griss sont dj dans lindex Champs dj prsents dans lindex

Boutons dajout ou de suppression de champs dans lindex

Boutons permettant de modifier lordre des champs dans lindex

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

Introduction C++ Builder

65

6. Utilisation des contrles ActiveX


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

6.1 Mise en place


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

6.1.1 Edition de la liste des contrles disponibles

Composant slectionn

Liste de classes associes au composant slectionn Rpertoire de cration des units associes aux contrles ActiveX

Palette dinstallation du composant

Chemin de recherche des units associes aux contrles ActiveX dj rfrencs

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

Une unit est dj associe au composant, auquel cas, un ou plusieurs noms de classes lui sont associes et apparaissent au centre de la bote de dialogue.

Introduction C++ Builder

66

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

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

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

6.1.2 Recensement dans la base de registres dun nouveau composant


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

Le nouveau composant est slectionn par dfaut

Nom de la classe par dfaut

Figure 6.2 Fentre des composants ActiveX aprs enregistrement dun composant Vous noterez que le nouveau composant est dornavant prsent dans la liste. Le nom est celui denregistrement dans le fichier .ocx accompagn du numro de version Introduction C++ Builder 67

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

6.1.3 Cration dune unit


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

Figure 6.3 Installation du composant dans un paquet La notion de paquet est quelque peu complique pour tre explique ici. Pour lheure il vous suffit de valider systmatiquement toutes les options qui vous sont prsentes.

Introduction C++ Builder

68

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

Lensemble des mthodes chacune accompagne de la liste de ses paramtres avec leurs types Lensemble des proprits avec leurs types

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

Figure 6.4 mise jour de la palette

6.2 Utilisation dun contrle ActiveX


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

Introduction C++ Builder

69

Mois slectionn Anne courante

Liste des jours du mois

Date courante

Figure 6.5 le composant Calendrier plac sur une fiche


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

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

Figure 6.6 Evnements associs au contrle calendrier

6.3 Dploiement dun programme utilisant un contrle ActiveX


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

Un fichier .ocx qui contient le code du composant Un fichier .hlp et un fichier .cnt, supports de laide relative au composant Un fichier .dep de dpendances sur dautres composants ActiveX

Introduction C++ Builder

70

7. Lcriture de nouveaux composants


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

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

7.2 Cration dun nouveau composant


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

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

Introduction C++ Builder

71

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

7.2.1 Lexpert composant


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

Nom de classe choisi pour le nouveau composant

Classe dont va driver le nouveau composant

Palette dinstallation

Emplacement et nom des fichiers .h et .cpp gnrs

Chemin utilis par C++ Builder lors de la recherche du source 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 d'un composant existant ?

oui

non

Driver du composant spcialiser ou de sa forme abstraite

oui

Composant visuel ? non

oui

Destin recevoir la focalisation ?

non

Driver de TComponent

Driver de TWinControl

Driver de TGraphicControl

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

Introduction C++ Builder

74

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

Introduction C++ Builder

75

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

7.3 Exercice rsolu : cration du composant TListBoxCool 7.3.1 Motivation et droulement gnral de lexercice
Les composants TListBox encapsulent les composants botes de listes classiques de Windows. Le mode de slection de ces composants est rgi par deux proprits :

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

Hors, il est particulirement pnible daccder aux index des lments slectionns en mode multiple ou tendu :

Le nombre dlments slectionns est stock dans la proprit SelCount (jusquici tout va bien )

Il faut ensuite vrifier le statut slectionn de chaque lment de la liste grce la proprit indice Selected qui sutilise comme un tableau sur lensemble des lments (numrots de 0 ItemCount 1)

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

Introduction C++ Builder

76

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

Programme 7.1 Programme daffichage des index et des lments slectionns dune bote de liste Le rsultat visuel est illustr par la figure suivante o vous pourrez vrifier que cela fonctionne !

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

Programme 7.2 Vers une utilisation plus simple des botes de listes Pour rsumer, on souhaite que Indices[i] nous renvoie le numro dindex du lment slectionn.

me

7.3.2 Mise en place


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

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

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

2. La prochaine tape consiste inclure le paquet nouvellement cr dans la liste des paquets chargs automatiquement par C++ Builder. Ceci se fait grce la fentre active par le menu Composant Installer des paquets.

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

Introduction C++ Builder

78

Le bouton composants fait apparatre la liste des composants contenus dans un paquet, par exemple, la figure suivante illustre le contenu du paquet Composants Internet de C++ Builder .

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

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

Introduction C++ Builder

79

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

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

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

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

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

Introduction C++ Builder

81

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

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

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

Introduction C++ Builder

82

Figure 7.10 Mise jour de la palette ! Comme nous navons pas fourni de nouvelle icne pour ce composant, il reprend celle de son anctre le plus rcent : TListBox.

7.3.3 Utilisation du composant


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

7.3.4 Utilisation dun composant non install sur la palette


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

7.4 Exercice Rsolu n2 : La calculette Francs Euros


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

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

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

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

Proprits spcifiques au nouveau composant

Fond du composant sur lequel sont greffs les widgets

Figure 7.11 Le composant calculette avec ses proprits associes

7.4.1 Crer le composant


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

7.4.2 Crer des proprits


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

Euros
84

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

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

Programme 7.6 Mise en place dattributs de stockage des proprits Reste spcifier la politique daccs aux proprits. Dans notre cas, le plus simple est dutiliser des mthodes dcriture sophistiques qui assurent la cohrence des donnes entre elles ainsi que des vnements chargs de mettre jour les valeurs des proprits lorsque du texte est saisi dans les botes ddition. Ainsi, on peut lire directement la valeur des proprits dans lattribut de stockage. Le reste des dfinitions inhrentes aux proprits devient :
private: __fastcall __fastcall __fastcall __published: __property void SetTaux (double value); void SetFrancs (double value); void SetEuros (double value);

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

double Taux

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

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

Introduction C++ Builder

85

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

7.4.3 Grer laspect visuel du composant


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

Le style du composant, proprit commune tous les descendants de TControl. Le positionnement et laffichage de composants inclus (TLabel et TEdit) La publication de proprits masques

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

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

Introduction C++ Builder

86

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

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

Sachez galement que le constructeur de la classe TControl inclut par dfaut les options suivants dans ControlStyle : csCaptureMouse, csClickEvents, csSetCaption et csDoubleClicks. Bien entendu, il vous est toujours possible de modifier ces valeurs, mais ceci doit uniquement tre fait dans un constructeur.

Introduction C++ Builder

87

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

Programme 7.8 dclaration simplifie de la classe Set o :

T est un type homologue unsigned char, la plupart du temps un type numr. valMin et valMax sont les valeurs extrmes autorises pour les lments de lensemble.

Du fait de lutilisation de valMin et valMax dans le template, deux classes bases sur le mme type T mais de valeurs extrmes diffrentes ne sont pas compatibles. La classe Set est pourvue des mthodes prsentes dans le tableau suivant. Afin de gagner de la place, le spcificateur __fastcall3 prsent pour chacune des mthodes nest pas prsent.
Set(void) Set(const Set&) Set &operator=(const Set&) Set &operator *=(const Set& ) Set &operator +=(const Set& ) Set &operator =(const Set& )

Constructeur par dfaut, conoit un ensemble vide Constructeur par copie Affectation brutale Lensemble courant devient respectivement lintersection, la diffrence ensembliste et la runion entre lui mme et un autre ensemble pass en argument Comparaisons entre ensembles. Seules les oprations tous lments identiques et son

bool operator==(const Set&) const bool operator!=(const Set&) const

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

Introduction C++ Builder

88

oppos sont fournies. Il nest pas prvu de pouvoir ordonner des ensembles !
bool contains(const T) const Set & operator<<(const T) Set & operator>>(const T)

Teste la prsence dun lment dans lensemble Ajoute un lment dans lensemble Retire un lment de lensemble. La classe ne bronche pas si lon tente de retirer un lment non prsent Ralisent respectivement lintersection, la diffrence ensembliste et la runion de lensemble courant et dun autre ensemble pass en argument

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

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 >> >> << << Height=200; Width=230; labelFrancs = new TLabel(this); 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; saisieFrancs->Text="0"; 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; Ajout des diffrents composants inclus csAcceptsControls) csSetCaption) csFramed) csOpaque; Style visuel du composant en cours de cration

Affichage des la proprit Francs

Introduction C++ Builder

90

boutonSaisieTaux->Parent=this; }

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

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

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

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

Programme 7.10 Publication des proprits caches

Introduction C++ Builder

91

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

// Mise jour de l'affichage saisieFrancs->Text=FloatToStr(FFrancs); saisieEuros->Text=FloatToStr(FEuros); labelTaux->Caption="Le taux vaut :"+FloatToStr(FTaux);


} void __fastcall TCCBruno::SetFrancs(double value) { // Affectation des valeurs aux proprits FFrancs = value; FEuros = FFrancs / FTaux;

// Mise jour de l'affichage saisieEuros->Text=FloatToStr(FEuros); saisieFrancs->Text=FloatToStr(FFrancs);


} void __fastcall TCCBruno::SetEuros(double value) { // Affectation des valeurs aux proprits FEuros = value; FFrancs = FEuros * FTaux;

// Mise jour de l'affichage saisieFrancs->Text=FloatToStr(FFrancs); saisieEuros->Text=FloatToStr(FEuros);


}

Programme 7.11 code dimplmentation des mthodes daccs en criture aux proprits financires Quelques remarques simposent (mais si

-) :

Les mthodes daccs aux proprits (que ce soit en lecture ou en criture) ne sont toujours de type __fastcall ce qui implique en particulier quelles ne sont jamais inline.

Introduction C++ Builder

92

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

Il faut faire attention ne pas introduire de mcanisme en boucle lors de lcriture des mthodes daccs en criture. Ainsi, vous remarquerez que les proprits sont utilises via leur attribut de stockage dans ce type de code. Ceci est destin viter des mcanismes dappel infini. En effet, supposez linstruction :
Euros= ;

que

dans la

mthode

SetFrancs,

vous ayez

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

qui invoque son tour la mthode SetFrancs, on se retrouve dans un cas de cercle vicieux o chaque mthode passe son temps invoquer lautre ! Moralit : faites bien attention lutilisation des proprits par leurs mthodes daccs en criture lorsque vous crivez lune dentre elles !

7.4.4 Gestion des vnements internes


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

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

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

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

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

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

Introduction C++ Builder

94

Programme 7.13 Prototypes des vnements associs au clavier Examinons plus en dtail ces vnements : OnKeyDown est gnr lorsquune touche quelconque du clavier est enfonce OnKeyUp est gnr lorsquune touche quelconque du clavier est relche Leurs paramtres communs sont :

Sender : adresse du composant metteur de lvnement Key : code clavier virtuel (gographique

-) de la touche

Shift : paramtre de type Set pouvant contenir trois valeurs associes aux trois modificateurs du clavier : ssShift, ssCtrl et ssAlt. Leur prsence dans Shift indique que la touche correspondante du clavier est enfonce.

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

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

Introduction C++ Builder

95

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

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

7.4.5 Ajouter la saisie du taux


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

Figure 7.12 Bote de saisie du taux de lEuro 7.4.5.2 Utilisation de la bote de dialogue Il nous faut maintenant utiliser notre nouvelle bote de dialogue lintrieur de notre composant. Cette tape seffectue de manire classique 2 exceptions prs.

Introduction C++ Builder

96

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

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

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

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

Introduction C++ Builder

97

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

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

7.5 Exercice rsolu n3 ralisation dun composant de saisie de date


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

Track Bar de slection du jour

Bote d'dition de rcapitulation de la date (lecture seulement)

Label indiquant le nb de jours du mois courant

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

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

Introduction C++ Builder

99

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

Programme 7.16 Code du constructeur


void __fastcall TBrunoDate::Paint(void) { TCustomControl::Paint(); // Appel de Paint du parent if (comboMois->Items->Count==0) { // 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 // Test sur le nb dlments de // la bote combo

Introduction C++ Builder

100

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

Programme 7.17 Code de Paint

7.6 Gestion des vnements externes


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

7.6.1 Motivation et mise en uvre


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

Obtenir des indications (on parle habituellement de notifications) sur les oprations subies par le composant, par exemple, lutilisateur modifi la date courante Interagir avec lutilisateur final du produit en lui permettant dajouter ses propres commandes en rponse des vnements standard.

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

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

Que vous publiiez un vnement standard ou personnalis, il apparatra toujours dans la page vnements de linspecteur dobjet.

7.6.2 Un exemple simple


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

Le premier consistera rendre visible lvnement standard OnClick

Introduction C++ Builder

101

Les deux autres sont spcifiques au composant de saisie de date et seront respectivement mis avant et aprs les oprations de changement de date.

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

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

Introduction C++ Builder

102

Evenements et gestionnaires associs

Composant de saisie de date

Figure 7.14 Manipulation des vnements externes du composant de saisie de date


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

Programme 7.19 Code associ aux vnements externes du composant de saisie de date

7.6.3 Prendre en compte les vnements


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

Introduction C++ Builder

103

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

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

Programme 7.21 Prise encompte des vnments spcifiques Il est possible dinteragir avec le code de votre utilisateur en utilisant des paramtres en entre sortie comme le prouve lexercice suivant : Introduction C++ Builder 104

7.6.4 Exercice : interdire la modification de la date (

[[)

Utilisez un argument boolen pour le gestionnaire OnAvantChangementDate afin de pouvoir interdire la modification de la date. On pourra se rfrer aux vnements OnBeforeClose.

7.7 Conversion dune bote de dialogue gnrique en composant


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

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

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

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

Introduction C++ Builder

105

Le texte initial de la bote de saisie : proprit Text dun composant Edit de la bote de dialogue. Cest galement au travers de ce dernier que vous pourrez rcuprer le rsultat de votre saisie.

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

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

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

Figure 7.16 les proprits de notre composant saisie

7.7.2 Fonctionnement de lencapsulation


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

Introduction C++ Builder

106

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

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

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

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

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

Programme 7.22 Mise en place du composant

7.7.4 Mise en place des proprits


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

Introduction C++ Builder

107

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

Programme 7.23 Cration des proprits du nouveau composant

7.7.5 Codage de la mthode Execute


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

Programme 7.24 la mthode Execute

7.8 Ralisation dun composant graphique


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

Introduction C++ Builder

108

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

7.8.1 Le composant Affichage de Graphe


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

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

Nombre d'arcs

2.0 4.0 6.0 4.0 2.0

Un sommet : coordonnes x et y

Un arc :index des sommets origine et destination

Figure 7.17 Format dun fichier de graphe

7.8.2 Mise en uvre


Nous allons proposer les proprits suivantes :

Le nombre darcs et le nombre de sommets : entiers (NbSommets et NbArcs) en lecture seulement La marge daffichage : espace en pixels (Marge) entre la frontire du composant et lenveloppe convexe du graphe. Cest un entier en lecture et

Introduction C++ Builder

109

criture. La marge est mise en vidence sur la figure suivante ou le composant Graphe occupe la zone client dun TPanel.

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

Bien entendu, la majeure partie du travail est accomplie par 2 mthodes : Laffectation dun nom de fichier (partie write de la proprit Fichier) qui alloue de lespace mmoire pour stocker les informations relatives au graphe (coordonnes des sommets, origine et destination de chaque arc) La mthode Paint daffichage du composant qui est charge de mettre jour laspect visuel du composant

Enveloppe convexe (fictive) du graphe

Marge

Panel sur lequel est pos le composant Graphe

Figure 7.18 Visualisation du composant Graphe

7.9 Exercices supplmentaires


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

Introduction C++ Builder

110

2. Modifier le composant TListBoxCool pour quil utilise un composant de stockage pour la proprit Indices. Celui-ci devra tre mis jour lorsquun utilisateur clique sur la liste. Indication : il faudra redfinir la mthode WndProc. ( )

3. Modifier le composant Calculette pour quil nutilise pas dattribut de stockage pour la proprit Euros. ( )

4. Modifier le composant Calculette pour quil utilise TComposantSaisie en lieu et place de sa bote ddie. Est il toujours ncessaire dutiliser un pragma link ? ( )

5. Modifier la bote de saisie TSaisieGenerale et le composant TComposantSaisie pour quils intgrent la notion de masque de saisie et traitent les exceptions qui y sont lies ( )

Introduction C++ Builder

111

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

Introduction C++ Builder

112

Vous aimerez peut-être aussi