0% ont trouvé ce document utile (0 vote)
402 vues1 420 pages

Guide Du Développeur: C Builder 6

Transféré par

Henintsoa Ramorasata
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
402 vues1 420 pages

Guide Du Développeur: C Builder 6

Transféré par

Henintsoa Ramorasata
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Guide du développeur

Borland ®
C++Builder 6™

pour Windows ®
Reportez-vous au fichier DEPLOY situé dans le répertoire racine de votre produit C++Builder pour obtenir la liste
complète des fichiers que vous pouvez distribuer en accord avec les termes du contrat de licence de C++Builder.
Les applications mentionnées dans ce manuel sont brevetées ou en attente de brevet. Reportez-vous au CD du
produit ou à la boîte de dialogue A propos. Ce document ne donne aucun droit sur ces brevets.
COPYRIGHT © 1983-2002 Borland Software Corporation. Tous droits réservés. Tous les produits Borland sont des
marques commerciales ou des marques déposées de Borland Software Corporation aux Etats-Unis ou dans
les autres pays. Toutes les autres marques sont la propriété de leurs fabricants respectifs.

CPE1360WW21001 6E4R0102
02030405-9 8 7 6 5 4 3 2 1
PDF
Table des matières
Chapitre 1 Chapitre 4
Introduction 1-1 Utilisation de BaseCLX 4-1
Contenu de ce manuel . . . . . . . . . . . . . . 1-1 Utilisation des flux . . . . . . . . . . . . . . . . . 4-2
Conventions typographiques. . . . . . . . . . . 1-3 Utilisation des flux pour lire ou écrire
Support technique . . . . . . . . . . . . . . . . . 1-3 des données . . . . . . . . . . . . . . . . . . 4-2
Méthodes de flux pour la lecture
et l’écriture . . . . . . . . . . . . . . . . . 4-2
Partie I Lecture et écriture de composants. . . . . 4-3
Programmation C++Builder Copie de données d’un flux vers un autre . 4-3
Spécification de la position et de la taille
Chapitre 2 du flux . . . . . . . . . . . . . . . . . . . . . 4-4
Développement d’applications Déplacement sur une position
particulière . . . . . . . . . . . . . . . . . 4-4
avec C++Builder 2-1 Utilisation des propriétés de position
L’environnement de développement intégré. . 2-1
et de taille. . . . . . . . . . . . . . . . . . 4-4
Conception d’applications . . . . . . . . . . . . 2-2
Utilisation des fichiers . . . . . . . . . . . . . . . 4-5
Création des projets . . . . . . . . . . . . . . . . 2-3
Approches des E/S fichier . . . . . . . . . . . 4-5
Modification du code . . . . . . . . . . . . . . . 2-4
Utilisation de flux de fichier . . . . . . . . . . 4-6
Compilation des applications . . . . . . . . . . 2-4
Création et ouverture de fichiers
Débogage des applications . . . . . . . . . . . . 2-5
en utilisant des flux de fichier . . . . . . 4-6
Déploiement des applications . . . . . . . . . . 2-5
Utilisation du handle de fichier . . . . . . 4-7
Manipulation de fichiers . . . . . . . . . . . . 4-7
Chapitre 3 Suppression d’un fichier . . . . . . . . . . 4-8
Utilisation des bibliothèques Recherche d’un fichier . . . . . . . . . . . 4-8
de composants 3-1 Modification d’un nom de fichier . . . . 4-10
Présentation des bibliothèques de classes . . . 3-1 Routines date-heure de fichier . . . . . . 4-10
Propriétés, méthodes et événements . . . . 3-2 Copie d’un fichier . . . . . . . . . . . . . 4-10
Propriétés . . . . . . . . . . . . . . . . . . 3-2 Utilisation des fichiers ini et du registre. . . . 4-11
Méthodes . . . . . . . . . . . . . . . . . . 3-3 Utilisation de TIniFile et TMemIniFile . 4-11
Evénements . . . . . . . . . . . . . . . . . 3-3 Utilisation de TRegistryIniFile . . . . . . 4-13
Evénements utilisateur. . . . . . . . . . . 3-3 Utilisation de TRegistry. . . . . . . . . . 4-13
Evénements système . . . . . . . . . . . . 3-4 Utilisation des listes . . . . . . . . . . . . . . . 4-14
Objets, composants et contrôles . . . . . . . . . 3-4 Opérations de listes courantes. . . . . . . . 4-14
Branche TObject . . . . . . . . . . . . . . . . 3-6 Ajout d’éléments de liste . . . . . . . . . 4-15
Branche TPersistent . . . . . . . . . . . . . . 3-7 Suppression d’éléments de liste . . . . . 4-15
Branche TComponent . . . . . . . . . . . . . 3-7 Accès aux éléments de la liste . . . . . . 4-15
Branche TControl. . . . . . . . . . . . . . . . 3-9 Réorganisation d’éléments de liste . . . 4-16
Branche TWinControl/TWidgetControl . . . 3-10 Listes persistantes . . . . . . . . . . . . . . . 4-16
Utilisation des listes de chaînes. . . . . . . . . 4-17
Lecture et enregistrement
des listes de chaînes. . . . . . . . . . . . . 4-17

i
Création d’une nouvelle liste de chaînes . . 4-18 Recensez la famille de conversion
Listes de chaînes à court terme . . . . . . 4-18 et les autres unités . . . . . . . . . . . . 4-34
Listes de chaînes à long terme . . . . . . 4-18 Utilisation des nouvelles unités . . . . . 4-35
Manipulation des chaînes d’une liste . . . . 4-19 Création d’espaces de dessin . . . . . . . . . . 4-36
Comptage des chaînes d’une liste . . . . 4-20
Accès à une chaîne spécifique . . . . . . 4-20 Chapitre 5
Recherche d’éléments Utilisation des composants 5-1
dans une liste de chaînes . . . . . . . . 4-20 Initialisation des propriétés d’un composant . . 5-2
Parcours des chaînes d’une liste . . . . . 4-20 Initialisation des propriétés à la conception . 5-2
Ajout d’une chaîne à une liste . . . . . . 4-20 Utilisation des éditeurs de propriétés. . . 5-3
Déplacement d’une chaîne Initialisation des propriétés à l’exécution . . 5-3
dans une liste . . . . . . . . . . . . . . . 4-21 Appel de méthodes. . . . . . . . . . . . . . . . . 5-3
Suppression d’une chaîne d’une liste . . 4-21 Utilisation des événements
Association d’objets et des gestionnaires d’événements . . . . . . . 5-4
à une liste de chaînes . . . . . . . . . . 4-21 Génération d’un nouveau
Utilisation des chaînes . . . . . . . . . . . . . . 4-22 gestionnaire d’événement . . . . . . . . . . 5-4
Routines manipulant les caractères Génération du gestionnaire de l’événement
étendus . . . . . . . . . . . . . . . . . . . . 4-22 par défaut d’un composant . . . . . . . . . 5-4
Routines couramment utilisées Recherche de gestionnaires d’événements . . 5-5
pour les AnsiStrings . . . . . . . . . . . . . 4-23 Association d’un événement à un gestionnaire
Routines couramment utilisées d’événement existant . . . . . . . . . . . . . 5-5
pour les chaînes à zéro terminal . . . . . . 4-26 Utilisation du paramètre Sender. . . . . . 5-6
Impression . . . . . . . . . . . . . . . . . . . . . 4-27 Affichage et codage d’événements
Conversion de mesures . . . . . . . . . . . . . . 4-28 partagés . . . . . . . . . . . . . . . . . . . 5-6
Exécution des conversions . . . . . . . . . . 4-28 Association d’événements de menu
Exécution des conversions simples. . . . 4-28 à des gestionnaires d’événements . . . . . . 5-6
Exécution des conversions complexes . . 4-29 Suppression de gestionnaires d’événements 5-7
Ajout de nouveaux types de mesure . . . . 4-29 Composants multiplates-formes ou non
Création d’une famille de conversion multiplates-formes . . . . . . . . . . . . . . . . 5-7
simple et ajout d’unités . . . . . . . . . . . 4-29 Ajout de composants personnalisés
Déclaration des variables . . . . . . . . . 4-30 à la palette des composants . . . . . . . . 5-10
Recensement de la famille
de conversion . . . . . . . . . . . . . . . 4-30 Chapitre 6
Recensement des unités de mesure . . . 4-30 Manipulation des contrôles 6-1
Utilisation des nouvelles unités . . . . . 4-30 Implémentation du glisser-déplacer
Utilisation d’une fonction de conversion . . 4-31 dans les contrôles . . . . . . . . . . . . . . . . . 6-1
Déclaration des variables . . . . . . . . . 4-31 Début de l’opération glisser-déplacer . . . . 6-1
Recensement de la famille Acceptation des éléments à déplacer . . . . . 6-2
de conversion . . . . . . . . . . . . . . . 4-31 Déplacement des éléments. . . . . . . . . . . 6-3
Recensement de l’unité de base . . . . . 4-31 Fin de l’opération glisser-déplacer . . . . . . 6-3
Ecriture des méthodes de conversion Personnalisation du glisser-déplacer
à destination et à partir avec un objet déplacement . . . . . . . . . . 6-4
de l’unité de base . . . . . . . . . . . . . 4-32 Changement du pointeur de la souris . . . . 6-4
Recensement des autres unités . . . . . . 4-32 Implémentation du glisser-ancrer
Utilisation des nouvelles unités . . . . . 4-32 dans les contrôles . . . . . . . . . . . . . . . . . 6-4
Utilisation d’une classe pour gérer Transformation d’un contrôle fenêtré
les conversions . . . . . . . . . . . . . . . . 4-32 en un site d’ancrage. . . . . . . . . . . . . . 6-5
Création de la classe de conversion . . . 4-33 Transformation d’un contrôle
Déclaration des variables . . . . . . . . . 4-34 en un enfant ancrable . . . . . . . . . . . . . 6-5

ii
Contrôle de l’ancrage des contrôles enfant . 6-6 Création de paquets et de DLL . . . . . . . . . 7-10
Contrôle du désancrage Utilisation des paquets et des DLL . . . . . 7-11
des contrôles enfant . . . . . . . . . . . . . 6-6 Utilisation des DLL dans C++Builder . . . . . 7-12
Contrôle de la réponse des contrôles enfant Création de DLL dans C++Builder. . . . . . . 7-12
aux opérations glisser-ancrer . . . . . . . . 6-7 Création de DLL contenant
Manipulation du texte dans les contrôles . . . 6-7 des composants VCL et CLX . . . . . . . . . 7-13
Définition de l’alignement du texte . . . . . 6-7 Liaison de DLL . . . . . . . . . . . . . . . . . . 7-16
Ajout de barres de défilement Ecriture d’applications de bases de données . 7-16
en mode exécution . . . . . . . . . . . . . . 6-8 Distribution d’applications
Ajout de l’objet Clipboard . . . . . . . . . . 6-9 de bases de données . . . . . . . . . . . . 7-17
Sélection de texte. . . . . . . . . . . . . . . . 6-9 Création d’applications serveur Web. . . . . . 7-18
Sélection de la totalité d’un texte . . . . . . 6-9 Utilisation de WebBroker. . . . . . . . . . . 7-18
Couper, copier et coller du texte . . . . . . . 6-10 Création d’applications WebSnap . . . . . . 7-19
Effacement du texte sélectionné . . . . . . . 6-10 Utilisation d’InternetExpress . . . . . . . . 7-20
Désactivation des éléments de menu . . . . 6-10 Création d’applications services Web. . . . 7-20
Ajout d’un menu surgissant . . . . . . . . . 6-11 Ecriture d’applications en utilisant COM . . . 7-20
Gestion de l’événement OnPopup . . . . . . 6-12 Utilisation de COM et de DCOM . . . . . . 7-21
Ajout de graphiques à des contrôles . . . . . . 6-12 Utilisation de MTS et de COM+ . . . . . . 7-21
Spécification du style dessiné Utilisation de modules de données . . . . . . 7-22
par le propriétaire . . . . . . . . . . . . . . 6-13 Création et modification de modules
Ajout d’objets graphiques de données standard . . . . . . . . . . . . 7-23
à une liste de chaînes . . . . . . . . . . . . 6-14 Nom d’un module de données
Ajout d’images à une application . . . . 6-14 et de son fichier unité . . . . . . . . . . 7-23
Ajout d’images à une liste de chaînes . . 6-14 Placer et nommer les composants . . . . 7-24
Dessiner des éléments dessinés Utilisation des propriétés et événements
par le propriétaire . . . . . . . . . . . . 6-15 des composants dans un module
Dimensionnement des éléments dessinés de données . . . . . . . . . . . . . . . . 7-25
par le propriétaire . . . . . . . . . . . . . . 6-15 Création de règles de gestion
Dessin des éléments par le propriétaire. . . 6-16 dans un module de données . . . . . . 7-25
Accès à un module de données
Chapitre 7 depuis une fiche . . . . . . . . . . . . . . . 7-25
Création d’applications, de composants Ajout d’un module de données distant
à un projet serveur d’application . . . . . 7-26
et de bibliothèques 7-1 Utilisation du référentiel d’objets. . . . . . . . 7-27
Création d’applications . . . . . . . . . . . . . . 7-1
Partage d’éléments dans un projet . . . . . 7-27
Applications d’interface utilisateur
Ajout d’éléments au Référentiel d’objets. . 7-27
graphique . . . . . . . . . . . . . . . . . . . 7-1
Partage d’objets par une équipe
Modèles d’interfaces utilisateur . . . . . 7-2
de développement. . . . . . . . . . . . . . 7-27
Applications SDI . . . . . . . . . . . . . . 7-2
Utilisation d’un élément du référentiel
Applications MDI. . . . . . . . . . . . . . 7-2
d’objets dans un projet . . . . . . . . . . . 7-28
Définition des options de l’EDI, du projet
Copie d’un élément . . . . . . . . . . . . 7-28
et de la compilation . . . . . . . . . . . 7-3
Héritage d’un élément . . . . . . . . . . 7-28
Modèles de programmation . . . . . . . . . 7-3
Utilisation d’un élément . . . . . . . . . 7-28
Applications console . . . . . . . . . . . . . . 7-4
Utilisation de modèles de projet . . . . . . 7-29
Utilisation de la VCL et de la CLX
Modification d’éléments partagés. . . . . . 7-29
dans les applications console . . . . . . 7-4
Spécification d’un projet par défaut, d’une
Applications service . . . . . . . . . . . . . . 7-4
nouvelle fiche et de la fiche principale . . 7-29
Threads de service . . . . . . . . . . . . . 7-7
Activation de l’aide dans les applications . . . 7-30
Propriétés de nom d’un service . . . . . 7-9
Interfaces avec les systèmes d’aide . . . . . 7-30
Débogage d’applications service . . . . . 7-10

iii
Implémentation de ICustomHelpViewer . . 7-31 Transfert de paramètres supplémentaires
Communication avec le gestionnaire aux fiches . . . . . . . . . . . . . . . . . . . . 8-8
d’aide . . . . . . . . . . . . . . . . . . . . . 7-31 Récupération des données des fiches. . . . . 8-9
Demande d’informations Récupération de données
au gestionnaire d’aide . . . . . . . . . . . . 7-32 dans les fiches non modales . . . . . . . 8-9
Affichage de l’aide basée sur un mot clé . . 7-33 Récupération de données
Affichage des sommaires . . . . . . . . . . . 7-34 dans les fiches modales . . . . . . . . . 8-10
Implémentation de IExtendedHelpViewer . 7-34 Réutilisation des composants
Implémentation de IHelpSelector . . . . . . 7-35 et des groupes de composants . . . . . . . . 8-13
Recensement des objets du système d’aide. 7-36 Création et utilisation
Recensement des visualiseurs d’aide . . 7-36 des modèles de composants . . . . . . . . . . 8-13
Recensement des sélecteurs d’aide . . . . 7-36 Manipulation des cadres. . . . . . . . . . . . . 8-14
Utilisation de l’aide Création de cadres . . . . . . . . . . . . . . 8-14
dans une application VCL . . . . . . . . . . . 7-37 Ajout de cadres à la palette
Comment TApplication traite-il l’aide VCL 7-37 des composants . . . . . . . . . . . . . . . 8-15
Comment les contrôles VCL Utilisation et modification des cadres . . . 8-15
traitent-ils l’aide . . . . . . . . . . . . . . . 7-37 Partage des cadres . . . . . . . . . . . . . . 8-16
Utilisation de l’aide Développement de boîtes de dialogue. . . . . 8-17
dans une application CLX . . . . . . . . . . . 7-38 Utilisation des boîtes de dialogue
Comment TApplication d’ouverture . . . . . . . . . . . . . . . . . . 8-17
traite-il l’aide CLX . . . . . . . . . . . . . . 7-38 Organisation des actions pour les barres d’outils
Comment les contrôles CLX et les menus . . . . . . . . . . . . . . . . . . . 8-18
traitent-ils l’aide . . . . . . . . . . . . . . . 7-38 Qu’est-ce qu’une action ?. . . . . . . . . . . 8-20
Appel direct à un système d’aide . . . . . . . . 7-39 Définition des bandes d’actions . . . . . . . 8-21
Utilisation de IHelpSystem . . . . . . . . . . . . 7-39 Création des barres d’outils et des menus . 8-21
Personnalisation du système d’aide de l’EDI . 7-40 Ajout de couleurs, de motifs ou d’images
aux menus, boutons et barres d’outils 8-23
Chapitre 8 Ajout d’icônes aux menus
Conception de l’interface utilisateur et aux barres d’outils . . . . . . . . . . 8-23
Création de barres d’outils et de menus
des applications 8-1 personnalisables par l’utilisateur . . . 8-24
Contrôle du comportement de l’application . . 8-1
Cacher les éléments et les catégories
Manipulation de l’application . . . . . . . . 8-2
inutilisés dans les bandes d’actions . . 8-25
Gestion de l’écran . . . . . . . . . . . . . . . 8-2
Utilisation des listes d’actions. . . . . . . . . . 8-26
Paramétrage des fiches . . . . . . . . . . . . . . 8-2
Définition des listes d’actions . . . . . . . . 8-26
Utilisation de la fiche principale . . . . . . . 8-3
Que se passe-t-il lors du déclenchement
Cacher la fiche principale . . . . . . . . . . . 8-3
d’une action ? . . . . . . . . . . . . . . . . 8-27
Ajout de fiches . . . . . . . . . . . . . . . . . 8-3
Réponse par les événements . . . . . . . 8-27
Liaison de fiches . . . . . . . . . . . . . . 8-3
Comment les actions trouvent
Gestion de la disposition . . . . . . . . . . . 8-4
leurs cibles . . . . . . . . . . . . . . . . 8-29
Utilisation des fiches . . . . . . . . . . . . . . . 8-5
Actualisation des actions . . . . . . . . . . . 8-29
Contrôle du stockage en mémoire
Classes d’actions prédéfinies . . . . . . . . 8-30
des fiches . . . . . . . . . . . . . . . . . . . 8-5
Conception de composants action . . . . . 8-31
Affichage d’une fiche créée
Recensement d’actions . . . . . . . . . . . . 8-32
automatiquement . . . . . . . . . . . . . 8-6
Création et gestion de menus . . . . . . . . . . 8-32
Création dynamique de fiche . . . . . . . 8-6
Ouverture du concepteur de menus . . . . 8-33
Création de fiches non modales
Construction des menus . . . . . . . . . . . 8-34
comme fenêtres . . . . . . . . . . . . . . 8-7
Nom des menus . . . . . . . . . . . . . . 8-34
Création d’une instance de fiche
Nom des éléments de menu . . . . . . . 8-34
en utilisant une variable locale . . . . . 8-7

iv
Ajout, insertion et suppression Création de groupes de boutons outil . 8-52
d’éléments de menu . . . . . . . . . . . 8-35 Utilisation de boutons outil bascule . . 8-52
Ajout de lignes de séparation. . . . . . . 8-37 Ajout d’un composant barre multiple . . . 8-52
Spécification de touches accélératrices Définition de l’aspect
et de raccourcis clavier . . . . . . . . . . 8-37 de la barre multiple . . . . . . . . . . . 8-53
Création de sous-menus. . . . . . . . . . . . 8-37 Réponse aux clics . . . . . . . . . . . . . . . 8-53
Création de sous-menus par déplacement Affectation d’un menu
de menus existants . . . . . . . . . . . . 8-38 à un bouton outil . . . . . . . . . . . . 8-53
Déplacement d’éléments de menu . . . . 8-38 Ajout de barres d’outils cachées . . . . . . 8-54
Ajout d’images à des éléments de menu 8-39 Masquage et affichage d’une barre d’outils 8-54
Affichage du menu . . . . . . . . . . . . . 8-40
Edition des éléments de menu Chapitre 9
dans l’inspecteur d’objets . . . . . . . . . . 8-40 Types de contrôles 9-1
Utilisation du menu contextuel Contrôles texte . . . . . . . . . . . . . . . . . . . 9-1
du concepteur de menus . . . . . . . . . . 8-41 Contrôles de saisie . . . . . . . . . . . . . . . 9-2
Commandes du menu contextuel . . . . 8-41 Propriétés des contrôles de saisie . . . . . . . 9-3
Déplacement parmi les menus Contrôles de saisie mémo
à la conception . . . . . . . . . . . . . . 8-41 et texte formaté . . . . . . . . . . . . . . 9-3
Utilisation des modèles de menu . . . . . . 8-42 Contrôles de visualisation de texte
Enregistrement d’un menu comme modèle 8-43 (CLX seulement). . . . . . . . . . . . . . . . 9-4
Conventions de nom pour les éléments Libellés . . . . . . . . . . . . . . . . . . . . . . 9-4
et les gestionnaires d’événements Contrôles de saisies spécialisées . . . . . . . . . 9-5
des modèles de menu . . . . . . . . . . 8-44 Barres de défilement . . . . . . . . . . . . . . 9-5
Manipulation d’éléments de menu Barres graduées . . . . . . . . . . . . . . . . . 9-5
à l’exécution. . . . . . . . . . . . . . . . . . 8-45 Contrôles flèches haut-bas (VCL seulement) 9-6
Fusion de menus . . . . . . . . . . . . . . . . 8-45 Contrôles incrémenteur (CLX seulement) . . 9-6
Spécification du menu actif : Contrôles touche d’accès rapide
propriété Menu . . . . . . . . . . . . . . 8-45 (VCL seulement). . . . . . . . . . . . . . . . 9-7
Ordre des éléments de menu fusionnés : Contrôles séparateur . . . . . . . . . . . . . . 9-7
propriété GroupIndex . . . . . . . . . . 8-46 Boutons et contrôles similaires . . . . . . . . . . 9-7
Importation de fichiers ressource . . . . . . 8-46 Contrôles bouton . . . . . . . . . . . . . . . . 9-8
Conception de barres d’outils Boutons bitmap . . . . . . . . . . . . . . . . . 9-8
et de barres multiples . . . . . . . . . . . . . . 8-47 Turboboutons . . . . . . . . . . . . . . . . . . 9-9
Ajout d’une barre d’outils en utilisant Cases à cocher . . . . . . . . . . . . . . . . . . 9-9
un composant volet . . . . . . . . . . . . . 8-48 Boutons radio . . . . . . . . . . . . . . . . . . 9-9
Ajout d’un turbobouton à un volet . . . 8-48 Barres d’outils . . . . . . . . . . . . . . . . . 9-10
Spécification du glyphe Barres multiples (VCL seulement) . . . . . 9-10
d’un turbobouton . . . . . . . . . . . . . 8-49 Contrôles liste . . . . . . . . . . . . . . . . . . . 9-11
Définition de l’état initial Boîtes liste et boîtes liste de cases à cocher 9-11
d’un turbobouton . . . . . . . . . . . . . 8-49 Boîtes à options . . . . . . . . . . . . . . . . 9-12
Création d’un groupe de turboboutons . 8-49 Vues arborescentes . . . . . . . . . . . . . . 9-13
Utilisation de boutons bascule . . . . . . 8-50 Vues liste . . . . . . . . . . . . . . . . . . . . 9-13
Ajout d’une barre d’outils en utilisant Sélecteurs Date/Heure et calendriers
le composant barre d’outils . . . . . . . . . 8-50 mensuels (VCL seulement). . . . . . . . . 9-14
Ajout d’un bouton outil . . . . . . . . . . 8-50 Regroupement de contrôles . . . . . . . . . . . 9-14
Affectation d’images Boîtes groupe et groupes de boutons radio 9-14
à des boutons outil . . . . . . . . . . . . 8-51 Volets . . . . . . . . . . . . . . . . . . . . . . 9-15
Définition de l’aspect et des conditions Boîtes de défilement . . . . . . . . . . . . . 9-15
initiales d’un bouton outil . . . . . . . . 8-51 Contrôles onglets . . . . . . . . . . . . . . . 9-16

v
Contrôles pages . . . . . . . . . . . . . . . . 9-16 Enregistrement d’une image
Contrôles en-têtes . . . . . . . . . . . . . . . 9-16 dans un fichier . . . . . . . . . . . . . 10-21
Contrôles d’affichage . . . . . . . . . . . . . . . 9-16 Remplacement de l’image . . . . . . . 10-22
Barres d’état. . . . . . . . . . . . . . . . . . . 9-17 Utilisation du presse-papiers
Barres de progression . . . . . . . . . . . . . 9-17 avec les graphiques . . . . . . . . . . . . 10-23
Propriétés d’aide ou de conseil d’aide . . . 9-17 Copier des graphiques
Grilles . . . . . . . . . . . . . . . . . . . . . . . . 9-18 dans le presse-papiers. . . . . . . . . 10-23
Grilles de dessin . . . . . . . . . . . . . . . . 9-18 Couper des graphiques
Grilles de chaînes . . . . . . . . . . . . . . . 9-18 dans le presse-papiers. . . . . . . . . 10-23
Editeur de liste de valeurs (VCL seulement) . 9-19 Coller des graphiques
Contrôles graphiques . . . . . . . . . . . . . . . 9-20 depuis le presse-papiers . . . . . . . 10-24
Images . . . . . . . . . . . . . . . . . . . . . . 9-20 Techniques de dessin
Formes . . . . . . . . . . . . . . . . . . . . . . 9-20 dans une application . . . . . . . . . . . 10-25
Biseaux . . . . . . . . . . . . . . . . . . . . . 9-20 Répondre à la souris . . . . . . . . . . 10-25
Boîtes à peindre . . . . . . . . . . . . . . . . 9-21 Ajout d’un champ à un objet fiche . . 10-28
Contrôles animation (VCL seulement) . . . 9-21 Amélioration du dessin des lignes . . 10-29
Utilisation du multimédia . . . . . . . . . . . 10-31
Chapitre 10 Ajout de séquences vidéo silencieuses
Utilisation des graphiques à une application . . . . . . . . . . . . . 10-31
Exemple d’ajout de séquences vidéo
et du multimédia 10-1 silencieuses . . . . . . . . . . . . . . . 10-32
Présentation de la programmation relative
Ajout de séquences audio et/ou vidéo
aux graphiques . . . . . . . . . . . . . . . . . . 10-1
à une application . . . . . . . . . . . . . 10-33
Rafraîchissement de l’écran . . . . . . . . . . 10-2
Exemple d’ajout de séquences audio
Types des objets graphiques . . . . . . . . . 10-3
et/ou vidéo (VCL seulement) . . . . 10-35
Propriétés et méthodes communes
du canevas . . . . . . . . . . . . . . . . . . 10-4
Utilisation des propriétés
Chapitre 11
de l’objet canevas . . . . . . . . . . . . . . 10-5 Ecriture d’applications multithreads 11-1
Utilisation des crayons. . . . . . . . . . . 10-6 Définition d’objets thread . . . . . . . . . . . . 11-2
Utilisation des pinceaux . . . . . . . . . . 10-8 Initialisation du thread . . . . . . . . . . . . 11-3
Lecture et définition de pixels . . . . . 10-10 Affectation d’une priorité par défaut . . 11-3
Utilisation des méthodes du canevas Libération des threads . . . . . . . . . . 11-4
pour dessiner des objets graphiques. . . 10-10 Ecriture de la fonction thread . . . . . . . . 11-4
Dessin de lignes et de polylignes . . . 10-10 Utilisation du thread principal
Dessin de formes . . . . . . . . . . . . . 10-12 VCL/CLX . . . . . . . . . . . . . . . . . 11-4
Gestion de plusieurs objets de dessin Utilisation de variables locales
dans votre application . . . . . . . . . . . 10-13 aux threads . . . . . . . . . . . . . . . . 11-6
Faire le suivi de l’outil de dessin Vérification de l’arrêt
à utiliser . . . . . . . . . . . . . . . . . 10-13 par d’autres threads . . . . . . . . . . . 11-6
Changement d’outil en utilisant Gestion des exceptions
un turbobouton . . . . . . . . . . . . 10-14 dans la fonction thread . . . . . . . . . 11-7
Utilisation des outils de dessin . . . . . 10-14 Ecriture du code de nettoyage . . . . . . . 11-7
Dessiner sur un graphique . . . . . . . . . 10-18 Coordination de threads . . . . . . . . . . . . . 11-8
Création de graphiques défilables . . . 10-18 Eviter les accès simultanés . . . . . . . . . . 11-8
Ajout d’un contrôle image . . . . . . . 10-18 Verrouillage d’objets. . . . . . . . . . . . 11-8
Chargement et enregistrement Utilisation de sections critiques . . . . . 11-8
de fichiers graphiques . . . . . . . . . . . 10-20 Utilisation du synchronisateur à écriture
Chargement d’une image exclusive et lecture multiple . . . . . . 11-9
depuis un fichier . . . . . . . . . . . . 10-21

vi
Autres techniques de partage Classes d’exception VCL et CLX . . . . . 12-18
de la mémoire . . . . . . . . . . . . . . 11-10 Considérations de portabilité . . . . . . . 12-20
Attente des autres threads . . . . . . . . . 11-10
Attente de la fin d’exécution Chapitre 13
d’un thread . . . . . . . . . . . . . . . 11-10 Gestion en langage C++
Attente de l’achèvement d’une tâche . 11-11
Exécution d’objets thread . . . . . . . . . . . . 11-12
de VCL et CLX 13-1
Les modèles objet en C++ et en Pascal Objet . 13-1
Redéfinition de la priorité par défaut . . . 11-12
Héritage et interfaces . . . . . . . . . . . . . 13-2
Démarrage et arrêt des threads . . . . . . 11-13
Utilisation d’interface à la place
Débogage d’applications multithreads . . . . 11-13
de l’héritage multiple . . . . . . . . . . 13-2
Nommer un thread . . . . . . . . . . . . . 11-14
Déclaration des classes interfaces . . . . 13-2
Conversion d’un thread anonyme
IUnknown et IInterface . . . . . . . . . . 13-3
en thread nommé . . . . . . . . . . . . 11-14
Création de classes gérant IUnknown . 13-4
Affectation de noms distincts
Classes interfaces et gestion
à des threads similaires . . . . . . . . 11-15
de la durée de vie . . . . . . . . . . . . 13-5
Identification et instanciation des objets . . 13-6
Chapitre 12 Différences entre les références C++
Gestion des exceptions 12-1 et Pascal Objet . . . . . . . . . . . . . . 13-6
Gestion des exceptions C++ . . . . . . . . . . . 12-1 Copie d’objets . . . . . . . . . . . . . . . 13-7
Syntaxe de gestion des exceptions . . . . . . 12-2 Utilisation d’objets comme arguments
Le bloc try . . . . . . . . . . . . . . . . . . 12-2 de fonction . . . . . . . . . . . . . . . . 13-8
L’instruction throw . . . . . . . . . . . . . 12-3 Construction d’objets en C++Builder
L’instruction catch . . . . . . . . . . . . . 12-3 pour les classes VCL/CLX . . . . . . . . . 13-8
Redéclenchement des exceptions . . . . . . 12-4 Construction d’objets en C++ . . . . . . 13-8
Spécifications des exceptions . . . . . . . . . 12-4 Construction d’objets Pascal Objet . . . 13-8
Déroulement des exceptions . . . . . . . . . 12-5 Construction des objets C++Builder . . 13-8
Pointeurs sécurisés . . . . . . . . . . . . . 12-6 Appels de méthodes virtuelles dans les
Constructeurs dans la gestion d’exceptions 12-6 constructeurs des classes de base . . . . 13-10
Gestion des exceptions non interceptées Modèle Pascal Objet. . . . . . . . . . . .13-11
et inattendues . . . . . . . . . . . . . . . . . 12-6 Modèle C++ . . . . . . . . . . . . . . . .13-11
Exceptions structurées sous Win32 . . . . . . . 12-7 Modèle C++Builder . . . . . . . . . . . .13-11
Syntaxe des exceptions structurées . . . . . 12-8 Exemple : appel de méthodes virtuelles13-11
Gestion des exceptions structurées . . . . . 12-8 Initialisation par le constructeur
Filtres d’exceptions. . . . . . . . . . . . . . . 12-9 des données membres
Mélange du C++ avec des exceptions pour les fonctions virtuelles . . . . . 13-12
structurées. . . . . . . . . . . . . . . . . . 12-11 Destruction d’objets. . . . . . . . . . . . . 13-14
Exemple d’un programme C++ Exceptions déclenchées
ayant des exceptions C. . . . . . . . . 12-12 dans les constructeurs. . . . . . . . . 13-14
Définition d’exceptions . . . . . . . . . . . 12-13 Méthodes virtuelles appelées
Déclenchement d’exceptions . . . . . . . . 12-13 dans les destructeurs . . . . . . . . . 13-15
Blocs de terminaison. . . . . . . . . . . . . 12-14 AfterConstruction et BeforeDestruction . 13-15
Options de gestion des exceptions Fonctions virtuelles de classe . . . . . . . 13-15
C++Builder . . . . . . . . . . . . . . . . . 12-15 Gestion des types de données et des concepts
Gestion des exceptions VCL/CLX. . . . . . . 12-16 du langage Pascal Objet . . . . . . . . . . . 13-16
Différences entre la gestion d’exceptions Typedefs . . . . . . . . . . . . . . . . . . . 13-16
C++ et VCL/CLX . . . . . . . . . . . . . 12-16 Classes gérant le langage Pascal Objet . . 13-16
Gestion des exceptions du système Equivalents dans le langage C++
d’exploitation . . . . . . . . . . . . . . . . 12-17 du langage Pascal Objet . . . . . . . . . 13-17
Gestion des exceptions VCL et CLX. . . . 12-18 Paramètres var . . . . . . . . . . . . . . 13-17

vii
Paramètres sans type. . . . . . . . . . . 13-17 Registre . . . . . . . . . . . . . . . . . . . 14-7
Tableaux ouverts . . . . . . . . . . . . . . . 13-18 Autres différences . . . . . . . . . . . . . 14-8
Calcul du nombre d’éléments. . . . . . 13-18 Fonctionnalités manquantes dans la CLX . 14-9
Temporaires . . . . . . . . . . . . . . . . 13-19 Fonctionnalités non portées directement. . 14-9
Tableau de constantes . . . . . . . . . . 13-19 Comparaison entre les unités CLX et VCL 14-10
Macro OPENARRAY . . . . . . . . . . . 13-20 Différences dans les constructeurs
Macro EXISTINGARRAY . . . . . . . . 13-20 d’objets CLX . . . . . . . . . . . . . . . . 14-13
Fonctions C++ attendant un argument Gestion des événements widget
tableau ouvert . . . . . . . . . . . . . . 13-20 et système . . . . . . . . . . . . . . . . . 14-14
Types définis différemment . . . . . . . . . 13-20 Partage des fichiers source
Types de données booléens . . . . . . . 13-21 entre Windows et Linux . . . . . . . . . 14-14
Types de données Char . . . . . . . . . 13-21 Différences d’environnement
Interfaces Delphi . . . . . . . . . . . . . . . 13-21 entre Windows et Linux . . . . . . . . . 14-14
Chaînes de ressource . . . . . . . . . . . . 13-22 Structure de répertoires sous Linux . . . 14-17
Paramètres par défaut . . . . . . . . . . . . 13-22 Ecriture de code portable . . . . . . . . . 14-18
Informations de type à l’exécution . . . . 13-23 Utilisation des directives
Types sans correspondants . . . . . . . . . 13-24 conditionnelles . . . . . . . . . . . . . 14-19
Type réel sur six octets. . . . . . . . . . 13-24 Emission de messages . . . . . . . . . 14-20
Tableaux renvoyés par des fonctions . 13-24 Inclusion de code assembleur inline . 14-21
Extensions des mots clés . . . . . . . . . . 13-25 Différences de programmation
__classid . . . . . . . . . . . . . . . . . . 13-25 sous Linux . . . . . . . . . . . . . . . . . 14-22
__closure . . . . . . . . . . . . . . . . . . 13-25 Applications de bases de données
__property . . . . . . . . . . . . . . . . . 13-27 multiplates-formes . . . . . . . . . . . . . . 14-22
__published . . . . . . . . . . . . . . . . 13-29 Différences de dbExpress . . . . . . . . . 14-23
Extensions du mot clé __declspec . . . . . 13-29 Différences au niveau composant . . . . . 14-24
__declspec(delphiclass) . . . . . . . . . 13-29 Différences au niveau
__declspec(delphireturn). . . . . . . . . 13-30 de l’interface utilisateur . . . . . . . . . 14-25
__declspec(delphirtti) . . . . . . . . . . 13-30 Portage d’applications
__declspec(dynamic) . . . . . . . . . . . 13-30 de bases de données vers Linux. . . . . 14-26
__declspec(hidesbase) . . . . . . . . . . 13-30 Mise à jour des données
__declspec(package) . . . . . . . . . . . 13-31 dans les applications dbExpress. . . . . 14-28
__declspec(pascalimplementation) . . . 13-31 Applications Internet multiplates-formes . . 14-30
__declspec(uuid) . . . . . . . . . . . . . 13-31 Portage d’applications Internet
vers Linux . . . . . . . . . . . . . . . . . 14-31
Chapitre 14
Développement d’applications Chapitre 15
multiplates-formes 14-1 Utilisation des paquets
Création d’applications multiplates-formes . . 14-1 et des composants 15-1
Portage d’applications Windows vers Linux. . 14-2 Pourquoi utiliser des paquets ? . . . . . . . . 15-2
Techniques de portage. . . . . . . . . . . . . 14-2 Les paquets et les DLL standard . . . . . . 15-2
Portages propres à une plate-forme . . . 14-3 Paquets d’exécution . . . . . . . . . . . . . . . 15-3
Portages multiplates-formes. . . . . . . . 14-3 Utilisation des paquets
Portages d’émulation Windows . . . . . 14-3 dans une application . . . . . . . . . . . . 15-3
Portage de votre application . . . . . . . . . 14-3 Paquets chargés dynamiquement . . . . . . 15-4
CLX et VCL . . . . . . . . . . . . . . . . . . . 14-5 Choix des paquets d’exécution à utiliser. . 15-4
Différences de CLX . . . . . . . . . . . . . . 14-6 Paquets personnalisés . . . . . . . . . . . . 15-5
Présentation visuelle . . . . . . . . . . . . 14-6 Paquets de conception . . . . . . . . . . . . . . 15-5
Styles . . . . . . . . . . . . . . . . . . . . . 14-7 Installation de paquets de composants. . . 15-6
Variants . . . . . . . . . . . . . . . . . . . 14-7 Création et modification de paquets . . . . . . 15-7

viii
Création d’un paquet . . . . . . . . . . . . . 15-7 Basculement dynamique de DLL
Modification d’un paquet existant . . . . . . 15-8 de ressource . . . . . . . . . . . . . . . . 16-13
Fichiers source de paquet et fichiers Localisation des applications . . . . . . . . . 16-13
d’options de projet . . . . . . . . . . . . . . 15-9 Localisation des ressources . . . . . . . . 16-13
Empaquetage des composants . . . . . . 15-9
Présentation de la structure d’un paquet . 15-10 Chapitre 17
Nom de paquets . . . . . . . . . . . . . 15-10 Déploiement des applications 17-1
Liste Requires . . . . . . . . . . . . . . . 15-10 Déploiement d’applications généralistes . . . 17-1
Liste Contains . . . . . . . . . . . . . . 15-11 Utilisation des programmes d’installation . 17-2
Construction des paquets . . . . . . . . . . 15-11 Identification des fichiers
Directives de compilation de l’application. . . . . . . . . . . . . . 17-3
propres aux paquets . . . . . . . . . . 15-12 Fichiers de l’application . . . . . . . . . 17-3
Utilisation du compilateur et du lieur Fichiers paquet. . . . . . . . . . . . . . . 17-3
en ligne de commande . . . . . . . . . 15-13 Modules de fusion. . . . . . . . . . . . . 17-4
Fichiers de paquets créés Contrôles ActiveX . . . . . . . . . . . . . 17-5
lors d’une construction. . . . . . . . . 15-14 Applications complémentaires . . . . . . 17-6
Déploiement de paquets . . . . . . . . . . . . 15-14 Emplacement des DLL . . . . . . . . . . 17-6
Déploiement d’applications utilisant Déploiement d’applications CLX . . . . . . . . 17-6
des paquets . . . . . . . . . . . . . . . . . 15-15 Déploiement d’applications
Distribution de paquets de bases de données . . . . . . . . . . . . . . 17-7
à d’autres développeurs . . . . . . . . . . 15-15 Déploiement d’applications de bases
Fichiers de collection de paquets . . . . . 15-15 de données dbExpress . . . . . . . . . . . 17-8
Déploiement d’applications BDE . . . . . . 17-9
Chapitre 16 Le moteur de bases de données
Création d’applications Borland . . . . . . . . . . . . . . . . . . 17-9
internationales 16-1 SQL Links . . . . . . . . . . . . . . . . 17-10
Internationalisation et localisation. . . . . . . . 16-1 Déploiement d’applications de bases de
Internationalisation . . . . . . . . . . . . . . 16-1 données multiniveaux (DataSnap) . . . .17-11
Localisation . . . . . . . . . . . . . . . . . . . 16-2 Déploiement d’applications Web . . . . . . . .17-11
Internationalisation des applications . . . . . . 16-2 Déploiement sur serveur Apache . . . . . 17-12
Codage de l’application . . . . . . . . . . . . 16-2 Activation des modules. . . . . . . . . 17-12
Jeux de caractères. . . . . . . . . . . . . . 16-2 Applications CGI . . . . . . . . . . . . 17-12
Jeux de caractères OEM et ANSI . . . . . 16-3 Programmation pour des environnements
Jeux de caractères sur plusieurs octets . 16-3 hôtes hétérogènes . . . . . . . . . . . . . . . 17-13
Caractères larges . . . . . . . . . . . . . . 16-3 Résolution d’écran et profondeur
Inclure des fonctionnalités bi-directionnelles de couleurs . . . . . . . . . . . . . . . . . 17-14
dans les applications . . . . . . . . . . . 16-4 Si vous n’utilisez pas de redimensionnement
Propriété BiDiMode . . . . . . . . . . . . 16-6 dynamique . . . . . . . . . . . . . . . 17-14
Fonctionnalités spécifiques Si vous redimensionnez dynamiquement
aux cibles locales . . . . . . . . . . . . . 16-9 les fiches et les contrôles . . . . . . . 17-14
Conception de l’interface utilisateur. . . . . 16-9 Adaptation à des profondeurs de couleurs
Texte . . . . . . . . . . . . . . . . . . . . . 16-9 variables. . . . . . . . . . . . . . . . . 17-16
Images graphiques . . . . . . . . . . . . 16-10 Fontes . . . . . . . . . . . . . . . . . . . . . 17-16
Formats et ordre de tri. . . . . . . . . . 16-10 Versions des systèmes d’exploitation . . . 17-17
Correspondances entre claviers. . . . . 16-10 Termes du contrat de licence logicielle . . . 17-17
Isolement des ressources . . . . . . . . . . 16-11 DEPLOY . . . . . . . . . . . . . . . . . . . 17-17
Création de DLL de ressource . . . . . . . 16-11 README . . . . . . . . . . . . . . . . . . . 17-18
Utilisation des DLL de ressource . . . . . 16-12 Contrat de licence . . . . . . . . . . . . . . 17-18
Documentation de produits
vendus par un tiers . . . . . . . . . . . . 17-18

ix
Partie II Edition des données affichées
dans un contrôle . . . . . . . . . . . . . 19-6
Développement d’applications Activation et désactivation de l’affichage
de bases de données des données . . . . . . . . . . . . . . . . . 19-7
Rafraîchissement de l’affichage
Chapitre 18 des données . . . . . . . . . . . . . . . . . 19-7
Conception d’applications Activation des événements souris,
clavier et timer. . . . . . . . . . . . . . . . 19-8
de bases de données 18-1 Choix de l’organisation des données. . . . . . 19-8
Utilisation des bases de données . . . . . . . . 18-1
Affichage d’un seul enregistrement. . . . . 19-8
Types de bases de données . . . . . . . . . . 18-3
Affichage de données
Sécurité des bases de données . . . . . . . . 18-4
en tant que libellés. . . . . . . . . . . . 19-9
Transactions . . . . . . . . . . . . . . . . . . . 18-5
Affichage et édition de champs
Intégrité référentielle, procédures stockées
dans une zone de saisie . . . . . . . . . 19-9
et déclencheurs . . . . . . . . . . . . . . . . 18-6
Affichage et édition de texte
Architecture des bases de données . . . . . . . 18-6
dans un contrôle mémo . . . . . . . . 19-10
Structure générale . . . . . . . . . . . . . . . 18-7
Affichage et édition dans un contrôle mémo
Fiche interface utilisateur . . . . . . . . . 18-7
de texte formaté . . . . . . . . . . . . 19-10
Module de données . . . . . . . . . . . . 18-7
Affichage et édition de champs graphiques
Connexion directe à un serveur
dans un contrôle image . . . . . . . . .19-11
de bases de données . . . . . . . . . . . . . 18-9
Affichage de données dans des boîtes liste
Utilisation d’un fichier dédié sur disque . 18-10
et des boîtes à options . . . . . . . . .19-11
Connexion à un autre ensemble
Manipulation de champs booléens
de données . . . . . . . . . . . . . . . . . 18-12
avec des cases à cocher . . . . . . . . 19-15
Connexion d’un ensemble de données client
Limitation de valeurs de champ
à un autre ensemble de données
avec des boutons radio . . . . . . . . 19-16
dans la même application . . . . . . . 18-14
Affichage de plusieurs enregistrements . 19-17
Utilisation d’une architecture
Visualisation et édition des données
multiniveau . . . . . . . . . . . . . . . 18-15
avec un contrôle TDBGrid . . . . . . . . . . 19-17
Combinaison des approches . . . . . . . . 18-16
Utilisation d’un contrôle grille
Conception de l’interface utilisateur . . . . . 18-17
à son état par défaut . . . . . . . . . . . 19-18
Analyse des données . . . . . . . . . . . . 18-18
Création d’une grille personnalisée. . . . 19-19
Ecriture de rapports . . . . . . . . . . . . . 18-18
Présentation des colonnes persistantes 19-20
Création de colonnes persistantes . . . 19-21
Chapitre 19 Suppression de colonnes persistantes. 19-22
Utilisation de contrôles de données 19-1 Modification de l’ordre
Fonctionnalités communes des colonnes persistantes . . . . . . . 19-22
des contrôles de données . . . . . . . . . . . . 19-2 Définition des propriétés de colonne
Association d’un contrôle de données en mode conception . . . . . . . . . . 19-23
à un ensemble de données . . . . . . . . . 19-3 Définition d’une colonne
Modification de l’ensemble de données de liste de référence . . . . . . . . . . 19-24
associé à l’exécution . . . . . . . . . . . 19-4 Insertion d’un bouton
Activation et désactivation dans une colonne . . . . . . . . . . . 19-24
de la source de données . . . . . . . . . 19-4 Restauration des valeurs par défaut
Réponse aux modifications effectuées d’une colonne . . . . . . . . . . . . . 19-25
par le biais de la source de données . . 19-4 Affichage des champs ADT et tableau . . 19-25
Edition et mise à jour des données . . . . . 19-5 Définition des options de la grille . . . . 19-28
Activation de l’édition des contrôles Saisie de modifications dans la grille. . . 19-29
lors d’une saisie utilisateur . . . . . . . 19-5 Contrôle du dessin de la grille . . . . . . 19-30

x
Comment répondre aux actions de l’utilisateur Ouverture et fermeture des champs
à l’exécution. . . . . . . . . . . . . . . . . 19-30 d’une grille de décision . . . . . . . . 20-12
Création d’une grille qui contient d’autres Réorganisation des lignes et des colonnes
contrôles orientés données . . . . . . . . . . 19-31 d’une grille de décision . . . . . . . . 20-12
Navigation et manipulation Perforation pour voir les détails
d’enregistrements . . . . . . . . . . . . . . . 19-33 dans les grilles de décision . . . . . . 20-13
Choix des boutons visibles . . . . . . . . . 19-34 Limite des dimensions à sélectionner
Affichage et dissimulation des boutons dans les grilles de décision . . . . . . 20-13
en mode conception . . . . . . . . . . 19-34 Propriétés des grilles de décision . . . . . 20-13
Affichage et dissimulation des boutons Création et utilisation de graphes
à l’exécution . . . . . . . . . . . . . . . 19-34 de décision . . . . . . . . . . . . . . . . . . . 20-14
Affichage de panneaux d’information. . . 19-35 Création de graphes de décision . . . . . 20-14
Utilisation d’un navigateur pour plusieurs Utilisation de graphes de décision . . . . 20-15
ensembles de données . . . . . . . . . . . 19-35 Affichage du graphe de décision . . . . . 20-16
Personnalisation du graphe de décision . 20-17
Chapitre 20 Définition des modèles de graphe
Utilisation de composants de décision par défaut . . . . . . . . 20-18
Personnalisation des séries
d’aide à la décision 20-1 d’un graphe de décision . . . . . . . 20-19
Présentation . . . . . . . . . . . . . . . . . . . . 20-1
Utilisation des composants d’aide
Présentation des références croisées. . . . . . . 20-2
à la décision à l’exécution . . . . . . . . . . 20-20
Références croisées à une dimension . . . . 20-3
Pivots de décision à l’exécution . . . . . . 20-20
Références croisées à plusieurs
Grilles de décision à l’exécution . . . . . 20-21
dimensions . . . . . . . . . . . . . . . . . . 20-3
Graphes de décision à l’exécution . . . . 20-21
Instructions relatives à l’utilisation de composants
Considérations relatives au contrôle
d’aide à la décision . . . . . . . . . . . . . . . 20-3
de la mémoire . . . . . . . . . . . . . . . . . 20-21
Utilisation d’ensembles de données
Définition du maximum de dimensions,
avec les composants d’aide à la décision . . . 20-5
de champs récapitulatifs, et de cellules 20-22
Création d’ensembles de données de décision
Définition de l’état des dimensions. . . . 20-22
avec TQuery ou TTable . . . . . . . . . . . 20-6
Utilisation de dimensions paginées. . . . 20-23
Création d’ensembles de données de décision
avec l’éditeur de requête de décision . . . 20-6
Utilisation des cubes de décision . . . . . . . . 20-7
Chapitre 21
Propriétés et événements Connexion aux bases de données 21-1
des cubes de décision . . . . . . . . . . . . 20-8 Utilisation de connexions implicites . . . . . . 21-2
Utilisation de l’éditeur de cube de décision 20-8 Contrôles des connexions . . . . . . . . . . . . 21-3
Visualisation et modification des paramètres Connexion à un serveur
de dimensions . . . . . . . . . . . . . . . 20-8 de bases de données . . . . . . . . . . . . 21-3
Définition du maximum de dimensions Déconnexion d’un serveur
et de récapitulations . . . . . . . . . . . 20-9 de base de données . . . . . . . . . . . . . 21-4
Visualisation et modification des options Contrôle de la connexion au serveur . . . . . 21-4
de conception . . . . . . . . . . . . . . . 20-9 Gestion des transactions . . . . . . . . . . . . . 21-6
Utilisation de sources de décision . . . . . . . 20-10 Démarrage d’une transaction . . . . . . . . 21-7
Propriétés et événements . . . . . . . . . . 20-10 Achèvement d’une transaction . . . . . . . 21-9
Utilisation de pivots de décision . . . . . . . 20-10 Achèvement d’une transaction réussie . 21-9
Propriétés des pivots de décision . . . . . 20-11 Achèvement d’une transaction
Création et utilisation de grilles de décision . 20-11 non réussie . . . . . . . . . . . . . . . . 21-9
Création de grilles de décision . . . . . . . 20-12 Spécification du niveau d’isolation
Utilisation de grilles de décision . . . . . . 20-12 des transactions . . . . . . . . . . . . . . 21-10
Envoi de commandes au serveur. . . . . . . .21-11

xi
Utilisation d’ensembles de données associés 21-13 Définition d’options de filtre . . . . . . . 22-18
Fermeture d’ensembles de données Navigation parmi les enregistrements
sans déconnexion du serveur . . . . . . . 21-13 d’un ensemble de données filtré . . . . 22-19
Déplacement parmi les ensembles Modification des données . . . . . . . . . . . 22-20
de données associés . . . . . . . . . . . . 21-14 Modification d’enregistrements . . . . . . 22-20
Obtention de métadonnées . . . . . . . . . . . 21-14 Ajout de nouveaux enregistrements . . . 22-21
Enumération des tables disponibles . . . . 21-15 Insertion d’enregistrements . . . . . . 22-22
Enumération des champs d’une table . . . 21-15 Ajout d’enregistrements à la fin . . . . 22-23
Enumération des procédures stockées Suppression d’enregistrements . . . . . . 22-23
disponibles . . . . . . . . . . . . . . . . . 21-15 Validation des données . . . . . . . . . . . 22-24
Enumération des index disponibles . . . . 21-16 Annulation des modifications . . . . . . . 22-24
Enumération des paramètres Modification d’enregistrements entiers. . 22-25
de procédure stockée . . . . . . . . . . . 21-16 Champs calculés . . . . . . . . . . . . . . . . 22-26
Types d’ensembles de données . . . . . . . . 22-27
Chapitre 22 Utilisation d’ensembles de données
Présentation de type table . . . . . . . . . . . . . . . . . . 22-29
Avantages de l’utilisation des ensembles
des ensembles de données 22-1 de données de type table. . . . . . . . . 22-30
Utilisation des descendants de TDataSet . . . . 22-2
Tri des enregistrements avec des index . 22-30
Détermination des états d’un ensemble
Obtention d’informations sur les index 22-31
de données . . . . . . . . . . . . . . . . . . . . 22-3
Spécification d’un index
Ouverture et fermeture des ensembles
avec IndexName . . . . . . . . . . . . 22-31
de données . . . . . . . . . . . . . . . . . . . . 22-5
Création d’un index
Navigation dans les ensembles de données . . 22-6
avec IndexFieldNames . . . . . . . . 22-32
Utilisation des méthodes First et Last . . . . 22-7
Utilisation d’index pour chercher
Utilisation des méthodes Next et Prior . . . 22-7
des enregistrements . . . . . . . . . . . . 22-32
Utilisation de la méthode MoveBy . . . . . 22-8
Exécution d’une recherche
Utilisation des propriétés Eof et Bof. . . . . 22-9
avec les méthodes Goto . . . . . . . . 22-33
Eof . . . . . . . . . . . . . . . . . . . . . . 22-9
Exécution d’une recherche
Bof . . . . . . . . . . . . . . . . . . . . . 22-10
avec les méthodes Find . . . . . . . . 22-34
Marquage d’enregistrements . . . . . . . . 22-11
Spécification de l’enregistrement en cours
La propriété Bookmark . . . . . . . . . 22-11
après une recherche réussie . . . . . 22-34
La méthode GetBookmark . . . . . . . 22-11
Recherche sur des clés partielles . . . 22-34
Les méthodes GotoBookmark
Réitération ou extension
et BookmarkValid . . . . . . . . . . . . 22-11
d’une recherche . . . . . . . . . . . . 22-35
La méthode CompareBookmarks. . . . 22-11
Limitation des enregistrements
La méthode FreeBookmark . . . . . . . 22-11
avec des portées . . . . . . . . . . . . . . 22-35
Un exemple d’utilisation de signets . . 22-12
Présentation des différences
Recherche dans les ensembles de données . . 22-12
entre les portées et les filtres . . . . . 22-35
Utilisation de la méthode Locate. . . . . . 22-12
Spécification de portées. . . . . . . . . 22-36
Utilisation de la méthode Lookup . . . . . 22-13
Modification d’une portée . . . . . . . 22-39
Affichage et édition d’ensembles de données
Application ou annulation
en utilisant des filtres . . . . . . . . . . . . . 22-15
d’une portée . . . . . . . . . . . . . . 22-40
Activation et désactivation des filtres . . . 22-15
Création de relations maître/détail . . . . 22-40
Création de filtres . . . . . . . . . . . . . . 22-16
Comment faire de la table la partie détail
Définition de la propriété Filter . . . . 22-16
d’un autre ensemble de données . . 22-41
Ecriture d’un gestionnaire d’événement
Utilisation de tables détail imbriquées 22-43
OnFilterRecord . . . . . . . . . . . . . 22-18
Contrôle des accès en lecture/écriture
Permutation entre les gestionnaires
aux tables . . . . . . . . . . . . . . . . . . 22-44
d’événements filtre à l’exécution . . . 22-18

xii
Création et suppression des tables. . . . . 22-44 Définition d’un champ de données . . . 23-7
Création de tables . . . . . . . . . . . . 22-44 Définition d’un champ calculé . . . . . . 23-8
Suppression de tables . . . . . . . . . . 22-47 Programmation d’un champ calculé . . 23-9
Vidage des tables. . . . . . . . . . . . . . . 22-47 Définition d’un champ de référence . 23-10
Synchronisation des tables . . . . . . . . . 22-48 Définition d’un champ agrégat . . . . 23-12
Utilisation d’ensembles de données Suppression de champs persistants. . . . 23-12
de type requête. . . . . . . . . . . . . . . . . 22-48 Définition des événements et des propriétés
Spécification de la requête . . . . . . . . . 22-49 des champs persistants . . . . . . . . . . 23-13
Spécification d’une requête en utilisant Définition des propriétés d’affichage
la propriété SQL . . . . . . . . . . . . 22-50 et d’édition en mode conception . . 23-13
Spécification d’une requête en utilisant Définition des propriétés des composants
la propriété CommandText . . . . . . 22-51 champ à l’exécution . . . . . . . . . . 23-15
Utilisation de paramètres Création des ensembles d’attributs
dans les requêtes . . . . . . . . . . . . . . 22-51 pour les composants champ . . . . . 23-15
Fourniture des paramètres Association des ensembles d’attributs
pendant la conception . . . . . . . . . 22-52 aux composants champ . . . . . . . . 23-16
Fourniture des paramètres Suppression des associations
pendant l’exécution. . . . . . . . . . . 22-53 d’ensembles d’attributs . . . . . . . . 23-16
Etablissement de relations maître/détail Contrôle ou dissimulation de la saisie
en utilisant des paramètres . . . . . . . . 22-54 utilisateur . . . . . . . . . . . . . . . . 23-17
Préparation des requêtes . . . . . . . . . . 22-55 Utilisation des formats par défaut pour les
Exécution de requêtes qui ne renvoient pas champs numériques, date et heure . 23-17
d’ensemble de résultats . . . . . . . . . . 22-56 Gestion des événements . . . . . . . . 23-18
Utilisation d’ensembles de résultats Manipulation des méthodes de champ
unidirectionnels. . . . . . . . . . . . . . . 22-57 lors de l’exécution . . . . . . . . . . . . . . 23-19
Utilisation d’ensembles de données de type Affichage, conversion et accès aux valeurs
procédure stockée . . . . . . . . . . . . . . . 22-57 des champs . . . . . . . . . . . . . . . . . . 23-20
Utilisation de paramètres Affichage de valeurs dans les contrôles
avec les procédures stockées . . . . . . . 22-59 standard . . . . . . . . . . . . . . . . . . 23-20
Définition des paramètres Conversion des valeurs de champs. . . . 23-21
pendant la conception . . . . . . . . . 22-60 Accès à des valeurs par la propriété par défaut
Utilisation des paramètres d’un ensemble de données . . . . . . . . 23-22
pendant l’exécution. . . . . . . . . . . 22-61 Accès à des valeurs par la propriété Fields
Préparation des procédures stockées . . . 22-62 d’un ensemble de données . . . . . . . . 23-23
Exécution de procédures stockées qui ne Accès à des valeurs par la méthode
renvoient pas d’ensemble de résultats. . 22-62 FieldByName d’un ensemble
Lecture de plusieurs ensembles de données . . . . . . . . . . . . . . . . . 23-23
de résultats . . . . . . . . . . . . . . . . . 22-63 Définition de la valeur par défaut
d’un champ . . . . . . . . . . . . . . . . . . 23-24
Chapitre 23 Utilisation de contraintes . . . . . . . . . . . 23-24
Manipulation Création de contrainte personnalisée . . . 23-24
Utilisation des contraintes du serveur . . 23-25
des composants champ 23-1 Utilisation des champs objet . . . . . . . . . 23-26
Composants champ dynamique . . . . . . . . . 23-2
Affichage des champs ADT et tableau . . 23-27
Champs persistants . . . . . . . . . . . . . . . . 23-3
Utilisation des champs ADT. . . . . . . . 23-27
Création de champs persistants . . . . . . . 23-4
Utilisation de composants champ
Modification de l’ordre des champs
persistant . . . . . . . . . . . . . . . . 23-27
persistants . . . . . . . . . . . . . . . . . . . 23-6
Utilisation de la méthode FieldByName
Définition de nouveaux champs
d’un ensemble de données . . . . . . 23-28
persistants . . . . . . . . . . . . . . . . . . . 23-6

xiii
Utilisation de la propriété FieldValues Liaison des paramètres . . . . . . . . . 24-13
d’un ensemble de données . . . . . . 23-28 Manipulation des procédures stockées
Utilisation de la propriété FieldValues redéfinies d’Oracle. . . . . . . . . . . 24-13
d’un champ ADT . . . . . . . . . . . . 23-28 Connexion aux bases de données
Utilisation de la propriété Fields avec TDatabase . . . . . . . . . . . . . . 24-14
d’un champ ADT . . . . . . . . . . . . 23-28 Association d’un composant
Utilisation des champs tableau. . . . . . . 23-29 base de données à une session. . . . 24-14
Utilisation de champs persistants . . . 23-29 Interactions entre les composants
Utilisation de la propriété FieldValues base de données et session . . . . . . 24-15
d’un champ tableau . . . . . . . . . . 23-29 Identification de la base de données . 24-15
Utilisation de la propriété Fields Ouverture d’une connexion
d’un champ tableau . . . . . . . . . . 23-29 avec TDatabase. . . . . . . . . . . . . 24-17
Utilisation des champs ensemble Utilisation des composants base de données
de données . . . . . . . . . . . . . . . . . 23-30 dans les modules de données . . . . 24-18
Affichage des champs ensemble Gestion des sessions de bases de données 24-18
de données. . . . . . . . . . . . . . . . 23-30 Activation d’une session . . . . . . . . 24-20
Accès aux données d’un ensemble Spécification du comportement
de données imbriqué . . . . . . . . . . 23-30 de la connexion de base de données
Utilisation de champs de référence . . . . 23-31 par défaut . . . . . . . . . . . . . . . . 24-21
Affichage des champs de référence . . 23-31 Gestion des connexions de bases
Accès aux données d’un champ de données . . . . . . . . . . . . . . . 24-22
de référence . . . . . . . . . . . . . . . 23-31 Manipulation des tables Paradox et dBASE
protégées par mot de passe . . . . . 24-24
Chapitre 24 Spécification des répertoires Paradox. 24-27
Utilisation du moteur de bases Manipulation des alias BDE . . . . . . 24-28
Récupération des informations
de données Borland 24-1 d’une session . . . . . . . . . . . . . . 24-29
Architecture BDE . . . . . . . . . . . . . . . . . 24-1
Création de sessions supplémentaires 24-30
Utilisation d’ensembles de données BDE . . 24-2
Affectation d’un nom à une session . 24-31
Association d’un ensemble de données
Gestion de sessions multiples . . . . . 24-32
avec les connexions de bases de données
Utilisation des transactions avec le BDE . . 24-34
et de session . . . . . . . . . . . . . . . . 24-3
Utilisation du SQL transparent . . . . . . 24-35
Mise en cache des BLOBS . . . . . . . . . 24-4
Utilisation de transactions locales . . . . 24-35
Obtention d’un handle BDE. . . . . . . . 24-5
Utilisation du BDE pour placer
Utilisation de TTable. . . . . . . . . . . . . . 24-5
en mémoire cache les mises à jour . . . . . 24-36
Spécification du type d’une table locale . 24-6
Activation des mises à jour BDE
Contrôle d’accès en lecture/écriture
en mémoire cache . . . . . . . . . . . . . 24-38
aux tables locales . . . . . . . . . . . . . 24-6
Application des mises à jour BDE
Spécification d’un fichier d’index
en mémoire cache . . . . . . . . . . . . . 24-38
dBASE . . . . . . . . . . . . . . . . . . . 24-7
Application des mises à jour en mémoire
Renommer une table locale . . . . . . . . 24-8
cache avec une base de données. . . 24-40
Importation des données
Application des mises à jour en mémoire
d’une autre table . . . . . . . . . . . . . 24-8
cache avec les méthodes de composant
Utilisation de TQuery . . . . . . . . . . . . . 24-9
base de données . . . . . . . . . . . . 24-41
Création de requêtes hétérogènes . . . 24-10
Création d’un gestionnaire d’événement
Obtention d’un ensemble de résultats
OnUpdateRecord. . . . . . . . . . . . 24-41
modifiable . . . . . . . . . . . . . . . . 24-11
Gestion des erreurs de mise à jour
Mise à jour des ensembles de résultats
en mémoire cache . . . . . . . . . . . 24-43
en lecture seule . . . . . . . . . . . . . 24-12
Utilisation de TStoredProc . . . . . . . . . 24-13

xiv
Utilisation d’objets mise à jour pour mettre Utilisation des ensembles
à jour un ensemble de données . . . . . 24-45 d’enregistrements . . . . . . . . . . . .25-11
Création d’instructions SQL Filtrage d’enregistrements
pour les composants mise à jour . . . 24-46 à partir de signets . . . . . . . . . . . 25-12
Utilisation de plusieurs objets Lecture d’enregistrements
mise à jour . . . . . . . . . . . . . . . . 24-50 de façon asynchrone. . . . . . . . . . 25-13
Exécution des instructions SQL. . . . . 24-52 Utilisation des mises à jour groupées. 25-13
Utilisation de TBatchMove . . . . . . . . . . . 24-55 Lecture et enregistrement des données
Création d’un composant action groupée. 24-55 dans des fichiers . . . . . . . . . . . . 25-16
Spécification d’un mode d’action Utilisation de TADODataSet. . . . . . . . 25-17
groupée . . . . . . . . . . . . . . . . . . . 24-56 Utilisation d’objets commande . . . . . . . . 25-19
Ajout d’enregistrements . . . . . . . . . 24-57 Spécification de la commande . . . . . . . 25-19
Mise à jour d’enregistrements . . . . . 24-57 Utilisation de la méthode Execute . . . . 25-20
Ajout et mise à jour d’enregistrements 24-57 Annulation des commandes . . . . . . . . 25-20
Copie d’ensembles de données . . . . . 24-57 Récupération d’ensembles de résultats
Suppression d’enregistrements . . . . . 24-58 à l’aide de commandes . . . . . . . . . . 25-21
Mappage des types de données . . . . . . 24-58 Gestion des paramètres de commande. . 25-21
Exécution d’une action groupée . . . . . . 24-59
Gestion des erreurs relatives Chapitre 26
aux actions groupées. . . . . . . . . . . . 24-59 Utilisation d’ensembles de données
Dictionnaire de données . . . . . . . . . . . . 24-60
Outils de manipulation du BDE . . . . . . . . 24-62
unidirectionnels 26-1
Types d’ensembles de données
unidirectionnels . . . . . . . . . . . . . . . . . 26-2
Chapitre 25 Connexion au serveur de bases de données . 26-3
Utilisation des composants ADO 25-1 Configuration de TSQLConnection . . . . . 26-4
Présentation générale des composants ADO. . 25-2 Identification du pilote . . . . . . . . . . 26-4
Connexion à des stockages de données ADO . 25-3 Spécification des paramètres
Connexion à un stockage de données de connexion . . . . . . . . . . . . . . . 26-4
avec TADOConnection . . . . . . . . . . . 25-3 Dénomination d’une description
Accès à l’objet connexion . . . . . . . . . 25-5 de connexion . . . . . . . . . . . . . . . 26-5
Optimisation d’une connexion . . . . . . . . 25-5 Utilisation de l’éditeur de connexion . . 26-5
Connexions asynchrones . . . . . . . . . 25-5 Spécification des données à afficher . . . . . . 26-6
Contrôle des dépassements de délais . . 25-6 Représentation des résultats d’une requête 26-7
Indication des types d’opérations Représentation des enregistrements
pris en charge par la connexion . . . . 25-6 d’une table . . . . . . . . . . . . . . . . . . 26-7
Spécification de l’exécution automatique Représentation d’une table en utilisant
des transactions par la connexion . . . 25-7 TSQLDataSet . . . . . . . . . . . . . . . . 26-8
Accès aux commandes d’une connexion . . 25-8 Représentation d’une table
Evénements connexion ADO . . . . . . . . . 25-8 en utilisant TSQLTable . . . . . . . . . 26-8
Evénements se produisant pendant Représentation des résultats
l’établissement d’une connexion . . . . 25-8 d’une procédure stockée . . . . . . . . . . 26-8
Evénements se produisant pendant Récupération des données. . . . . . . . . . . . 26-9
la déconnexion . . . . . . . . . . . . . . 25-9 Préparation de l’ensemble de données . . . 26-9
Evénements se produisant pendant Récupération de plusieurs ensembles
la gestion des transactions. . . . . . . . 25-9 de données . . . . . . . . . . . . . . . . . 26-10
Autres événements . . . . . . . . . . . . . 25-9 Exécution des commandes ne renvoyant pas
Utilisation des ensembles de données ADO . . 25-9 d’enregistrement . . . . . . . . . . . . . . . 26-10
Connexion d’un ensemble de données ADO Spécification de la commande à exécuter .26-11
à un stockage de données . . . . . . 25-10 Exécution de la commande . . . . . . . . .26-11

xv
Création et modification des métadonnées Clonage d’un curseur d’ensemble
du serveur . . . . . . . . . . . . . . . . . . 26-12 de données client . . . . . . . . . . . 27-17
Définition de curseurs liés maître/détail . . . 26-13 Ajout d’informations d’application
Accès aux informations de schéma . . . . . . 26-13 aux données . . . . . . . . . . . . . . . . 27-18
Récupération de métadonnées dans un Utilisation d’un ensemble de données client
ensemble de données unidirectionnel . . 26-14 pour mettre en cache les mises à jour . . . 27-18
Lecture des données après l’utilisation Présentation de l’utilisation d’un cache
de l’ensemble de données pour les mises à jour . . . . . . . . . . . 27-19
pour des métadonnées . . . . . . . . . 26-15 Choix du type d’ensemble de données
Structure des ensembles pour les mises à jour en cache. . . . . . 27-21
de métadonnées. . . . . . . . . . . . . 26-15 Indication des enregistrements modifiés . 27-22
Débogage d’applications dbExpress. . . . . . 26-19 Mise à jour des enregistrements . . . . . 27-24
Utilisation de TSQLMonitor pour contrôler Application des mises à jour . . . . . . 27-24
les commandes SQL . . . . . . . . . . . . 26-19 Intervention pendant l’application
Utilisation d’un callback pour contrôler des mises à jour . . . . . . . . . . . . 27-25
les commandes SQL . . . . . . . . . . . . 26-20 Conciliation des erreurs
de mise à jour . . . . . . . . . . . . . 27-27
Chapitre 27 Utilisation d’un ensemble de données client
Utilisation avec un fournisseur. . . . . . . . . . . . . . 27-29
Spécification d’un fournisseur. . . . . . . 27-29
d’ensembles de données client 27-1 Extraction des données dans l’ensemble
Manipulation des données avec un ensemble
de données ou le document source . . . 27-31
de données client . . . . . . . . . . . . . . . . 27-2
Extractions incrémentales. . . . . . . . 27-31
Navigation parmi les données des ensembles
Extraction à la demande . . . . . . . . 27-32
de données client . . . . . . . . . . . . . . . 27-2
Obtention de paramètres de l’ensemble
Limitation des enregistrements affichés. . . 27-3
de données source. . . . . . . . . . . . . 27-32
Edition des données . . . . . . . . . . . . . . 27-6
Transmission de paramètres à l’ensemble
Annulation des modifications. . . . . . . 27-6
de données source. . . . . . . . . . . . . 27-33
Enregistrement des modifications . . . . 27-7
Envoi de paramètres de requête
Définition de contraintes pour les valeurs
ou de procédure stockée . . . . . . . 27-34
des données . . . . . . . . . . . . . . . . . . 27-8
Limitation des enregistrements
Spécification de contraintes
avec des paramètres . . . . . . . . . . 27-34
personnalisées . . . . . . . . . . . . . . . 27-8
Gestion des contraintes liées au serveur . 27-35
Tri et indexation . . . . . . . . . . . . . . . . 27-9
Rafraîchissement des enregistrements . . 27-36
Ajout d’un nouvel index . . . . . . . . 27-10
Communication avec des fournisseurs à l’aide
Suppression et permutation d’index . . 27-11
d’événements personnalisés . . . . . . . 27-37
Utilisation des index pour regrouper
Redéfinition de l’ensemble de données
les données . . . . . . . . . . . . . . . 27-11
source . . . . . . . . . . . . . . . . . . . . 27-38
Représentation des valeurs calculées . . . 27-12
Utilisation d’un ensemble de données client
Utilisation de champs calculés de façon
avec des données basées sur des fichiers . 27-39
interne dans les ensembles de données
Création d’un nouvel ensemble
client . . . . . . . . . . . . . . . . . . . 27-13
de données . . . . . . . . . . . . . . . . . 27-39
Utilisation des agrégats maintenus . . . . 27-13
Chargement des données depuis un fichier
Spécification d’agrégats . . . . . . . . . 27-14
ou un flux . . . . . . . . . . . . . . . . . 27-40
Agrégats de groupes
Fusion des modifications
d’enregistrements . . . . . . . . . . . . 27-15
dans les données . . . . . . . . . . . . . 27-41
Obtention de valeurs d’agrégat. . . . . 27-16
Sauvegarde des données dans un fichier
Copie de données d’un autre ensemble
ou un flux . . . . . . . . . . . . . . . . . 27-41
de données . . . . . . . . . . . . . . . . . 27-16
Affectation directe des données . . . . 27-16

xvi
Chapitre 28 Structure de l’application client . . . . . . . 29-5
Structure du serveur d’applications . . . . 29-5
Utilisation des composants Contenu du module de données
fournisseur 28-1 distant . . . . . . . . . . . . . . . . . . . 29-6
Spécification de la source de données . . . . . 28-2 Utilisation des modules de données
Utilisation d’un ensemble de données comme transactionnels . . . . . . . . . . . . . . 29-7
source des données. . . . . . . . . . . . . . 28-2 Regroupement des modules de données
Utilisation d’un document XML comme source distants . . . . . . . . . . . . . . . . . . 29-9
des données . . . . . . . . . . . . . . . . . . 28-3 Sélection d’un protocole de connexion . . 29-10
Communication avec l’ensemble de données Utilisation de connexions DCOM . . . 29-10
client . . . . . . . . . . . . . . . . . . . . . . . . 28-3 Utilisation de connexions Socket . . . .29-11
Détermination du mode d’application Utilisation de connexions Web . . . . .29-11
des mises à jour à l’aide d’un fournisseur Utilisation de connexions SOAP. . . . 29-12
d’ensemble de données . . . . . . . . . . . . . 28-4 Construction d’une application multiniveau 29-13
Contrôle des informations placées Création du serveur d’applications . . . . . 29-13
dans les paquets de données . . . . . . . . . . 28-5 Configuration du module de données
Spécification des champs apparaissant distant. . . . . . . . . . . . . . . . . . . . 29-15
dans les paquets de données . . . . . . . . 28-5 Configuration d’un module de données
Initialisation des options contrôlant distant non transactionnel . . . . . . 29-15
les paquets de données . . . . . . . . . . . 28-6 Configuration d’un module de données
Ajout d’informations personnalisées distant transactionnel . . . . . . . . . 29-16
aux paquets de données . . . . . . . . . . . 28-7 Configuration de TSoapDataModule . 29-18
Comment répondre aux demandes Extension de l’interface du serveur
de données des clients . . . . . . . . . . . . . 28-8 d’applications . . . . . . . . . . . . . . . 29-18
Comment répondre aux demandes Ajout de rappels à l’interface du serveur
de mise à jour des clients . . . . . . . . . . . . 28-9 d’applications. . . . . . . . . . . . . . 29-19
Modification des paquets delta avant Extension de l’interface d’un serveur
la mise à jour de la base de données . . 28-10 d’applications transactionnel . . . . . 29-19
Comment contrôler l’application Gestion des transactions
des mises à jour . . . . . . . . . . . . . . 28-11 dans les applications multiniveaux . . . 29-19
Filtrage des mises à jour . . . . . . . . . . 28-13 Gestion des relations maître / détail . . . 29-20
Résolution des erreurs de mise à jour Gestion des informations d’état
par le fournisseur . . . . . . . . . . . . . 28-13 dans les modules de données distants . 29-21
Application des mises à jour à des ensembles Utilisation de plusieurs modules
de données représentant plusieurs de données distants . . . . . . . . . . . . 29-23
tables . . . . . . . . . . . . . . . . . . . . . 28-14 Recensement du serveur d’applications . . . 29-24
Comment répondre aux événements Création de l’application client . . . . . . . . 29-24
générés par le client . . . . . . . . . . . . . . 28-14 Connexion au serveur d’applications. . . 29-25
Gestion des contraintes du serveur . . . . . . 28-15 Spécification d’une connexion
à l’aide de DCOM . . . . . . . . . . . 29-26
Chapitre 29 Spécification d’une connexion
Création d’applications à l’aide de sockets . . . . . . . . . . . 29-27
multiniveaux 29-1 Spécification d’une connexion
Avantages du modèle de base de données à l’aide de HTTP . . . . . . . . . . . . 29-28
multiniveau . . . . . . . . . . . . . . . . . . . . 29-2 Spécification d’une connexion
Présentation des applications multiniveaux à l’aide de SOAP. . . . . . . . . . . . 29-28
basées sur les fournisseurs . . . . . . . . . . . 29-3 Courtage de connexions . . . . . . . . 29-29
Présentation d’une application Gestion des connexions serveur. . . . . . 29-29
à niveau triple . . . . . . . . . . . . . . . . 29-4 Connexion au serveur. . . . . . . . . . 29-30

xvii
Fermeture ou changement Obtention du paquet de données résultant 30-8
de connexion serveur. . . . . . . . . . 29-30 Conversion de nœuds définis
Appel des interfaces serveur . . . . . . . . 29-31 par l’utilisateur . . . . . . . . . . . . . . . 30-8
Connexion à un serveur d’applications qui Utilisation d’un document XML comme source
utilise plusieurs modules de données . . 29-32 pour un fournisseur . . . . . . . . . . . . . . 30-9
Ecriture des applications client Web . . . . . 29-33 Utilisation d’un document XML comme client
Distribution d’une application client en tant d’un fournisseur . . . . . . . . . . . . . . . 30-10
que contrôle ActiveX. . . . . . . . . . . . 29-34 Lecture d’un document XML
Création d’une fiche active à partir d’un fournisseur . . . . . . . . . 30-10
pour l’application client . . . . . . . . 29-34 Application de mises à jour d’un document
Construction des applications Web XML à un fournisseur . . . . . . . . . . .30-11
avec InternetExpress . . . . . . . . . . . . 29-35
Construction d’une application Partie III
InternetExpress . . . . . . . . . . . . . . . 29-36 Ecriture d’applications Internet
Utilisation des bibliothèques javascript 29-37
Droits d’accès au serveur d’applications Chapitre 31
et à son lancement . . . . . . . . . . . 29-38
Utilisation d’un courtier XML . . . . . . . 29-38 Ecriture d’applications CORBA 31-1
Lecture des paquets de données XML 29-39 Vue générale d’une application CORBA. . . . 31-2
Application des mises à jour Stubs et squelettes. . . . . . . . . . . . . . . 31-2
à partir des paquets delta XML. . . . 29-40 Utilisation de Smart Agent . . . . . . . . . 31-3
Création des pages Web avec un générateur Activation d’applications serveur . . . . . . 31-4
de page InternetExpress . . . . . . . . . . 29-41 Liaison dynamique d’appels d’interfaces . 31-4
Utilisation de l’éditeur de pages Web . 29-42 Ecriture de serveurs CORBA . . . . . . . . . . 31-5
Définition des propriétés Définition d’interfaces d’objets . . . . . . . 31-5
des éléments Web . . . . . . . . . . . . 29-43 Utilisation de l’expert serveur CORBA . . 31-6
Personnalisation du modèle d’un générateur Génération de stubs et de squelettes
de page InternetExpress . . . . . . . . 29-44 à partir d’un fichier IDL . . . . . . . . . . 31-6
Utilisation de l’expert d’implémentation
Chapitre 30 d’objet CORBA . . . . . . . . . . . . . . . 31-7
Instanciation des objets CORBA . . . . . 31-8
Utilisation de XML dans les applications Utilisation du modèle de délégation . . 31-9
de bases de données 30-1 Visualisation et changement
Définition des transformations. . . . . . . . . . 30-1 des modifications . . . . . . . . . . . 31-10
Correspondance entre les nœuds XML Implémentation des objets CORBA. . . . 31-10
et les champs du paquet de données . . . 30-2 Protection contre les conflits de thread 31-12
Utilisation de XMLMapper . . . . . . . . . . 30-4 Modification des interfaces CORBA . . . 31-13
Chargement d’un schéma XML Recensement d’interfaces serveur. . . . . 31-13
ou d’un paquet de données . . . . . . . 30-5 Ecriture de clients CORBA . . . . . . . . . . 31-14
Définition des mappages . . . . . . . . . 30-5 Utilisation des stubs . . . . . . . . . . . . 31-15
Génération de fichiers Utilisation de l’interface d’appel
de transformation . . . . . . . . . . . . . 30-6 dynamique . . . . . . . . . . . . . . . . . 31-16
Conversion de documents XML en paquets Test des serveurs CORBA . . . . . . . . . . . 31-18
de données . . . . . . . . . . . . . . . . . . . . 30-7 Configuration de l’outil de test . . . . . . 31-18
Spécification du document XML source . . 30-7 Enregistrement et exécution
Spécification de la transformation . . . . . . 30-7 de scripts de test. . . . . . . . . . . . . . 31-19

xviii
Chapitre 32 Type de méthode de requête . . . . . . . 33-7
Activation et désactivation
Création d’applications serveur des éléments d’action . . . . . . . . . . 33-7
Internet 32-1 Choix d’un élément d’action par défaut 33-7
A propos de WebBroker et de WebSnap . . . . 32-1 Réponse aux messages de requête
Terminologie et normes . . . . . . . . . . . . . . 32-3 avec des éléments d’action . . . . . . . . . 33-8
Composition d’une URL Envoi de la réponse . . . . . . . . . . . . 33-9
(Uniform Resource Locator) . . . . . . . . 32-4 Utilisation de plusieurs éléments
URI et URL . . . . . . . . . . . . . . . . . 32-4 d’action . . . . . . . . . . . . . . . . . . 33-9
En-tête de message de requête HTTP . . . . 32-4 Accès aux informations de requêtes client . . 33-9
Activité d’un serveur HTTP . . . . . . . . . . . 32-5 Propriétés contenant des informations
Composition des requêtes client . . . . . . . 32-5 d’en-tête de requête . . . . . . . . . . . . . 33-9
Traitement des requêtes client Propriétés identifiant la destination. . 33-10
par le serveur . . . . . . . . . . . . . . . . . 32-6 Propriétés décrivant le client Web. . . 33-10
Réponses aux requêtes client . . . . . . . . . 32-6 Propriétés identifiant le but
Types d’applications serveur Web . . . . . . . . 32-7 de la requête . . . . . . . . . . . . . . 33-10
ISAPI et NSAPI . . . . . . . . . . . . . . . 32-7 Propriétés décrivant la réponse
CGI autonome . . . . . . . . . . . . . . . 32-7 attendue . . . . . . . . . . . . . . . . . .33-11
WinCGI autonome . . . . . . . . . . . . . 32-7 Propriétés décrivant le contenu . . . . .33-11
Apache . . . . . . . . . . . . . . . . . . . . 32-7 Contenu d’un message de requête HTTP .33-11
Débogueur d’application Web . . . . . . 32-8 Création de messages de réponse HTTP . . .33-11
Conversion des types cibles Informations d’en-tête de réponse . . . . 33-12
d’applications serveur Web . . . . . . . . . 32-9 Indication du statut de la réponse . . 33-12
Débogage d’applications serveur . . . . . . . 32-10 Indication d’attente d’une action
Utilisation du débogueur du client. . . . . . . . . . . . . . . . . 33-12
d’application Web . . . . . . . . . . . . . 32-10 Description de l’application serveur . 33-12
Démarrage de l’application Description du contenu . . . . . . . . . 33-13
avec le débogueur d’application Web 32-10 Définition du contenu de la réponse . . . 33-13
Conversion de votre application en un autre Envoi de la réponse. . . . . . . . . . . . . 33-13
type d’application serveur Web. . . . 32-11 Génération du contenu des messages
Débogage d’applications Web de réponse . . . . . . . . . . . . . . . . . . . 33-14
sous forme de DLL. . . . . . . . . . . . . 32-11 Utilisation du composant
Droits des utilisateurs nécessaires au générateur de page . . . . . . . . . . . . 33-14
débogage des DLL . . . . . . . . . . . 32-12 Modèles HTML . . . . . . . . . . . . . 33-14
Choix du modèle HTML . . . . . . . . 33-15
Chapitre 33 Conversion des balises HTML
Utilisation de l’agent Web 33-1 transparentes . . . . . . . . . . . . . . 33-16
Création d’applications serveur Web Utilisation du générateur de page
avec l’agent Web . . . . . . . . . . . . . . . . . 33-1 depuis un élément d’action. . . . . . 33-16
Module Web . . . . . . . . . . . . . . . . . . 33-2 Chaînage de générateurs de page . . . 33-17
Objet application Web . . . . . . . . . . . . . 33-3 Utilisation des bases de données
Structure d’une application agent Web . . . . . 33-3 dans les réponses . . . . . . . . . . . . . . . 33-18
Répartiteur Web . . . . . . . . . . . . . . . . . . 33-4 Ajout d’une session au module Web . . . 33-19
Ajout d’actions au répartiteur . . . . . . . . 33-5 Représentation HTML
Répartition des messages de requête . . . . 33-5 d’une base de données . . . . . . . . . . 33-19
Eléments d’action . . . . . . . . . . . . . . . . . 33-6 Utilisation des générateurs
Choix du déclenchement de page ensemble de données . . . . 33-19
des éléments d’action . . . . . . . . . . . . 33-6 Utilisation des générateurs de tableau 33-20
URL de destination. . . . . . . . . . . . . 33-6 Choix des attributs de tableau . . . . . 33-20

xix
Choix des attributs de lignes . . . . . . 33-21 Etape 3. Ajout d’un composant
Choix des attributs de colonnes . . . . 33-21 adaptateur . . . . . . . . . . . . . . . 34-16
Incorporation de tableaux Création d’une grille pour afficher
dans un document HTML . . . . . . . 33-21 les données . . . . . . . . . . . . . . . . . 34-17
Configuration d’un générateur Etape 1. Ajout d’une grille . . . . . . . 34-17
de tableau ensemble de données . . . 33-21 Etape 2. Ajout de commandes
Configuration d’un générateur de modification à la grille . . . . . . 34-19
de tableau requête . . . . . . . . . . . 33-22 Ajout d’une fiche de modification . . . . 34-20
Etape 1. Ajout d’un nouveau module
Chapitre 34 de page Web . . . . . . . . . . . . . . 34-20
Création d’applications serveur Web Etape 2. Enregistrement
du nouveau module . . . . . . . . . . 34-20
avec WebSnap 34-1 Etape 3. Mise à disposition
Composants WebSnap de base. . . . . . . . . . 34-2
de CountryTableU pour le nouveau
Modules Web . . . . . . . . . . . . . . . . . . 34-2
module . . . . . . . . . . . . . . . . . 34-20
Types de module d’application Web . . . 34-3
Etape 4. Ajout des champs de saisie . 34-20
Modules de page Web . . . . . . . . . . . 34-4
Etape 5. Ajout de boutons . . . . . . . 34-21
Modules de données Web . . . . . . . . . 34-5
Etape 6. Liaison entre les actions
Adaptateurs . . . . . . . . . . . . . . . . . . . 34-6
de la fiche et la page de la grille. . . 34-22
Champs . . . . . . . . . . . . . . . . . . . 34-6
Etape 7. Liaison des actions de grille
Actions . . . . . . . . . . . . . . . . . . . . 34-6
avec la page de la fiche . . . . . . . . 34-23
Erreurs . . . . . . . . . . . . . . . . . . . . 34-7
Exécution de l’application complète . . . 34-23
Enregistrements . . . . . . . . . . . . . . . 34-7
Ajout du compte-rendu des erreurs . . . 34-24
Générateurs de page . . . . . . . . . . . . . . 34-7
Etape 1. Ajout de la gestion des erreurs
Création d’applications serveur Web
à la grille . . . . . . . . . . . . . . . . 34-24
avec WebSnap . . . . . . . . . . . . . . . . . . 34-8
Etape 2. Ajout de la gestion des erreurs
Sélection d’un type de serveur . . . . . . . . 34-9
à la fiche . . . . . . . . . . . . . . . . 34-24
Spécification des composants du module
Etape 3. Test du mécanisme de gestion
d’application . . . . . . . . . . . . . . . . . 34-9
des erreurs . . . . . . . . . . . . . . . 34-24
Sélection des options du module
Conception HTML avancée . . . . . . . . . . 34-25
d’application Web . . . . . . . . . . . . . 34-11
Manipulation de script côté serveur
Didacticiel WebSnap. . . . . . . . . . . . . . . 34-12
dans des fichiers HTML . . . . . . . . . 34-26
Création d’une nouvelle application . . . 34-12
Prise en charge des ouvertures de session . 34-27
Etape 1. Démarrage de l’expert
Ajout d’une prise en charge
d’application WebSnap. . . . . . . . . 34-12
des ouvertures de session . . . . . . . . 34-28
Etape 2. Enregistrement
Utilisation du service de sessions . . . . . 34-29
des fichiers générés et du projet . . . 34-13
Pages de connexion . . . . . . . . . . . . . 34-30
Etape 3. Spécification du titre
Configuration des pages nécessitant
de l’application . . . . . . . . . . . . . 34-13
des connexions. . . . . . . . . . . . . . . 34-32
Création d’une page CountryTable . . . . 34-13
Droits d’accès utilisateur . . . . . . . . . . 34-32
Etape 1. Ajout d’un nouveau module
Affichage dynamique des champs sous la
de page Web. . . . . . . . . . . . . . . 34-14
forme de zones de saisie ou de texte 34-33
Etape 2. Enregistrement du nouveau
Masquage des champs
module de page Web . . . . . . . . . . 34-14
et de leur contenu . . . . . . . . . . . 34-34
Ajout des composants de données
Interdiction d’accès à la page . . . . . 34-34
au module CountryTable . . . . . . . . . 34-15
Utilisation de scripts côté serveur
Etape 1. Ajout des composants
avec WebSnap . . . . . . . . . . . . . . . . . 34-34
orientés données . . . . . . . . . . . . 34-15
Scripts actifs . . . . . . . . . . . . . . . . . 34-35
Etape 2. Spécification d’un champ clé . 34-16
Moteur de script. . . . . . . . . . . . . . . 34-36

xx
Blocs de script . . . . . . . . . . . . . . . . 34-36 Utilisation de l’expert
Création de scripts . . . . . . . . . . . . . . 34-36 d’application SOAP . . . . . . . . . . . . 36-12
Experts modèles . . . . . . . . . . . . . 34-36 Ajout de nouveaux services Web . . . . . 36-13
TAdapterPageProducer . . . . . . . . . 34-36 Modification du code généré. . . . . . 36-13
Modification et visualisation des scripts . 34-37 Utilisation d’une classe de base
Comment inclure un script différente . . . . . . . . . . . . . . . . 36-14
dans une page . . . . . . . . . . . . . . . 34-37 Utilisation de l’importateur
Objets de script . . . . . . . . . . . . . . . . 34-37 de services Web . . . . . . . . . . . . . . 36-15
Répartition des requêtes et des réponses . . . 34-38 Création de classes d’exception personnalisées
Composants répartiteur . . . . . . . . . . . 34-38 pour les services Web . . . . . . . . . . . 36-16
Fonctions d’un répartiteur d’adaptateur . 34-39 Génération de documents WSDL
Utilisation de composants d’adaptateur pour une application de service Web . . 36-17
pour générer du contenu . . . . . . . 34-39 Conception de clients pour les services Web 36-18
Réception de requêtes de l’adaptateur Importation de documents WSDL . . . . 36-18
et génération des réponses . . . . . . 34-40 Appel des interfaces invocables . . . . . . 36-18
Requête d’image . . . . . . . . . . . . . 34-42
Réponse d’image . . . . . . . . . . . . . 34-42 Chapitre 37
Répartition des éléments d’action . . . . . 34-43 Utilisation des sockets 37-1
Fonctions du répartiteur de page . . . . . 34-44 Implémentation des services . . . . . . . . . . 37-1
Description des protocoles de services . . . 37-2
Chapitre 35 Communication avec les applications . 37-2
Utilisation de documents XML 35-1 Services et ports . . . . . . . . . . . . . . . . 37-2
Utilisation du modèle DOM . . . . . . . . . . . 35-2 Types de connexions par socket . . . . . . . . 37-2
Utilisation des composants XML . . . . . . . . 35-3 Connexions client . . . . . . . . . . . . . . . 37-3
Utilisation de TXMLDocument. . . . . . . . 35-3 Connexions d’écoute . . . . . . . . . . . . . 37-3
Utilisation des nœuds XML. . . . . . . . . . 35-4 Connexions serveur . . . . . . . . . . . . . . 37-3
Utilisation de la valeur d’un nœud . . . 35-5 Description des sockets . . . . . . . . . . . . . 37-3
Utilisation des attributs d’un nœud . . . 35-5 Description des hôtes . . . . . . . . . . . . . 37-4
Ajout et suppression de nœuds enfant . 35-5 Choix entre le nom de l’hôte
Abstraction de documents XML et son adresse IP . . . . . . . . . . . . . 37-5
avec l’expert Liaison de données . . . . . . . 35-6 Utilisation des ports . . . . . . . . . . . . . 37-5
Utilisation de l’expert Utilisation des composants socket . . . . . . . 37-5
Liaison de données XML . . . . . . . . . . 35-8 Obtenir des informations sur la connexion 37-6
Utilisation du code généré par l’expert Utilisation de sockets client . . . . . . . . . 37-6
Liaison de données XML . . . . . . . . . . 35-9 Désignation du serveur souhaité . . . . 37-6
Formation de la connexion . . . . . . . . 37-7
Chapitre 36 Obtention d’informations
Utilisation de services Web 36-1 sur la connexion . . . . . . . . . . . . . 37-7
Présentation des interfaces invocables . . . . . 36-2 Fermeture de la connexion . . . . . . . . 37-7
Utilisation de types non scalaires Utilisation de sockets serveur . . . . . . . . 37-7
dans des interfaces invocables . . . . . . . 36-4 Désignation du port . . . . . . . . . . . . 37-7
Recensement des types non scalaires . . 36-5 Ecoute des requêtes client . . . . . . . . 37-8
Recensement des types typedef Connexion aux clients. . . . . . . . . . . 37-8
et des types énumérés . . . . . . . . . . 36-6 Fermeture des connexions serveur . . . 37-8
Emploi d’objets distants . . . . . . . . . . 36-8 Réponse aux événements socket . . . . . . . . 37-8
Exemple d’objet distant . . . . . . . . . . 36-9 Evénements d’erreurs. . . . . . . . . . . . . 37-9
Conception de serveurs Evénements client . . . . . . . . . . . . . . . 37-9
gérant les services Web . . . . . . . . . . . . 36-11 Evénements serveur . . . . . . . . . . . . . 37-9
Conception d’un serveur de service Web . 36-11 Evénements d’écoute . . . . . . . . . . . 37-9

xxi
Evénements de connexions client . . . 37-10 Chapitre 39
Lectures et écritures sur des connexions
socket . . . . . . . . . . . . . . . . . . . . . . 37-10
Utilisation
Connexions non bloquantes . . . . . . . . 37-10 des bibliothèques de types 39-1
Lecture et écriture d’événements . . . . 37-11 L’éditeur de bibliothèques de types . . . . . . 39-2
Connexions bloquantes . . . . . . . . . . . 37-11 Composants de l’éditeur
de bibliothèques de types . . . . . . . . . 39-3
Partie IV Barre d’outils . . . . . . . . . . . . . . . 39-4
Volet liste des objets. . . . . . . . . . . . 39-5
Développement d’applications COM Barre d’état . . . . . . . . . . . . . . . . . 39-6
Les pages d’informations de type . . . . 39-6
Chapitre 38 Eléments d’une bibliothèque de types . . . 39-9
Présentation Interfaces . . . . . . . . . . . . . . . . . . 39-9
des technologies COM 38-1 Dispinterfaces . . . . . . . . . . . . . . 39-10
COM, spécification et implémentation . 38-2 CoClasses . . . . . . . . . . . . . . . . . 39-10
Extensions de COM . . . . . . . . . . . . 38-2 Définitions de types . . . . . . . . . . . 39-10
Composantes d’une application COM . . . . . 38-3 Modules. . . . . . . . . . . . . . . . . . .39-11
Interfaces COM. . . . . . . . . . . . . . . . . 38-3 Utilisation de l’éditeur de bibliothèques
L’interface COM de base, IUnknown . . 38-4 de types. . . . . . . . . . . . . . . . . . . 39-12
Pointeurs d’interface COM . . . . . . . . 38-5 Types autorisés. . . . . . . . . . . . . . 39-13
Serveurs COM . . . . . . . . . . . . . . . . . 38-5 Création d’une nouvelle bibliothèque
CoClasses et fabricants de classes . . . . 38-6 de types . . . . . . . . . . . . . . . . . 39-14
Serveurs en processus, hors processus Ouverture d’une bibliothèque de types
et distants . . . . . . . . . . . . . . . . . 38-7 existante . . . . . . . . . . . . . . . . . 39-15
Le mécanisme du marshaling. . . . . . . 38-8 Ajout d’une interface à une bibliothèque
Agrégation. . . . . . . . . . . . . . . . . . 38-9 de types . . . . . . . . . . . . . . . . . 39-15
Clients COM . . . . . . . . . . . . . . . . . 38-10 Modification d’une interface en utilisant
Extensions de COM . . . . . . . . . . . . . . . 38-10 la bibliothèque de types . . . . . . . 39-15
Serveurs Automation . . . . . . . . . . . . 38-13 Ajout de propriétés et méthodes
Pages Active Server . . . . . . . . . . . . . 38-14 à une interface ou dispinterface . . . 39-16
Contrôles ActiveX . . . . . . . . . . . . . . 38-14 Ajout d’une CoClasse à une bibliothèque
Documents Active . . . . . . . . . . . . . . 38-15 de types . . . . . . . . . . . . . . . . . 39-17
Objets transactionnels . . . . . . . . . . . . 38-15 Ajout d’une interface à une CoClasse 39-18
Objets événement COM+ et souscripteurs Ajout d’une énumération à une bibliothèque
d’événement . . . . . . . . . . . . . . . . 38-16 de types . . . . . . . . . . . . . . . . . 39-18
Bibliothèques de types . . . . . . . . . . . 38-17 Ajout d’un alias à une bibliothèque
Contenu d’une bibliothèque de types . 38-17 de types . . . . . . . . . . . . . . . . . 39-18
Création de bibliothèques de types . . 38-18 Ajout d’un enregistrement ou d’une union
Quand utiliser les bibliothèques à une bibliothèque de types . . . . . 39-19
de types . . . . . . . . . . . . . . . . . 38-18 Ajout d’un module à une bibliothèque
Accès aux bibliothèques de types . . . 38-19 de types . . . . . . . . . . . . . . . . . 39-19
Avantages des bibliothèques de types . 38-19 Enregistrement et recensement
Utilisation des outils de bibliothèques des informations d’une bibliothèque
de types . . . . . . . . . . . . . . . . . 38-20 de types . . . . . . . . . . . . . . . . . 39-19
Implémentation des objets COM Enregistrement d’une bibliothèque
à l’aide d’experts . . . . . . . . . . . . . . . . 38-20 de types . . . . . . . . . . . . . . . . . 39-20
Code généré par les experts . . . . . . . . 38-23

xxii
Rafraîchissement de la bibliothèque Utilisation de l’expert objet COM . . . . . . . 41-3
de types . . . . . . . . . . . . . . . . . 39-20 Utilisation de l’expert objet Automation . . . 41-4
Recensement d’une bibliothèque Choix d’un modèle de thread . . . . . . . . 41-5
de types . . . . . . . . . . . . . . . . . 39-21 Ecriture d’un objet supportant
Exportation d’un fichier IDL . . . . . . 39-21 le modèle de thread libre . . . . . . . . 41-7
Déploiement des bibliothèques de types . . . 39-21 Ecriture d’un objet supportant
le modèle de thread apartment . . . . 41-8
Chapitre 40 Ecriture d’un objet supportant
Création de clients COM 40-1 le modèle de thread neutre . . . . . . . 41-8
Importation des informations Spécification des options ATL . . . . . . . . . 41-9
d’une bibliothèque de types . . . . . . . . . . 40-2 Définition de l’interface d’un objet COM . . 41-10
Utilisation de la boîte de dialogue Importation Ajout d’une propriété
de bibliothèque de types . . . . . . . . . . 40-3 à l’interface de l’objet . . . . . . . . . . . 41-10
Utilisation de la boîte de dialogue Ajout d’une méthode
Importation d’ActiveX . . . . . . . . . . . . 40-4 à l’interface de l’objet . . . . . . . . . . . .41-11
Code généré par l’importation des Exposition d’événements aux clients . . . .41-11
informations d’une bibliothèque de types 40-5 Gestion des événements
Contrôle d’un objet importé . . . . . . . . . . . 40-7 dans un objet Automation . . . . . . 41-12
Utilisation des composants enveloppe . . . 40-7 Interfaces d’Automation . . . . . . . . . . . . 41-13
Enveloppes ActiveX . . . . . . . . . . . . 40-8 Interfaces doubles . . . . . . . . . . . . . . 41-13
Enveloppes des serveurs Automation . . 40-8 Interfaces de répartition . . . . . . . . . . 41-14
Utilisation de contrôles ActiveX Interfaces personnalisées . . . . . . . . . . 41-15
orientés données . . . . . . . . . . . . . . . 40-9 Marshaling des données . . . . . . . . . . . . 41-15
Exemple : impression d’un document Types compatibles avec l’Automation . . 41-16
avec Microsoft Word . . . . . . . . . . . . 40-11 Restrictions de type
Etape 1 : préparation de C++Builder pour le marshaling automatique . . . . 41-16
pour cet exemple . . . . . . . . . . . . 40-11 Marshaling personnalisé . . . . . . . . . . 41-17
Etape 2 : importation de la bibliothèque Recensement d’un objet COM . . . . . . . . 41-17
de types Word. . . . . . . . . . . . . . 40-12 Recensement d’un serveur en processus . 41-17
Etape 3 : utilisation d’un objet interface Recensement d’un serveur
VTable ou de répartition hors processus . . . . . . . . . . . . . . . 41-18
pour contrôler Microsoft Word . . . . 40-12 Test et débogage de l’application . . . . . . . 41-18
Etape 4 : nettoyage de l’exemple . . . . 40-13
Ecriture de code client basé sur les définitions Chapitre 42
de la bibliothèque de types . . . . . . . . 40-14 Création d’une page Active Server 42-1
Connexion à un serveur . . . . . . . . . 40-14 Création d’un objet Active Server . . . . . . . 42-2
Contrôle d’un serveur Automation Utilisation des éléments intrinsèques ASP. 42-3
en utilisant une interface double . . . 40-14 Application . . . . . . . . . . . . . . . . . 42-4
Contrôle d’un serveur Automation en Request . . . . . . . . . . . . . . . . . . . 42-4
utilisant une interface de répartition . 40-15 Response . . . . . . . . . . . . . . . . . . 42-5
Gestion des événements Session . . . . . . . . . . . . . . . . . . . 42-6
dans un contrôleur Automation . . . 40-16 Server . . . . . . . . . . . . . . . . . . . . 42-7
Création de clients pour les serveurs Création d’ASP pour des serveurs
n’ayant pas une bibliothèque de types . . . 40-18 en et hors processus. . . . . . . . . . . . . 42-7
Recensement d’un objet Active Server. . . . . 42-8
Chapitre 41 Recensement d’un serveur en processus . . 42-8
Création de serveurs COM simples 41-1 Recensement d’un serveur hors processus 42-9
Présentation de la création d’un objet COM . . 41-2 Test et débogage d’une application ASP . . . 42-9
Conception d’un objet COM . . . . . . . . . . . 41-2

xxiii
Chapitre 43 Regroupement des ressources . . . . . . . . 44-6
Fournisseurs de ressources
Création d’un contrôle ActiveX 43-1 base de données . . . . . . . . . . . . . 44-6
Présentation de la création
Gestionnaire de propriétés partagées . . 44-7
d’un contrôle ActiveX . . . . . . . . . . . . . . 43-2
Libération des ressources . . . . . . . . 44-10
Eléments d’un contrôle ActiveX . . . . . . . 43-3
Regroupement d’objets . . . . . . . . . . . 44-10
Contrôle VCL . . . . . . . . . . . . . . . . 43-3
Support transactionnel MTS et COM+. . . . .44-11
Enveloppe ActiveX . . . . . . . . . . . . . 43-3
Attributs transactionnels . . . . . . . . . . 44-12
Bibliothèque de types . . . . . . . . . . . 43-3
Initialisation de l’attribut
Page de propriétés . . . . . . . . . . . . . 43-4
transactionnel. . . . . . . . . . . . . . 44-13
Conception d’un contrôle ActiveX . . . . . . . 43-4
Objets avec état et sans état . . . . . . . . 44-13
Génération d’un contrôle ActiveX
Contrôle de l’arrêt des transactions. . . . 44-14
à partir d’un contrôle VCL . . . . . . . . . . . 43-4
Démarrage des transactions . . . . . . . . 44-14
Génération d’un contrôle ActiveX
Définition d’un objet transaction
basé sur une fiche VCL . . . . . . . . . . . . . 43-6
côté client . . . . . . . . . . . . . . . . 44-15
Licences des contrôles ActiveX . . . . . . . . . 43-8
Définition d’un objet transaction
Personnalisation de l’interface
côté serveur. . . . . . . . . . . . . . . 44-16
du contrôle ActiveX . . . . . . . . . . . . . . . 43-9
Délais des transactions . . . . . . . . . . . 44-17
Ajout de propriétés, méthodes
Sécurité en fonction des rôles . . . . . . . . . 44-17
et événements supplémentaires . . . . . 43-10
Présentation de la création
Ajout de propriétés et de méthodes . . 43-10
des objets transactionnels . . . . . . . . . . 44-18
Ajout d’événement . . . . . . . . . . . . 43-12
Utilisation de l’expert objet transactionnel . 44-19
Activation de la liaison de données simple
Choix d’un modèle de thread
avec la bibliothèque de types . . . . . . . 43-12
pour un objet transactionnel . . . . . . . 44-20
Création d’une page de propriétés
Activités. . . . . . . . . . . . . . . . . . 44-21
pour un contrôle ActiveX . . . . . . . . . . . 43-14
Génération d’événements dans COM+ . . . 44-22
Création d’une nouvelle page
Utilisation de l’expert objet événement . 44-24
de propriétés . . . . . . . . . . . . . . . . 43-15
Utilisation de l’expert Objet Abonnement
Ajout de contrôles à une page
d’événement COM+. . . . . . . . . . . . 44-25
de propriétés . . . . . . . . . . . . . . . . 43-15
Déclenchement d’événement en utilisant
Association des contrôles
un objet événement COM+ . . . . . . . 44-26
de la page de propriétés
Transfert de références d’objets . . . . . . . . 44-27
aux propriétés du contrôle ActiveX . . . 43-15
Utilisation de la méthode SafeRef . . . 44-27
Actualisation de la page de propriétés 43-16
Callbacks . . . . . . . . . . . . . . . . . 44-28
Actualisation de l’objet . . . . . . . . . 43-16
Débogage et test des objets transactionnels . 44-28
Connexion d’une page de propriétés
Installation d’objets transactionnels . . . . . 44-29
à un contrôle ActiveX . . . . . . . . . . . 43-16
Administration d’objets transactionnels . . . 44-30
Recensement d’un contrôle ActiveX . . . . . 43-17
Test d’un contrôle ActiveX . . . . . . . . . . . 43-17
Déploiement d’un contrôle ActiveX
Partie V
sur le Web. . . . . . . . . . . . . . . . . . . . 43-18 Création de composants
Paramétrage des options . . . . . . . . . . 43-19 personnalisés
Chapitre 44 Chapitre 45
Création d’objets MTS ou COM+ 44-1 Présentation générale
Principe des objets transactionnels . . . . . . . 44-2
Contraintes d’un objet transactionnel . . . . 44-3 de la création d’un composant 45-1
Gestion des ressources . . . . . . . . . . . . . . 44-4 Bibliothèques de classes . . . . . . . . . . . . . 45-1
Accès au contexte d’un objet . . . . . . . . . 44-4 Composants et classes . . . . . . . . . . . . . . 45-2
Activation juste-à-temps . . . . . . . . . . . 44-5 Comment créer un composant ? . . . . . . . . 45-3

xxiv
Modification de contrôles existants . . . . . 45-3 Définition de l’interface d’exécution . . . . 46-7
Création de contrôles fenêtrés . . . . . . . . 45-4 Définition de l’interface de conception. . . 46-8
Création de contrôles graphiques . . . . . . 45-4 Répartition des méthodes . . . . . . . . . . . . 46-9
Sous-classement de contrôles Windows. . . 45-5 Méthodes standard . . . . . . . . . . . . . . 46-9
Création de composants non visuels . . . . 45-5 Méthodes virtuelles . . . . . . . . . . . . . 46-10
Contenu d’un composant ? . . . . . . . . . . . . 45-5 Surcharge des méthodes . . . . . . . . 46-10
Suppression des dépendances . . . . . . . . 45-6 Membres abstraits d’une classe . . . . . . . . .46-11
Définition des propriétés, méthodes Classes et pointeurs . . . . . . . . . . . . . . .46-11
et événements. . . . . . . . . . . . . . . . . 45-6
Propriétés . . . . . . . . . . . . . . . . . . 45-6 Chapitre 47
Evénements . . . . . . . . . . . . . . . . . 45-7 Création de propriétés 47-1
Méthodes . . . . . . . . . . . . . . . . . . 45-7 Pourquoi créer des propriétés ? . . . . . . . . . 47-1
Encapsulation des graphiques . . . . . . . . 45-8 Types de propriétés. . . . . . . . . . . . . . . . 47-2
Recensement des composants . . . . . . . . 45-9 Publication des propriétés héritées . . . . . . . 47-3
Création d’un nouveau composant . . . . . . . 45-9 Définition des propriétés . . . . . . . . . . . . 47-4
Création d’un composant Déclaration des propriétés . . . . . . . . . . 47-4
avec l’expert composant . . . . . . . . . . 45-10 Stockage interne des données . . . . . . . . 47-4
Création manuelle d’un composant . . . . 45-12 Accès direct . . . . . . . . . . . . . . . . . . 47-5
Création d’un fichier unité . . . . . . . 45-13 Méthodes d’accès . . . . . . . . . . . . . . . 47-5
Dérivation du composant . . . . . . . . 45-13 Méthode read . . . . . . . . . . . . . . . 47-7
Déclaration d’un nouveau Méthode write . . . . . . . . . . . . . . . 47-7
constructeur . . . . . . . . . . . . . . . 45-14 Valeurs par défaut d’une propriété . . . . . 47-8
Recensement du composant. . . . . . . 45-14 Spécification d’aucune
Création de bitmaps pour les composants 45-16 valeur par défaut . . . . . . . . . . . . 47-8
Test des composants non installés. . . . . . . 45-17 Création de propriétés tableau . . . . . . . . . 47-9
Test des composants installés . . . . . . . . . 45-19 Création de propriétés
Installation d’un composant pour les sous-composants . . . . . . . . . . 47-10
dans la palette de composants . . . . . . . . 45-20 Stockage et chargement des propriétés . . . .47-11
Emplacement des fichiers du composant . 45-20 Utilisation du mécanisme de stockage
Ajout du composant . . . . . . . . . . . . . 45-21 et de chargement . . . . . . . . . . . . . 47-12
Spécification des valeurs par défaut . . . 47-12
Chapitre 46 Détermination du stockage . . . . . . . . 47-13
Programmation orientée objet Initialisation après chargement . . . . . . 47-14
et écriture des composants 46-1 Stockage et chargement des propriétés
Définition de nouvelles classes . . . . . . . . . 46-1 non publiées . . . . . . . . . . . . . . . . 47-14
Dérivation de nouvelles classes . . . . . . . 46-2 Création de méthodes pour le stockage et le
Modifier les valeurs par défaut chargement de valeurs de propriétés 47-15
d’une classe pour éviter Redéfinition de la méthode
les répétitions . . . . . . . . . . . . . . . 46-2 DefineProperties . . . . . . . . . . . . 47-15
Ajout de nouvelles capacités
à une classe . . . . . . . . . . . . . . . . 46-3 Chapitre 48
Déclaration d’une nouvelle classe Création d’événements 48-1
de composant . . . . . . . . . . . . . . . . . 46-3 Qu’est-ce qu’un événement ? . . . . . . . . . . 48-1
Ancêtres, descendants et hiérarchies Les événements sont des closures . . . . . 48-2
des classes. . . . . . . . . . . . . . . . . . . . . 46-4 Les événements sont des propriétés . . . . 48-2
Contrôle des accès . . . . . . . . . . . . . . . . . 46-4 Les types d’événements
Masquer les détails d’implémentation . . . 46-5 sont des types de closures . . . . . . . . . 48-3
Définition de l’interface avec le concepteur Le type de renvoi des gestionnaires
des composants . . . . . . . . . . . . . . . . 46-7 d’événements est void . . . . . . . . . 48-3

xxv
Les gestionnaires d’événements Spécification d’une palette
sont facultatifs . . . . . . . . . . . . . . . . 48-4 pour un contrôle . . . . . . . . . . . . . 50-6
Implémentation des événements standard . . . 48-4 Réponse aux changements de palette. . 50-6
Identification des événements standard. . . 48-5 Bitmaps hors écran . . . . . . . . . . . . . . . . 50-6
Evénements standard Création et gestion des bitmaps hors écran 50-7
pour tous les contrôles . . . . . . . . . . 48-5 Copie des images bitmap . . . . . . . . . . 50-7
Evénements standard Réponse aux changements . . . . . . . . . . . 50-7
pour les contrôles standard . . . . . . . 48-5
Rendre visibles des événements . . . . . . . 48-5 Chapitre 51
Changement de la gestion Gestion des messages
des événements standard . . . . . . . . . . 48-6
Définition de vos propres événements . . . . . 48-7
et des notifications système 51-1
Compréhension du système
Déclenchement de l’événement . . . . . . . 48-7
de gestion des messages . . . . . . . . . . . . 51-1
Deux sortes d’événements. . . . . . . . . 48-7
Que contient un message Windows ? . . . 51-2
Définition du type de gestionnaire . . . . . 48-8
Répartition des messages . . . . . . . . . . 51-3
Notifications simples . . . . . . . . . . . . 48-8
Suivi du flux des messages . . . . . . . 51-3
Gestionnaires d’événements spécifiques. 48-8
Modification de la gestion des messages . . . 51-4
Renvoi d’informations
Surcharge de la méthode du gestionnaire . 51-4
à partir du gestionnaire . . . . . . . . . 48-8
Utilisation des paramètres d’un message . 51-5
Déclaration de l’événement . . . . . . . . . . 48-9
Interception des messages . . . . . . . . . . 51-5
Les noms d’événement débutent
Création de nouveaux gestionnaires
par “On” . . . . . . . . . . . . . . . . . . 48-9
de messages . . . . . . . . . . . . . . . . . . . 51-6
Appel de l’événement . . . . . . . . . . . . . 48-9
Définition de vos propres messages . . . . 51-6
Les gestionnaires vides
Déclaration d’un identificateur
doivent être valides. . . . . . . . . . . . 48-9
de message . . . . . . . . . . . . . . . . 51-6
Les utilisateurs peuvent surcharger
Déclaration d’un type
la gestion par défaut . . . . . . . . . . 48-10
structure de message . . . . . . . . . . 51-7
Déclaration d’une nouvelle méthode
Chapitre 49 de gestion d’un message . . . . . . . . . . 51-8
Création de méthodes 49-1 Envoi des messages . . . . . . . . . . . . . . 51-8
Eviter les interdépendances . . . . . . . . . . . 49-1 Diffusion d’un message
Noms des méthodes. . . . . . . . . . . . . . . . 49-2 à tous les contrôles d’une fiche . . . . 51-9
Protection des méthodes . . . . . . . . . . . . . 49-3 Appel direct du gestionnaire
Méthodes qui doivent être publiques . . . . 49-3 de message d’un contrôle. . . . . . . . 51-9
Méthodes qui doivent être protégées . . . . 49-3 Envoi d’un message à l’aide de la file
Rendre virtuelles des méthodes . . . . . . . . . 49-4 d’attente des messages Windows . . 51-10
Déclaration des méthodes . . . . . . . . . . . . 49-4 Envoi d’un message qui ne s’exécute pas
immédiatement. . . . . . . . . . . . . 51-10
Chapitre 50 Réponse aux notifications du système
Graphiques et composants 50-1 à l’aide de CLX . . . . . . . . . . . . . . . . .51-11
Présentation des graphiques . . . . . . . . . . . 50-1 Réponse aux signaux . . . . . . . . . . . . .51-11
Utilisation du canevas . . . . . . . . . . . . . . 50-3 Affectation de gestionnaires
Travail sur les images . . . . . . . . . . . . . . . 50-3 de signaux personnalisés . . . . . . . 51-12
Utilisation d’une image, d’un graphique Réponse aux événements système . . . . 51-13
ou d’un canevas . . . . . . . . . . . . . . . 50-4 Evénements couramment utilisés . . . 51-14
Chargement et stockage des graphiques . . 50-4 Surcharge de la méthode EventFilter . 51-15
Gestion des palettes . . . . . . . . . . . . . . 50-5 Génération des événements Qt . . . . 51-16

xxvi
Chapitre 52 Chapitre 53
Accessibilité des composants Modification
au moment de la conception 52-1 d’un composant existant 53-1
Recensement des composants . . . . . . . . . . 52-1 Création et recensement du composant . . . . 53-1
Déclaration de la fonction Register . . . . . 52-2 Modification de la classe composant. . . . . . 53-3
Ecriture de la fonctionRegister . . . . . . . . 52-2 Surcharge du constructeur . . . . . . . . . . 53-3
Spécification des composants . . . . . . . 52-2 Spécification de la nouvelle valeur
Spécification de la page de palette . . . . 52-3 par défaut de la propriété . . . . . . . . . 53-4
Utilisation de la fonction
RegisterComponents . . . . . . . . . . . 52-3 Chapitre 54
Ajout de bitmaps à la palette . . . . . . . . . . 52-4 Création d’un contrôle graphique 54-1
Fournir l’aide pour vos composants . . . . . . 52-5 Création et recensement du composant . . . . 54-1
Création du fichier d’aide. . . . . . . . . . . 52-5 Publication des propriétés héritées . . . . . . . 54-3
Création des entrées . . . . . . . . . . . . 52-5 Ajout de fonctionnalités graphiques . . . . . . 54-3
Aide contextuelle des composants . . . . 52-7 Détermination de ce qui doit être dessiné . 54-4
Ajout des fichiers d’aide Déclaration du type de la propriété. . . 54-4
des composants . . . . . . . . . . . . . . 52-7 Déclaration de la propriété . . . . . . . . 54-4
Ajout d’éditeurs de propriétés . . . . . . . . . . 52-8 Ecriture de la méthode
Dérivation d’une classe d’implémentation . . . . . . . . . . . . 54-5
éditeur de propriétés. . . . . . . . . . . . . 52-8 Surcharge du constructeur
Modification de la propriété et du destructeur . . . . . . . . . . . . . . 54-5
sous une forme textuelle . . . . . . . . . . 52-9 Modification des valeurs par défaut
Affichage de la valeur de la propriété . 52-10 des propriétés . . . . . . . . . . . . . . 54-5
Définition de la valeur de la propriété 52-10 Publication du crayon et du pinceau . . . . 54-6
Modification globale de la propriété . . . 52-10 Déclaration des données membres . . . 54-6
Spécification des attributs de l’éditeur . . 52-11 Déclaration des propriétés d’accès . . . 54-7
Recensement de l’éditeur de propriétés. . 52-12 Initialisation des classes
Catégories de propriété . . . . . . . . . . . . . 52-13 ayant un propriétaire . . . . . . . . . . 54-8
Recensement d’une propriété à la fois . . 52-14 Définition des propriétés des classes
Recensement de plusieurs propriétés ayant un propriétaire . . . . . . . . . . 54-8
en une seule fois . . . . . . . . . . . . . . 52-14 Dessin de l’image du composant . . . . . . 54-9
Spécification de catégories de propriétés . 52-15 Adaptation du dessin de la forme . . . . 54-10
Utilisation de la fonction
IsPropertyInCategory . . . . . . . . . . . 52-16 Chapitre 55
Ajout d’éditeurs de composants . . . . . . . . 52-17 Personnalisation d’une grille 55-1
Ajout d’éléments au menu contextuel. . . 52-17 Création et recensement du composant . . . . 55-1
Spécification d’éléments de menu . . . 52-17 Publication des propriétés héritées . . . . . . . 55-3
Implémentation des commandes . . . . 52-18 Modification des valeurs initiales . . . . . . . 55-4
Modification du comportement suite Redimensionnement des cellules . . . . . . . . 55-5
à un double-clic. . . . . . . . . . . . . . . 52-18 Remplissage des cellules. . . . . . . . . . . . . 55-6
Ajout de formats de Presse-papiers . . . . 52-19 Suivi de la date . . . . . . . . . . . . . . . . 55-6
Recensement d’un éditeur de composants 52-20 Stockage interne de la date. . . . . . . . 55-7
Compilation des composants en paquets. . . 52-20 Accès au jour, au mois et à l’année . . . 55-8
Problèmes d’installation Génération des numéros de jours . . . . 55-9
de composants personnalisés. . . . . . . . . 52-21 Sélection du jour en cours . . . . . . . .55-11
Navigation de mois en mois
et d’année en année . . . . . . . . . . . . . 55-12

xxvii
Navigation de jour en jour . . . . . . . . . . . 55-13 Chapitre 58
Déplacement de la sélection . . . . . . . . 55-13
Fourniture d’un événement OnChange . . 55-13
Extensions de l’EDI 58-1
Présentation de l’API Tools . . . . . . . . . . . 58-2
Exclusion des cellules vides . . . . . . . . 55-14
Conception d’une classe expert . . . . . . . . . 58-3
Implémentation des interfaces de l’expert . 58-4
Chapitre 56 Simplification de l’implémentation
Contrôles orientés données 56-1 d’interfaces . . . . . . . . . . . . . . . . . . 58-6
Création d’un contrôle Installation du paquet de l’expert. . . . . . 58-7
pour scruter les données . . . . . . . . . . . . 56-2 Accès aux services de l’API Tools . . . . . . . 58-8
Création et recensement du composant . . . 56-2 Utilisation d’objets natifs de l’EDI . . . . . 58-9
Fonctionnement du contrôle Utilisation de l’interface INTAServices . 58-9
en lecture seulement . . . . . . . . . . . . . 56-3 Ajout d’une image à la liste d’images . 58-9
Ajout de la propriété ReadOnly . . . . . 56-3 Ajout d’une action à la liste d’actions 58-10
Autorisation des mises à jour Suppression de boutons
nécessaires . . . . . . . . . . . . . . . . . 56-4 de barres d’outils . . . . . . . . . . . .58-11
Ajout du lien aux données . . . . . . . . . . 56-5 Débogage d’un expert . . . . . . . . . . . 58-12
Déclaration de la donnée membre . . . . 56-6 Numéros de version de l’interface . . . . 58-12
Déclaration des propriétés d’accès . . . . 56-6 Utilisation des fichiers et des éditeurs . . . . 58-13
Exemple de déclaration Utilisation des interfaces de module . . . 58-14
des propriétés d’accès . . . . . . . . . . 56-6 Utilisation des interfaces d’éditeur . . . . 58-14
Initialisation du lien de données . . . . . 56-7 Création de fiches et de projets . . . . . . . . 58-15
Réponse aux changements de données . . . 56-8 Création de modules . . . . . . . . . . . . 58-15
Création d’un contrôle de modification Notification d’un expert
de données . . . . . . . . . . . . . . . . . . . . 56-9 des événements de l’EDI. . . . . . . . . . . 58-19
Modification de la valeur par défaut Installation d’une DLL expert. . . . . . . . . 58-23
de FReadOnly. . . . . . . . . . . . . . . . . 56-9 Utilisation d’une DLL
Gestion des messages liés à la souris sans paquets d’exécution . . . . . . . . . 58-25
ou au clavier . . . . . . . . . . . . . . . . . 56-9
Réponse aux messages indiquant Annexe A
la manipulation de la souris. . . . . . 56-10 Implémentations spécifiques
Réponse aux messages indiquant
la manipulation du clavier . . . . . . 56-11 de la norme ANSI A-1
Mise à jour de la classe lien de données
sur un champ . . . . . . . . . . . . . . . . 56-12
Annexe B
Modification de la méthode Change . . . 56-12 Référence de scripts
Mise à jour de l’ensemble de données . . 56-13 côté serveur WebSnap B-1
Types d’objets . . . . . . . . . . . . . . . . . . . . B-2
Chapitre 57 Type Adapter . . . . . . . . . . . . . . . . . . B-2
Transformation d’une boîte Propriétés . . . . . . . . . . . . . . . . . . . B-3
de dialogue en composant 57-1 Type AdapterAction . . . . . . . . . . . . . . B-4
Propriétés . . . . . . . . . . . . . . . . . . . B-5
Définition de l’interface du composant . . . . . 57-2
Méthodes . . . . . . . . . . . . . . . . . . . B-6
Création et recensement du composant . . . . 57-2
Type AdapterErrors . . . . . . . . . . . . . . . B-6
Création de l’interface du composant. . . . . . 57-3
Propriétés . . . . . . . . . . . . . . . . . . . B-6
Inclusion des fichiers de l’unité de la fiche. 57-4
Type AdapterField . . . . . . . . . . . . . . . B-7
Ajout des propriétés de l’interface . . . . . . 57-4
Propriétés . . . . . . . . . . . . . . . . . . . B-7
Ajout de la méthode Execute . . . . . . . . . 57-5
Méthodes . . . . . . . . . . . . . . . . . . B-10
Test du composant. . . . . . . . . . . . . . . . . 57-7
Type AdapterFieldValues . . . . . . . . . . B-10
Propriétés . . . . . . . . . . . . . . . . . . B-10

xxviii
Méthodes . . . . . . . . . . . . . . . . . .B-11 Propriétés . . . . . . . . . . . . . . . . . . B-19
Type AdapterFieldValuesList . . . . . . . . .B-11 Méthodes . . . . . . . . . . . . . . . . . . B-19
Propriétés . . . . . . . . . . . . . . . . . .B-11 Objet Session. . . . . . . . . . . . . . . . . . B-19
Méthodes . . . . . . . . . . . . . . . . . .B-12 Propriétés . . . . . . . . . . . . . . . . . . B-19
Type AdapterHiddenFields . . . . . . . . . .B-12 Exemples JScript . . . . . . . . . . . . . . . . . B-20
Propriétés . . . . . . . . . . . . . . . . . .B-12 Exemple 1 . . . . . . . . . . . . . . . . . . . B-21
Méthodes . . . . . . . . . . . . . . . . . .B-12 Exemple 2 . . . . . . . . . . . . . . . . . . . B-21
Type AdapterImage . . . . . . . . . . . . . .B-12 Exemple 3 . . . . . . . . . . . . . . . . . . . B-22
Propriétés . . . . . . . . . . . . . . . . . .B-12 Exemple 4 . . . . . . . . . . . . . . . . . . . B-22
Type Module . . . . . . . . . . . . . . . . . .B-13 Exemple 5 . . . . . . . . . . . . . . . . . . . B-22
Propriétés . . . . . . . . . . . . . . . . . .B-13 Exemple 6 . . . . . . . . . . . . . . . . . . . B-23
Type Page . . . . . . . . . . . . . . . . . . . .B-13 Exemple 7 . . . . . . . . . . . . . . . . . . . B-23
Propriétés . . . . . . . . . . . . . . . . . .B-13 Exemple 8 . . . . . . . . . . . . . . . . . . . B-24
Objets globaux . . . . . . . . . . . . . . . . . . .B-14 Exemple 9 . . . . . . . . . . . . . . . . . . . B-24
Objet Application . . . . . . . . . . . . . . .B-15 Exemple 10 . . . . . . . . . . . . . . . . . . . B-25
Propriétés . . . . . . . . . . . . . . . . . .B-15 Exemple 11 . . . . . . . . . . . . . . . . . . . B-27
Méthodes . . . . . . . . . . . . . . . . . .B-16 Exemple 12 . . . . . . . . . . . . . . . . . . . B-28
Objet EndUser . . . . . . . . . . . . . . . . .B-16 Exemple 13 . . . . . . . . . . . . . . . . . . . B-29
Propriétés . . . . . . . . . . . . . . . . . .B-16 Exemple 14 . . . . . . . . . . . . . . . . . . . B-30
Objet Modules . . . . . . . . . . . . . . . . .B-17 Exemple 15 . . . . . . . . . . . . . . . . . . . B-32
Objet page. . . . . . . . . . . . . . . . . . . .B-17 Exemple 16 . . . . . . . . . . . . . . . . . . . B-33
Objet pages . . . . . . . . . . . . . . . . . . .B-17 Exemple 17 . . . . . . . . . . . . . . . . . . . B-34
Objet Producer . . . . . . . . . . . . . . . . .B-17 Exemple 18 . . . . . . . . . . . . . . . . . . . B-35
Propriétés . . . . . . . . . . . . . . . . . .B-18 Exemple 19 . . . . . . . . . . . . . . . . . . . B-36
Méthodes . . . . . . . . . . . . . . . . . .B-18 Exemple 20 . . . . . . . . . . . . . . . . . . . B-36
Objet Request . . . . . . . . . . . . . . . . . .B-18 Exemple 21 . . . . . . . . . . . . . . . . . . . B-37
Propriétés . . . . . . . . . . . . . . . . . .B-18 Exemple 22 . . . . . . . . . . . . . . . . . . . B-38
Objet Response . . . . . . . . . . . . . . . . .B-19

xxix
xxx
Chapitre

1
Introduction
Chapitre 1

Ce manuel aborde des notions de développement intermédiaires et avancées.


Il traite notamment de la création d’applications de bases de données client/
serveur, de l’écriture de composants personnalisés, de la création d’applications
serveurs Web Internet et du support des spécifications de nombreux standards
comme SOAP, TCP/IP, COM+ et ActiveX. Nombre de fonctionnalités avancées
concernant le développement web, les technologies XML de pointe et le
développement de bases de données nécessitent des composants ou des experts
qui ne sont pas disponibles dans toutes les versions de C++Builder.
Ce guide suppose que l’utilisation et les techniques fondamentales de
programmation C++Builder ont été assimilées. Pour une présentation de la
programmation C++Builder et de l’environnement de développement intégré
(EDI), voir le manuel de Prise en main et l’aide en ligne.

Contenu de ce manuel
Ce manuel est composé des cinq parties suivantes :
• La partie I, “Programmation C++Builder”, décrit la manière de concevoir des
applications C++Builder généralistes. Cette partie donne des détails sur les
techniques de programmation utilisables dans toute application C++Builder.
Elle décrit, par exemple, la manière d’utiliser les objets courants de la
bibliothèque de composants visuels (VCL) ou de la bibliothèque de
composants Borland multiplate-forme (CLX) qui simplifient le développement
de l’interface utilisateur : gestion des chaînes, manipulation du texte,
implémentation des dialogues communs, manipulation des graphiques, gestion
des erreurs et des exceptions, utilisation des DLL, automation OLE et écriture
d’applications internationales.
En général, il est rarement important que la VCL de C++Builder soit écrite en
Pascal Objet. Mais, dans un petit nombre de cas, cela peut affecter vos
programmes C++Builder. Un chapitre concernant le langage C++ et la VCL

Introduction 1-1
Contenu de ce manuel

traite de certaines questions relatives au langage, comme la façon dont


l’instanciation de classe en C++ diffère lorsque vous utilisez des classes de la
VCL et les extensions du langage C++ permettant de prendre en charge le
modèle de programmation “composant-propriété-événement” de C++Builder.
Un chapitre décrit comment utiliser les objets de la bibliothèque de
composants Borland multiplate-forme (CLX) pour développer des applications
pouvant être compilées et exécutées sous Windows ou sous Linux.
Le chapitre sur le déploiement aborde les opérations nécessaires pour
distribuer votre application auprès de ses utilisateurs. Ce chapitre donne des
informations sur les options de compilation, l’utilisation de InstallShield
Express, les problèmes de droits de distribution et sur le choix des paquets,
DLL et autres bibliothèques qu’il faut utiliser pour générer la version
distribuée d’une application.
• La partie II, “Développement d’applications de bases de données”, décrit
comment construire des applications de bases de données en utilisant les
outils et les composants base de données. C++Builder vous permet d’accéder à
de nombreux types de bases de données, notamment des bases de données
locales, comme Paradox et dBASE, et des bases de données serveur SQL en
réseau, comme InterBase, Oracle et Sybase. Vous pouvez choisir parmi divers
mécanismes d’accès aux données, dont dbExpress, BDE (moteur de bases de
données Borland), InterBaseExpress et ADO (ActiveX Data Objects). Pour
implémenter les applications de bases de données les plus évoluées, vous avez
besoin de fonctionnalités qui ne sont pas disponibles dans toutes les éditions
de C++Builder.
• La partie III, “Ecriture d’applications Internet”, décrit comment créer des
applications distribuées sur internet. C++Builder comprend une large gamme
d’outils permettant d’écrire des applications serveur web : Web Broker
(agent Web), une architecture pour la création d’applications serveur
multiplates-formes ; WebSnap, qui vous permet de concevoir des pages web
dans un environnement GUI ; le support de l’utilisation de documents XML ;
BizSnap, une architecture pour utiliser les services web basés sur SOAP.
Cette partie contient également un chapitre sur les composants socket de
C++Builder qui vous permettent de créer des applications pouvant
communiquer avec d’autres systèmes utilisant TCP/IP et des protocoles
voisins. Les sockets fournissent des connexions basées sur le protocole TCP/
IP, mais sont suffisamment généraux pour fonctionner avec des protocoles
apparentés comme Xerox Network System (XNS), DECnet de Digital ou la
famille IPX/SPX de Novell.
• La partie IV, “Développement d’applications COM”, décrit comment
construire des applications qui peuvent interagir avec d’autres objets API
basés sur COM. C++Builder supporte les applications COM basées sur les
experts ATL (Active Template Library) et un éditeur de bibliothèque de types
pour faciliter le développement de serveurs COM. Un outil d’importation
vous permet de créer rapidement des applications client. Le support des
clients COM est disponible dans toutes les éditions de C++Builder. Le support
des serveurs COM n’est pas disponible dans toutes les éditions de C++Builder.

1-2 Guide du développeur


Conventions typographiques

• La partie V, “Création de composants personnalisés”, décrit la manière de


concevoir et d’implémenter vos propres composants et de les intégrer à la
palette des composants de l’EDI. Un composant peut quasiment constituer
tout élément de programme manipulable à la conception. L’implémentation de
composants personnalisés nécessite la dérivation d’une nouvelle classe à partir
d’une classe existante de la bibliothèque de classes VCL ou CLX.

Conventions typographiques
Ce manuel utilise les polices et les symboles décrits dans le tableau suivant pour
mettre en évidence des parties particulières du texte :

Tableau 1.1 Polices et symboles utilisés dans ce manuel


Police ou symbole Signification
Police à pas fixe Le texte apparaissant avec une police à pas fixe sert à représenter le
texte tel qu’il apparaît à l’écran ou dans du code C++. Il indique aussi
les valeurs à saisir au clavier.
[] Les crochets dans le texte ou dans une syntaxe représentent des
éléments facultatifs. Ces crochets sont à omettre lors de la saisie.
Gras Les mots en gras dans le texte ou dans le code servent à représenter les
mots réservés du C++ et les options du compilateur.
Italique Les mots en caractères italiques représentent des identificateurs du C++
comme les variables et les noms de types. L’italique sert aussi à faire
ressortir certains mots comme les nouveaux termes.
Touches Cette police sert à indiquer une touche du clavier. Par exemple,
“Appuyez sur Echap pour quitter un menu”.

Support technique
Borland propose diverses options de support, notamment des services gratuits
sur Internet vous permettant de faire des recherches dans notre base
documentaire et de contacter d’autres utilisateurs de produits Borland.
Vous disposez aussi de différents services de support technique et d’un support
payant de type Consulting.
Pour plus d’informations sur les services de support développeur proposés
par Borland, visitez notre site Web à l’adresse http://www.borland.com/
devsupport/bcppbuilder. Si vous résidez en France, consultez www.borland.fr
ou http://www.borland.com/bww/intlcust.html si vous êtes situé dans un
autre pays.
Quand vous contactez le support, soyez prêt à fournir des informations
complètes sur l’environnement, la version et l’édition du produit que vous
utilisez, ainsi qu’une description détaillée du problème.

Introduction 1-3
1-4 Guide du développeur
Partie

I
Programmation C++Builder
Partie I

Les chapitres de cette partie présentent les concepts et connaissances nécessaires


pour créer des applications C++Builder avec n’importe quelle édition du produit.

Programmation C++Builder
Chapitre

Développement d’applications
Chapitre 2
2
avec C++Builder
Borland C++Builder est un environnement de programmation visuelle orienté
objet permettant le développement d’applications 32 bits en vue de leur
déploiement sous Windows et sous Linux. En utilisant C++Builder, vous pouvez
créer de puissantes applications avec un minimum de programmation.
C++Builder propose un ensemble d’outils de conception pour le développement
rapide d’applications (RAD), dont des experts programmateur et des modèles
d’applications ou de fiches, et gère la programmation orientée objet avec deux
bibliothèques étendues de classes :
• La bibliothèque de classes VCL comprend des objets qui encapsulent l’API
Windows ainsi que d’autres techniques de programmation utiles (Windows).
• La bibliothèque de composants Borland multiplate-forme (CLX), qui contient des
objets encapsulant la bibliothèque Qt (Windows ou Linux).
Ce chapitre décrit brièvement l’environnement de développement C++Builder et
comment il s’inscrit dans le cycle de développement. Le reste de ce manuel
donne des détails techniques sur le développement d’applications, la gestion des
bases de données et les applications Internet ou Intranet, la création de contrôles
ActiveX ou COM, et sur l’écriture de composants personnalisés.

L’environnement de développement intégré


Au démarrage de C++Builder, vous êtes immédiatement placé dans
l’environnement de développement intégré, appelé également EDI. Cet
environnement propose tous les outils nécessaires à la conception, au test, au
débogage et au déploiement d’applications, permettant un prototypage rapide et
un cycle de développement plus court.

Développement d’applications avec C++Builder 2-1


Conception d’applications

L’EDI dispose de tous les outils nécessaires pour commencer à concevoir une
application :
• Le concepteur de fiche, une fenêtre vide, appelée une fiche, dans laquelle
concevoir l’interface utilisateur, de l’application.
• La palette des composants qui affiche des composants visuels ou non visuels
que vous pouvez utiliser pour concevoir votre interface utilisateur.
• L’inspecteur d’objets pour connaître ou modifier les propriétés et événements
d’un objet.
• L’arborescence d’objets pour afficher ou modifier les relations logiques d’un
objet.
• L’éditeur de code pour écrire ou modifier la logique sous-jacente d’un
programme.
• Le gestionnaire de projet qui permet de gérer les fichiers constituant un ou
plusieurs projets.
• Le débogueur intégré pour rechercher et corriger les erreurs dans votre code.
• De nombreux outils, comme les éditeurs de propriété qui permettent de
modifier la valeur des propriétés d’un objet.
• Des outils en ligne de commande, y compris des compilateurs, des éditeurs de
liens.
• Des bibliothèques de classes contenant de nombreux objets réutilisables. De
nombreux objets fournis dans la bibliothèque des classes sont accessibles dans
la palette des composants de l’EDI. Par convention, les noms des objets de la
bibliothèque des classes commencent par un T, comme TStatusBar.
Certains d’entre eux ne font pas partie de toutes les éditions du produit.
Une présentation plus complète de l’environnement de développement est
proposée dans le manuel Prise en main, livré avec le produit. En outre, le système
d’aide en ligne offre de l’aide sur tous les menus, boîtes de dialogues et fenêtres.

Conception d’applications
Vous pouvez utiliser C++Builder pour concevoir tout type d’application 32 bits,
que ce soit un utilitaire de portée générale ou un programme complexe de
gestion de données ou des applications distribuées.
Alors même que vous concevez visuellement l’interface utilisateur d’une
application, C++Builder génère le code C++ sous-jacent pour gérer l’application.
Dès que vous sélectionnez et modifiez les propriétés des composants et des
fiches, le résultat de ces modifications apparaît automatiquement dans le code
source, et vice-versa. Vous pouvez modifier directement les fichiers source avec
tout éditeur de texte, y compris l’éditeur de code intégré. Les modifications
effectuées dans le code sont immédiatement reflétées dans l’environnement
visuel.
Dans C++Builder vous pouvez créer vos propres composants. La plupart des
composants fournis sont écrits en Pascal Objet. Vous pouvez ajouter à la palette
les composants que vous avez écrits et la personnaliser à votre convenance en
insérant de nouveaux onglets.

2-2 Guide du développeur


Création des projets

Vous pouvez également utiliser C++Builder pour concevoir des applications


s’exécutant sous Linux et sous Windows en utilisant CLX. CLX contient un
ensemble de classes qui, lorsque vous les utilisez à la place de la VCL,
permettent à votre programme de passer indifféremment de Windows à Linux.
Reportez-vous au chapitre 14, “Développement d’applications multiplates-
formes”, pour avoir des détails sur le développement multiplate-forme et
connaître les différences entre les environnements Windows et Linux.
Le chapitre 7, “Création d’applications, de composants et de bibliothèques”, décrit
comment C++Builder gère les différents types d’applications.

Création des projets


Tout le développement d’applications avec C++Builder s’effectue par le biais des
projets. Quand vous créez une application dans C++Builder, vous créez un
projet. Un projet est une collection de fichiers qui constituent une application.
Certains de ces fichiers sont créés au cours de la conception. D’autres sont
générés automatiquement lorsque vous compilez le code source du projet.
Vous pouvez voir le contenu d’un projet à l’aide d’un outil de gestion de projet
nommé le Gestionnaire de projet. Le gestionnaire de projet présente la liste, sous
forme d’une vue hiérarchisée, des noms d’unités et des fiches contenues
éventuellement dans chaque unité, ainsi que les chemins d’accès aux fichiers du
projet. Vous pouvez modifier directement la plupart de ces fichiers, mais il est
plus simple et plus sûr d’utiliser les outils visuels de C++Builder.
En haut de la hiérarchie, se trouve un fichier groupe. Vous pouvez combiner
plusieurs projets dans un groupe de projets. Cela vous permet d’ouvrir plusieurs
projets à la fois dans le gestionnaire de projet. Les groupes de projets permettent
de rassembler des projets liés et de travailler sur eux, par exemple des
applications qui fonctionnent ensemble ou font partie d’une application
multiniveau. Si vous ne travaillez que sur un seul projet, vous n’avez pas besoin
de fichier groupe de projets pour créer une application.
Les fichiers projet, qui décrivent des projets individuels, des fichiers et des
options associées, portent l’extension .bpr. Les fichiers projet contiennent des
directives pour la construction d’une application ou d’un objet partagé. Quand
vous ajoutez et supprimez des fichiers en utilisant le gestionnaire de projet, le
fichier projet est mis à jour. Vous spécifiez les options du projet dans la boîte de
dialogue Options de projet, qui contient des onglets pour les divers aspects de
votre projet, comme les fiches, l’application, le compilateur. Ces options de projet
sont stockées avec le projet dans le fichier projet.
Les unités et les fiches sont les blocs de base de la construction d’une application
C++Builder. Un projet peut partager n’importe quel fichier fiche et unité existant,
y compris ceux qui se trouvent hors de l’arborescence des répertoires du projet.
Cela inclut des procédures et des fonctions personnalisées, écrites sous forme de
routines indépendantes.
Si vous ajoutez à un projet un fichier partagé, celui-ci n’est pas copié dans le
répertoire du projet en cours ; il reste à sa place initiale. L’ajout du fichier

Développement d’applications avec C++Builder 2-3


Modification du code

partagé au projet en cours inscrit le nom et le chemin du fichier dans le fichier


projet. C++Builder s’en charge automatiquement lorsque vous ajoutez des unités
à un projet
Quand vous compilez un projet, l’emplacement des fichiers qui constituent le
projet n’a aucune importance. Le compilateur traite les fichiers partagés comme
ceux créés par le projet lui-même.

Modification du code
L’éditeur de code C++Builder est un éditeur ASCII complet. Si vous utilisez
l’environnement de programmation visuel, une fiche est automatiquement
affichée dans un nouveau projet. Vous pouvez commencer la conception de
l’interface de votre application en plaçant des objets sur la fiche et en modifiant
leur fonctionnement dans l’inspecteur d’objets. Mais d’autres tâches de
programmation, comme l’écriture des gestionnaires d’événements pour les objets,
doivent se faire en tapant directement le code.
Le contenu d’une fiche et toutes ses propriétés ainsi que ses composants et leurs
propriétés peuvent être modifiés sous forme de texte dans l’éditeur de code.
Vous pouvez ajuster le code généré dans l’éditeur de code et ajouter d’autres
composants en tapant du code dans l’éditeur. Au fur et à mesure que vous tapez
du code dans l’éditeur, le compilateur l’analyse constamment afin de changer la
disposition de la fiche. Vous pouvez revenir à la fiche, voir et tester les
changements apportés dans l’éditeur, puis continuer à modifier la fiche elle-
même.
La génération de code C++Builder et le système de flux des propriétés est
entièrement ouvert à l’examen. Le code source de tout ce qui se trouve dans le
fichier exécutable final (tous les objets VCL, les objets CLX, les sources RTL et
les fichiers projet) peut être visualisé et modifié dans l’éditeur de code.

Compilation des applications


Quand vous avez fini de concevoir l’interface de votre application sur la fiche,
après avoir écrit le code supplémentaire souhaité, vous pouvez compiler le projet
depuis l’EDI ou depuis la ligne de commande.
Tous les projets ont comme cible un fichier exécutable distribuable unique. Vous
pouvez voir ou tester votre application à divers stades du développement en la
compilant, la construisant ou l’exécutant :
• Quand vous la compilez, seules les unités qui ont changé depuis la dernière
compilation sont recompilées.
• Quand vous la construisez, toutes les unités du projet sont compilées, qu’elles
aient ou non changé depuis la dernière compilation. Cette technique est utile
quand vous n’êtes pas certain des fichiers qui ont été modifiés ou quand vous
voulez simplement garantir que tous les fichiers en cours soient synchronisés.

2-4 Guide du développeur


Débogage des applications

Il est également important de construire l’application quand vous avez changé


les directives globales du compilateur, afin d’assurer que tout le code se
compile de façon correcte. Vous pouvez tester ainsi la validité de votre code
source, sans compiler le projet.
• Quand vous l’exécutez, vous compilez l’application, puis l’exécutez. Si vous
avez modifié le code source depuis la dernière compilation, le compilateur
recompile les modules qui ont été changés et lie à nouveau votre application.
Si vous avez regroupé plusieurs projets, vous pouvez les compiler ou les
construire tous à la fois dans un même groupe de projet. Choisissez Projet|
Compiler tous les projets ou Projet|Construire tous les projets, le groupe de
projets étant sélectionné dans le gestionnaire de projet.
CLX Pour compiler une application CLX sous Linux, une application Borland C++
n’est pas encore disponible, mais vous pouvez déjà développer l’application dans
C++Builder.

Débogage des applications


C++Builder dispose d’un débogueur intégré qui permet de localiser et de
corriger les erreurs d’une application. Le débogueur intégré permet de contrôler
l’exécution du programme, de surveiller la valeur de variables et d’éléments de
structures de données ou de modifier la valeur de données lors de l’exécution.
Le débogueur intégré peut suivre à la fois les erreurs d’exécution et les erreurs
de logique. En exécutant le programme jusqu’à un emplacement spécifique et en
visualisant la valeur des variables, les fonctions de la pile des appels et les
sorties du programme, vous pouvez surveiller son comportement et trouver les
endroits où il ne se comporte pas comme prévu. Le débogueur est décrit plus en
détail dans l’aide en ligne.
Vous pouvez également utiliser la gestion des exceptions pour connaître,
localiser et traiter les erreurs. Les exceptions dans C++Builder sont des classes,
comme les autres classes de C++Builder, sauf que, par convention, leur nom
commence par E au lieu de T. Voir chapitre 12, “Gestion des exceptions”, pour
davantage d’informations sur la gestion des exceptions.

Déploiement des applications


C++Builder dispose d’outils facilitant le déploiement d’une application. Par
exemple, InstallShield Express (non disponible dans toutes les éditions) vous aide
à créer un programme d’installation pour votre application qui contient tous les
fichiers nécessaires à l’exécution de l’application distribuée. Le logiciel
TeamSource (non disponible dans toutes les éditions) est également disponible
pour suivre les mises à jour des applications.
Remarque Les versions de C++Builder n’ont pas toutes des capacités de déploiement.

Développement d’applications avec C++Builder 2-5


Déploiement des applications

CLX Pour déployer une application CLX sous Linux, une application Borland C++
n’est pas encore disponible, mais vous pouvez déjà développer l’application dans
C++Builder.
Pour davantage d’informations sur le déploiement, voir chapitre 17,
“Déploiement des applications”.

2-6 Guide du développeur


Chapitre

Utilisation des bibliothèques


Chapitre 3
3
de composants
Ce chapitre présente les bibliothèques de classes et décrit certains composants
que vous pouvez utiliser au cours du développement de vos applications.
C++Builder comprend à la fois la bibliothèque de composants visuels (VCL)
et la bibliothèque de composants Borland multiplate-forme (CLX). La VCL est
réservée au développement Windows tandis que CLX permet le développement
multiplate-forme Windows et Linux. Ces deux bibliothèques de classes sont
différentes mais présentent de nombreuses similarités.

Présentation des bibliothèques de classes


VCL et CLX sont des bibliothèques de classes constituées d’objets que vous
utilisez pour développer des applications. Les deux bibliothèques se ressemblent
et contiennent de nombreux objets identiques. Certains objets de la VCL
implémentent des fonctionnalités disponibles uniquement sous Windows, comme
les objets qui apparaissent dans les onglets ADO, BDE, QReport, COM+ et
Serveurs de la palette des composants. Pratiquement tous les objets CLX sont
disponibles à la fois pour Windows et pour Linux.
Tous les objets VCL et CLX dérivent de TObject qui est une classe abstraite dont
les méthodes encapsulent des comportements essentiels comme la construction,
la destruction et la gestion des messages. Quand vous écrivez vos propres
classes, elles doivent dériver de TObject dans la bibliothèque de classes que vous
prévoyez utiliser.
Les composants sont un sous-ensemble de la VCL ou de CLX et dérivent de la
classe abstraite TComponent. Vous pouvez placer les composants dans une fiche
ou un module de données et les manipuler pendant la conception. La plupart
des composants sont visuels ou non, selon qu’ils apparaissent ou pas à
l’exécution. Certains des composants apparaissent sur la palette des composants.

Utilisation des bibliothèques de composants 3-1


Présentation des bibliothèques de classes

Les composants visuels, comme TForm ou TSpeedButton sont appelés des contrôles
et dérivent de TControl. TControl propose des propriétés qui spécifient les
attributs visuels des contrôles comme la hauteur ou la largeur.
Les composants non visuels sont utilisés pour diverses tâches. Si, par exemple,
vous écrivez une application qui se connecte à une base de données, vous
pouvez placer un composant TDataSource dans une fiche pour connecter un
contrôle et l’ensemble de données utilisé par le contrôle. Cette connection est
invisible pour l’utilisateur, TDataSource est donc non visuel. A la conception,
les composants non visuels sont représentés par une icône. Cela vous permet
de manipuler leurs propriétés et événements comme pour un contrôle visuel.
Vous pouvez accéder à des informations détaillées sur tous les objets VCL ou
CLX, en utilisant l’aide en ligne pendant que vous programmez. Dans l’éditeur
de code, placez le curseur en un endroit quelconque de l’objet et appuyez sur F1
pour afficher de l’aide. Les objets, propriétés, méthodes et événements qui font
partie de la VCL sont marqués “Référence VCL” et ceux faisant partie de CLX
sont marqués “Référence CLX”.

Propriétés, méthodes et événements


VCL et CLX sont toutes deux une hiérarchie d’objets, intégrée à l’EDI qui vous
permet de développer rapidement des applications. Les objets des deux
bibliothèques sont basés sur des propriétés, des méthodes et des événements.
Chaque objet contient des données membres (propriétés), des fonctions qui
opèrent sur les données (méthodes) et un moyen d’interagir avec les utilisateurs
des classes (événements). La VCL et CLX sont écrits en Pascal Objet, même si la
VCL est basée sur l’API Windows et CLX sur bibliothèque de widgets Qt.

Propriétés
Les Propriétés sont les caractéristiques d’un objet, relatives à son comportement
visible ou aux opérations qu’il effectue. Par exemple, la propriété Visible
détermine si un objet doit être vu ou non dans l’interface d’une application.
Des propriétés bien conçues simplifient l’utilisation de vos composants par
d’autres programmeurs et en facilite la maintenance.
Voici quelques fonctionnalités utiles des propriétés :
• Alors que les méthodes ne sont disponibles qu’à l’exécution, vous pouvez
accéder aux propriétés et les modifier au cours de la conception et obtenir une
réponse immédiate des composants dans l’EDI.
• Les propriétés peuvent être accédées via l’inspecteur d’objets dans lequel vous
pouvez changer les valeurs visuellement. Définir les propriétés au moment de
la conception est plus simple qu’écrire directement le code, et ce dernier est
plus facile à maintenir.
• Comme les données sont encapsulées, elles sont protégées et privées pour
l’objet réel.

3-2 Guide du développeur


Présentation des bibliothèques de classes

• Les appels effectués pour obtenir ou définir des valeurs sont des méthodes, et
donc le traitement reste invisible pour l’utilisateur de l’objet. Par exemple, les
données peuvent résider dans une table, mais apparaître au programmeur
comme des données membres normales.
• Vous pouvez implémenter la logique qui déclenche des événements ou
modifier d’autres données pendant l’accès à la propriété. Par exemple, changer
la valeur d’une propriété peut nécessiter la modification d’une autre. Vous
pouvez modifier les méthodes créées pour la propriété.
• Les propriétés peuvent être virtuelles.
• Une propriété n’est pas limitée à un seul objet. Changer une propriété d’un
objet peut affecter plusieurs autres objets. Par exemple, définir la propriété
Checked d’un bouton radio affecte tous les autres boutons radio du groupe.

Méthodes
Une méthode est une fonction qui est un membre d’une classe. Les méthodes
définissent le comportement d’un objet. Les méthodes de classe peuvent accéder
à toutes les propriétés publiques, protégées et privées et aux données membres de la
classe, on les désigne fréquemment par le terme fonctions membres.
Voir “Contrôle des accès” à la page 46-4.

Evénements
Un événement est une action ou une occurrence détectée par un programme.
La plupart des applications modernes sont dites pilotées par événements, car
elles sont conçues pour répondre à des événements. Dans un programme, le
programmeur n’a aucun moyen de prévoir la séquence exacte des actions que
va entreprendre l’utilisateur. Il peut, par exemple, choisir un élément de menu,
cliquer sur un bouton ou sélectionner du texte. Vous allez donc écrire le code
qui gère chacun des événements qui vous intéressent au lieu d’écrire du code
s’exécutant toujours selon le même ordre.
Quelle que soit la façon dont un événement a été appelé, C++Builder recherche
si du code a été écrit pour gérer cet événement. Si c’est le cas, ce code est
exécuté, sinon, le comportement par défaut se produit.
Les types d’événements qui peuvent survenir se divisent en deux grandes
catégories :
• Evénements utilisateur
• Evénements système

Evénements utilisateur
Les événements utilisateur sont des actions initiées par l’utilisateur.
Les événements utilisateur sont, par exemple, OnClick (l’utilisateur a cliqué avec
la souris), OnKeyPress (l’utilisateur a appuyé sur une touche du clavier)
et OnDblClick (l’utilisateur a double-cliqué sur un bouton de la souris).

Utilisation des bibliothèques de composants 3-3


Objets, composants et contrôles

Evénements système
Ce sont des événements que le système d’exploitation déclenche pour vous.
Par exemple, l’événement OnTimer (le composant Timer déclenche l’un de ces
événements lorsqu’un intervalle prédéfini s’est écoulé), l’événement OnCreate (le
composant est en train d’être créé), l’événement OnPaint (un composant ou une
fenêtre a besoin d’être redessiné), etc. En règle générale, ces événements ne sont
pas directement déclenchés par des actions de l’utilisateur.

Objets, composants et contrôles


La figure suivante est une vue très simplifiée de la hiérarchie des héritages qui
illustre les relations entre objets, composants et contrôles.
Figure 3.1 Objets, composants et contrôles

TObject

TComponent

TControl

TForm TButton TCheckBox TListBox

Chaque objet hérite de TObject et beaucoup d’objets héritent de TComponent.


Les contrôles héritent de TControl et ont la capacité à s’afficher eux-mêmes à
l’exécution. Un contrôle comme TCheckBox hérite de toutes les fonctionnalités de
TObject, TComponent et de TControl, et ajoute ses spécificités propres.
Le diagramme suivant est un résumé de la bibliothèque de composants visuels
(VCL) qui montre les principales branches de l’arbre d’héritage. La bibliothèque
de composants Borland multiplate-forme (CLX) lui ressemble beaucoup à ce
niveau, mais TWinControl est remplacé par TWidgetControl.

3-4 Guide du développeur


Objets, composants et contrôles

Figure 3.2 Diagramme simplifié de la hiérarchie

TObject TPersistent TComponent TControl TWinControl

[Objets]
[Objets] [Objets] TGraphicControl [Objets]

[Objets]

Exception [Objets]

Plusieurs importantes classes de base montrées dans la figure sont décrites dans
le tableau suivant :

Tableau 3.1 Importantes classes de base


Classe Description
TObject C’est la classe de base et l’ancêtre ultime de tout ce qui se trouve dans la
VCL ou dans CLX. TObject encapsule le comportement fondamental commun
à tous les objets VCL/ CLX, en introduisant les méthodes qui effectuent les
fonctions de base, comme la création, la maintenance et la destruction d’une
instance d’objet.
Exception Spécifie la classe de base de toutes les classes relatives aux exceptions.
Exception fournit une interface cohérente pour les conditions d’erreur et
permet aux applications de les gérer harmonieusement.
TPersistent Spécifie la classe de base de tous les objets qui implémentent des propriétés.
Les classes issues de TPersistent prennent en charge l’envoi de données aux
flux et permettent l’affectation des classes.
TComponent Spécifie la classe de base de tous les composants non visuels, comme
TApplication. TComponent est l’ancêtre commun de tous les composants. Cette
classe permet à un composant de figurer sur la palette des composants, de
posséder d’autres composants et d’être manipulé directement sur une fiche.
TControl Représente la classe de base de tous les contrôles visibles à l’exécution.
TControl est l’ancêtre commun de tous les composants visuels et fournit les
contrôles visuels standard comme la position et le curseur. Cette classe
fournit également des événements qui répondent aux actions de la souris.
TWinControl Spécifie la classe de base de tous les objets d’interface utilisateur. Les
contrôles issus de TWinControl sont des contrôles fenêtrés qui peuvent
capturer la saisie au clavier. Dans CLX, on les appelle des widgets, et
TWidgetControl remplace TWinControl.

Les quelques sections suivantes présentent une description générale des types de
classes que contient chaque branche. Pour avoir une présentation complète de la
hiérarchie des objets VCL et CLX, reportez-vous aux posters VCL et CLX fournis
avec ce produit.

Utilisation des bibliothèques de composants 3-5


Objets, composants et contrôles

Branche TObject
La branche TObject comprend tous les objets VCL et CLX qui dérivent de TObject
mais non de TPersistent. L’essentiel des capacités des objets VCL et CLX est basé
sur les méthodes définies dans TObject. TObject encapsule le comportement
fondamental commun à tous les objets VCL ou CLX, en introduisant des
méthodes qui permettent :
• De répondre à la création ou à la destruction d’objets.
• De donner des informations sur le type de classe et d’instance d’un objet et
des informations de type à l’exécution (RTTI) sur ses propriétés publiées.
• De gérer le traitement des messages (VCL) ou les événements système (CLX).
TObject est l’ancêtre immédiat de nombreuses classes simples. Les classes
contenues dans la branche de TObject ont une caractéristique commune
importante : elles sont transitoires. Cela signifie que ces classes ne disposent pas
d’une méthode pour enregistrer leur état avant leur destruction ; elles ne sont
pas persistantes.
Le groupe de classes le plus important de cette branche est constitué par la
classe Exception. Cette classe propose un grand nombre de classes d’exceptions
prédéfinies pour gérer automatiquement de nombreuses conditions d’exception
comme les erreurs de division par zéro, les erreurs d’entrées/sorties ou les
transtypages incorrects.
La branche TObject contient également un autre groupe de classes qui
encapsulent des structures de données, comme :
• TBits, une classe qui stocke un “tableau” de valeur booléennes.
• TList, une classe liste liée.
• TStack, une classe qui gère un tableau de pointeurs du type dernier entré,
premier sorti.
• TQueue, une classe qui gère un tableau de pointeurs du type premier entré,
premier sorti.
Dans la VCL, vous trouverez aussi des enveloppes pour les objets externes
comme TPrinter, qui encapsulent l’interface imprimante Windows, et TRegistry,
une enveloppe de bas niveau pour le registre du système et les fonctions qui
opèrent sur le registre. Elles sont spécifiques à l’environnement Windows.
TStream est un bon exemple du type de classes contenues dans cette branche.
TStream est la classe de base des objets flux qui permettent de lire ou d’écrire sur
divers types de support de données, comme les fichiers disque ou la mémoire
vive.
Globalement, cette branche contient un grand nombre de différents types de
classes particulièrement utiles pour le développeur.

3-6 Guide du développeur


Objets, composants et contrôles

Branche TPersistent
La branche TPersistent comprend tous les objets VCL et CLX qui dérivent de
TPersistent mais pas de TComponent. La persistance détermine ce qui est
enregistré dans un fichier fiche ou un module de données et ce qui est chargé
dans la fiche ou le module de données lorsqu’il est extrait de la mémoire.
Les objets de cette branche implémentent des propriétés pour les composants.
Les propriétés sont uniquement chargés et enregistrés avec une fiche si elles ont
un propriétaire. Le propriétaire doit être un composant. Cette branche introduit
la fonction GetOwner qui vous permet de déterminer le propriétaire de la
propriété.
Les objets de cette branche sont également les premiers à inclure une section
publiée dans laquelle les propriétés peuvent être automatiquement chargées et
enregistrées. Un méthode DefineProperties vous permet aussi d’indiquer la façon
de charger et d’enregistrer les propriétés.
Voici quelques autres classes de la branche TPersistent de la hiérarchie :
• TGraphicsObject, une classe de base abstraite pour les objets graphiques, par
exemple : TBrush, TFont et TPen.
• TGraphic, une classe de base abstraite pour les objets comme TBitmap et TIcon,
qui peuvent stocker et afficher des images visuelles.
• TStrings, une classe de base pour les objets qui représentent une liste de
chaînes.
• TClipboard, une classe contenant du texte ou des graphiques qui ont été
coupés ou copiés d’une application.
• TCollection, TOwnedCollection et TCollectionItem, classes qui maintiennent les
collections indexées d’éléments spécialement définis.

Branche TComponent
La branche TComponent contient des objets qui dérivent de TComponent mais pas
de TControl. Les objets de cette branche sont des composants que vous pouvez
manipuler sur des fiches au cours de la conception. Ce sont des objets persistants
aux capacités suivantes :
• Ils apparaissent dans la palette des composants et peuvent être modifiés dans
le concepteur de fiche.
• Ils peuvent posséder et gérer d’autres composants.
• Ils se chargent et s’enregistrent eux-mêmes.
Plusieurs méthodes de TComponent dictent la façon dont agissent les composants
durant la conception et les informations qui sont enregistrées avec le composant.
La gestion des flux est introduite dans cette branche de la VCL et de CLX.
C++Builder gère automatiquement la plupart des opérations principales relatives
aux flux. Les propriétés sont persistantes si elles sont publiées et les propriétés
publiées sont automatiquement mises en flux.

Utilisation des bibliothèques de composants 3-7


Objets, composants et contrôles

La classe TComponent introduit également le concept de possession (propriété)


qui se propage dans la VCL et dans CLX. Deux propriétés supportent la
possession : Owner et Components. Chaque composant dispose d’une propriété
Owner qui référence un autre composant comme son propriétaire. Un composant
peut posséder d’autres composants. Dans ce cas, tous les composants possédés
sont référencés dans la propriété Array du composant.
Le constructeur d’un composant prend un seul paramètre qui est utilisé pour
spécifier le propriétaire du nouveau composant. Si le propriétaire transmis existe,
le nouveau composant est ajouté à la liste des composants du propriétaire. Outre
la liste des composants, pour référencer les composants possédés, cette propriété
fournit la destruction automatique des composants possédés. Si le composant a
un propriétaire, il est détruit lorsque le propriétaire est détruit. Par exemple,
comme TForm est un descendant de TComponent, tous les composants possédés
par la fiche sont détruits, et leur emplacement en mémoire libéré, lorsque la fiche
est détruite. Cela garantit que tous les composants de la fiche se nettoient eux-
mêmes correctement lorsque leurs destructeurs sont appelés.
Si un type de propriété est TComponent ou un de ses descendants, le système de
flux crée une instance de ce type lorsqu’il le lit. Si un type de propriété est
TPersistent mais pas TComponent, le système de flux utilise l’instance existante,
accessible via la propriété, et lit les valeurs des propriétés de cette instance.
Quand il crée un fichier fiche (fichier utilisé pour stocker les informations
relatives aux composants de la fiche), le concepteur de fiche parcourt le tableau
de ses composants et enregistre tous les composants dans la fiche. Chaque
composant “sait” comment écrire dans un flux (dans ce cas, un fichier texte) ses
propriétés modifiées. Parallèlement, lorsqu’il charge les propriétés des
composants du fichier fiche, le concepteur de fiche parcourt le tableau des
composants et charge chacun d’eux.
Cette branche contient, entre autres, les types de classes suivants :
• TActionList, une classe qui gère une liste d’actions utilisées par des
composants et des contrôles, comme les éléments de menu et les boutons.
• TMainMenu, une classe qui définit une barre de menus et les menus
déroulants associés dans une fiche.
• Les classes TOpenDialog, TSaveDialog, TFontDialog, TFindDialog, TColorDialog,
etc., fournissent les boîtes de dialogue communes.
• TScreen, une classe qui mémorise les fiches et les modules de données
instanciés par l’application, la fiche active et le contrôle actif dans cette fiche,
la taille et la résolution de l’écran, ainsi que les curseurs et les fontes
utilisables par l’application.
Les composants qui n’ont pas besoin d’interface visuelle peuvent être
directement dérivés de TComponent. Pour faire un outil tel qu’un périphérique
TTimer, vous devez le dériver de TComponent. Ce type de composant se trouve
sur la palette des composants, mais exécute des fonctions internes accessibles par
le code et qui n’apparaissent pas, à l’exécution, dans l’interface utilisateur.

3-8 Guide du développeur


Objets, composants et contrôles

Dans CLX, la branche TComponent contient aussi THandleComponent. C’est la


classe de base des composants non visuels qui nécessitent un handle sur un objet
Qt sous-jacent, comme les boîtes de dialogue et les menus.
Pour davantage d’informations sur l’initialisation des propriétés, l’appel des
méthodes ou l’utilisation des événements d’un composant, voir chapitre 5,
“Utilisation des composants”.

Branche TControl
La branche TControl est constituée de composants qui dérivent de TControl mais
pas de TWinControl (TWidgetControl dans CLX). Les objets de cette branche sont
des contrôles, c’est-à-dire des objets visuels que l’utilisateur de l’application peut
voir et manipuler à l’exécution. Tous les contrôles ont des propriétés, méthodes
et événements communs qui sont propres à l’aspect visuel des contrôles, comme
la position du contrôle, le curseur associé à la fenêtre (au widget dans CLX) du
contrôle, des méthodes pour dessiner ou déplacer le contrôle et des événements
permettant de répondre aux actions de la souris. Ils ne peuvent jamais recevoir
la saisie du clavier.
Si TComponent définit des comportements communs à tous les composants,
TControl définit ceux communs à tous les contrôles visuels. Il s’agit de routines
de dessin, des événements standard et de la notion de conteneur.
Tous les contrôles visuels partagent certaines propriétés. Ces propriétés sont
héritées de TControl mais elles ne sont publiées (elles apparaissent dans
l’inspecteur d’objets) que pour les composants où elles sont applicables. Ainsi,
TImage ne publie pas la propriété Color car sa couleur est déterminée par l’image
qu’il affiche.
Il y a deux types de contrôles :
• Ceux qui ont leur propre fenêtre (ou widget).
• Ceux qui utilisent la fenêtre (ou le widget) de leur parent.
Les contrôles qui ont leur propre fenêtre sont appelés contrôles “fenêtrés” (VCL)
ou “basés sur des widgets” (CLX) et dérivent de TWinControl (TWidgetControl
dans CLX). Les boutons et les cases à cocher en font partie.
Les contrôles qui utilisent une fenêtre (ou un widget) parent sont appelés
contrôles graphiques et dérivent de TGraphicControl. Les contrôles image et forme
en font partie. Les contrôles graphique ne possèdent pas de handle et ne peuvent
pas recevoir la focalisation de saisie. Comme un contrôle graphique n’a pas
besoin d’un handle, il utilise moins de ressources système. Les contrôles
graphique doivent se dessiner eux-mêmes et ne peuvent pas servir de parent
à d’autres contrôles.
Voir “Contrôles graphiques” à la page 9-20 pour davantage d’informations sur
les autres contrôles graphiques et le chapitre 9, “Types de contrôles”, pour
davantage d’informations sur les différents types de contrôles. Voir le chapitre 6,
“Manipulation des contrôles”, pour davantage d’informations sur la manière
d’interagir sur les contrôles à l’exécution.

Utilisation des bibliothèques de composants 3-9


Objets, composants et contrôles

Branche TWinControl/TWidgetControl
Dans la VCL, la branche TWinControl contient tous les contrôles qui dérivent de
TWinControl. TWinControl est la classe de base de tous les contrôles fenêtrés, qui
sont des éléments que vous utilisez dans l’interface utilisateur d’une application,
comme les boutons, les étiquettes ou les barres de défilement. Les contrôles
fenêtrés encapsulent un contrôle de Windows.
Dans CLX, TWidgetControl, qui remplace TWinControl, est la classe de base de
tous les contrôles widget qui encapsulent des widgets.
Les contrôles fenêtrés et widgets :
• Peuvent recevoir la focalisation lors de l’exécution de l’application, ce qui
signifie qu’ils peuvent recevoir les saisies clavier effectuées par l’utilisateur de
l’application. Par comparaison, d’autres contrôles peuvent seulement afficher
des données.
• Peuvent être le parent d’un ou de plusieurs contrôles enfant.
• Ont un handle ou un identificateur unique.
La branche TWinControl/TWidgetControl contient des contrôles dessinés
automatiquement (comme TEdit, TListBox, TComboBox, TPageControl, etc) et des
contrôles personnalisés que C++Builder doit dessiner, comme TDBNavigator,
TMediaPlayer (VCL uniquement) ou TGauge (VCL uniquement). Les descendants
directs de TWinControl /TWidgetControl implémentent typiquement des contrôles
standard, comme un champ d’édition, une boîte à option ou un contrôle page, et
savent donc déjà comment se dessiner eux-mêmes.
La classe TCustomControl est fournie pour les composants qui nécessitent un
handle mais n’encapsulent pas de contrôle standard ayant la capacité de se
redessiner lui-même. Vous n’avez jamais à vous soucier de la façon dont les
contrôles s’affichent ou répondent aux événements — C++Builder encapsule
complètement ce comportement pour vous.

3-10 Guide du développeur


Chapitre

Utilisation de BaseCLX
Chapitre 4
4
De nombreuses unités communes à la VCL et à CLX fournissent la prise en
charge sous-jacente des deux bibliothèques de composants. Ces unités sont
collectivement dénommées BaseCLX. BaseCLX n’inclut aucun des composants
qui apparaissent sur la palette des composants. Elle inclut à la place un certain
nombre de classes et de routines globales utilisées par les composants qui
apparaissent sur la palette des composants. Ces classes et routines sont
également disponibles pour une utilisation dans du code d’application ou pour
l’écriture de vos propres classes.
Remarque Les routines globales constituant BaseCLX sont souvent appelées la bibliothèque
d’exécution. Il ne faut pas confondre ces routines avec la bibliothèque
d’exécution C++. Un grand nombre de ces routines ont des fonctions similaires
à celles de la bibliothèque d’exécution C++, mais elles peuvent se distinguer à
cause de leurs noms de fonctions qui commencent par une lettre capitale, et elles
sont déclarées dans l’en-tête d’une unité.
Les rubriques suivantes traitent de bon nombre des classes et routines qui
constituent BaseCLX, et elles montrent la manière de les utiliser. Ces utilisations
incluent :
• Utilisation des flux
• Utilisation des fichiers
• Utilisation des fichiers ini et du registre
• Utilisation des listes
• Utilisation des listes de chaînes
• Utilisation des chaînes
• Conversion de mesures
• Création d’espaces de dessin
Remarque Cette liste de tâches n’est pas exhaustive. La bibliothèque d’exécution de
BaseCLX contient de nombreuses routines pour l’exécution de tâches qui ne sont
pas mentionnées ici. Ces routines incluent ainsi un ensemble de fonctions
mathématiques (définies dans l’unité Math), des routines pour la manipulation
des valeurs date/heure (définies dans les unités SysUtils et DateUtils) et des

Utilisation de BaseCLX 4-1


Utilisation des flux

routines pour la manipulation des Variants Pascal Objet (définies dans l’unité
Variants).

Utilisation des flux


Les flux sont des classes qui vous permettent de lire et d’écrire des données.
Ils offrent une interface commune pour la lecture et l’écriture sur différents
supports, tels que la mémoire, les chaînes, les sockets et les champs BLOB dans
les bases de données. Il existe plusieurs classes de flux, qui dérivent toutes de
TStream. Chaque classe de flux est propre à un type de support. Par exemple,
TMemoryStream lit ou écrit dans une image mémoire, alors que TFileStream lit
ou écrit dans un fichier.

Utilisation des flux pour lire ou écrire des données


Les classes de flux partagent toutes plusieurs méthodes pour lire et écrire des
données. Ces méthodes se différencient selon qu’elles effectuent les opérations
suivantes :
• Renvoi du nombre d’octets lus ou écrits.
• Nécessité de connaître le nombre d’octets.
• Déclenchement d’une exception en cas d’erreur.

Méthodes de flux pour la lecture et l’écriture


La méthode Read lit un nombre d’octets spécifié à partir du flux en commençant
par sa Position en cours, dans un tampon. Read déplace ensuite la position en
cours du nombre d’octets effectivement lus. Read a le prototype suivant :
virtual int __fastcall Read(void *Buffer, int Count);
Read est utile quand le nombre d’octets du fichier est inconnu. Read renvoie le
nombre d’octets effectivement transférés, qui peut être inférieur à Count si le flux
ne contient pas Count octets de données après la position courante.
La méthode Write écrit Count octets d’un tampon vers le flux, en commençant
à la Position courante. Write a le prototype suivant :
virtual int __fastcall Write(const void *Buffer, int Count);
Après avoir écrit dans le fichier, Write avance la position en cours du nombre
d’octets écrits et renvoie le nombre d’octets effectivement écrits, qui peut être
inférieur à Count si la fin du tampon a été atteinte ou si le flux ne peut pas
accepter d’autres octets.
Les procédures correspondantes sont ReadBuffer et WriteBuffer qui, à la différence
de Read et Write, ne renvoient pas le nombre d’octets lus ou écrits. Ces
procédures sont utiles dans les situations où le nombre d’octets est connu et
obligatoire, par exemple pour la lecture de structures. ReadBuffer et WriteBuffer
déclenchent une exception (EReadError et EWriteError), si le nombre d’octets ne
correspond pas exactement. Les méthodes Read et Write, au contraire, peuvent

4-2 Guide du développeur


Utilisation des flux

renvoyer un nombre d’octets différent de la valeur demandée. Les prototypes de


ReadBuffer et WriteBuffer sont :
virtual int __fastcall ReadBuffer(void *Buffer, int Count);
virtual int __fastcall WriteBuffer(const void *Buffer, int Count);
Ces méthodes appellent les méthodes Read et Write pour réaliser la lecture et
l’écriture effectives.

Lecture et écriture de composants


TStream définit des méthodes spécialisées, ReadComponent et WriteComponent,
pour la lecture et l’écriture de composants. Vous pouvez les utiliser dans vos
applications pour enregistrer des composants et leurs propriétés lorsque vous les
créez ou que vous les modifiez lors de l’exécution.
ReadComponent et WriteComponent sont les méthodes utilisées par l’EDI pour lire
ou écrire des composants dans des fichiers de fiches. Lors de la gestion de flux
de composants à destination ou en provenance d’un fichier de fiche, les classes
de flux fonctionnent avec les classes TFiler, TReader et TWriter, pour lire des
objets à partir du fichier de fiche ou les écrire sur disque. Pour davantage
d’informations sur l’utilisation du système de flux de composant, voir l’aide en
ligne sur les classes TStream, TFiler, TReader, TWriter et TComponent.

Copie de données d’un flux vers un autre


Lors de la copie de données d’un flux vers un autre, il n’est pas nécessaire de
lire puis d’écrire explicitement les données. Vous pouvez utiliser à la place la
méthode CopyFrom, telle qu’elle est illustrée dans l’exemple suivant.
L’application comprend deux contrôles d’édition (From et To) et un bouton pour
copier le fichier.
void __fastcall TForm1::CopyFileClick(TObject *Sender)
{
TStream* stream1= new TFileStream(From->Text,fmOpenRead | fmShareDenyWrite);
try
{
TStream* stream2 = new TFileStream(To->Text, fmOpenWrite | fmShareDenyRead);
try
{
stream2 -> CopyFrom(stream1, stream1->Size);
}
__finally
{
delete stream2;
}
}
__finally
{
delete stream1;
}
}

Utilisation de BaseCLX 4-3


Utilisation des flux

Spécification de la position et de la taille du flux


Outre les méthodes de lecture et d’écriture, les flux permettent aux applications
de se positionner de manière arbitraire dans le flux ou de changer sa taille.
Après un déplacement sur une position spécifiée, l’opération de lecture ou
d’écriture suivante démarre la lecture ou l’écriture du flux à cette position.

Déplacement sur une position particulière


La méthode Seek est le mécanisme le plus général pour se déplacer vers une
position particulière dans le flux. Il existe deux surcharges pour la méthode Seek :
virtual int __fastcall Seek(int Offset, Word Origin);
virtual __int64 __fastcall Seek(const __int64 Offset, TSeekOrigin Origin);
Les deux surcharges fonctionnent de la même manière. La différence réside dans
le fait qu’une version utilise un entier sur 32 bits pour représenter les positions et
les décalages, alors que l’autre utilise un entier sur 64 bits.
Le paramètre Origin indique la manière d’interpréter le paramètre Offset. Origin
peut prendre l’une des valeurs suivantes :

Valeur Signification
soFromBeginning Offset part du début de la ressource. Seek se déplace vers la position
Offset. Offset doit être >= 0.
soFromCurrent Offset part de la position en cours dans la ressource. Seek se déplace
vers Position + Offset.
soFromEnd Offset part de la fin de la ressource. Offset doit être <= 0 afin d’indiquer
le nombre d’octets avant la fin du fichier.

Seek réinitialise la position en cours dans le flux en la déplaçant du décalage


spécifié. Seek renvoie la nouvelle position en cours dans le flux.

Utilisation des propriétés de position et de taille


Tous les flux disposent de propriétés qui contiennent la position en cours et la
taille du flux. Ces propriétés sont utilisées par la méthode Seek, ainsi que par
toutes les méthodes qui lisent ou écrivent dans le flux.
La propriété Position indique le décalage en cours dans le flux exprimé en octets
(à partir du début des données du flux).
La propriété Size indique la taille en octets du flux. Elle peut être utilisée pour
déterminer le nombre d’octets disponibles pour une lecture, ou pour tronquer les
données dans le flux.
Size est utilisée de manière interne par les routines qui lisent et écrivent dans
le flux.
L’initialisation de la propriété Size modifie la taille des données dans le flux.
Par exemple, sur un flux de fichier, l’initialisation de Size insère une marque de
fin de fichier pour tronquer le fichier. Si la taille du flux ne peut pas être

4-4 Guide du développeur


Utilisation des fichiers

modifiée, une exception est déclenchée. Ainsi, tenter de modifier la taille d’un
flux de fichier ouvert en lecture seule déclenche une exception.

Utilisation des fichiers


BaseCLX prend en charge plusieurs méthodes de manipulation des fichiers.
En plus de l’utilisation des flux de fichiers, il existe plusieurs routines
de la bibliothèque d’exécution pour les E/S fichier. Les flux de fichiers
et les routines globales pour lire et écrire dans des fichiers sont décrits
dans “Approches des E/S fichier” à la page 4-5.
En plus des opérations d’entrée/sortie, vous pouvez souhaiter manipuler des
fichiers sur disque. La prise en charge des opérations sur les fichiers eux-mêmes
plutôt que sur leur contenu est décrite dans “Manipulation de fichiers” à la
page 4-7.
Remarque Lors de l’utilisation de CLX dans des applications multi-plates-formes, n’oubliez
pas qu’à la différence du langage Pascal Objet, le système d’exploitation Linux
distingue majuscules et minuscules. Lors de l’utilisation d’objets et de routines
fonctionnant avec des fichiers, soyez attentif à la casse des noms de fichiers.

Approches des E/S fichier


Il existe trois approches que vous pouvez adopter pour la lecture et l’écriture de
fichiers :
• L’approche recommandée pour la manipulation de fichiers consiste à utiliser
des flux de fichier. Les flux de fichier sont des instances d’objet de la classe
TFileStream utilisées pour accéder aux informations de fichiers disque. Les flux
de fichier sont portables et proposent une approche de haut niveau des
opérations d’E/S de fichier. Comme les flux de fichier mettent à disposition le
handle de fichier, cette approche peut être combinée avec la suivante. La
section suivante “Utilisation de flux de fichier” décrit en détail TFileStream.
• Vous pouvez travailler avec des fichiers en utilisant une approche basée sur
un handle. Les handles de fichier sont fournis par le système d’exploitation
lorsque vous créez ou ouvrez un fichier pour manipuler son contenu. L’unité
SysUtils définit un certain nombre de routines de gestion de fichiers qui
manipulent des fichiers en utilisant des handles. Sous Windows, il s’agit
généralement d’enveloppes de fonctions de l’API Windows. Comme les
fonctions Delphi utilisent la syntaxe du Pascal Objet et fournissent
occasionnellement les valeurs par défaut des paramètres, elles peuvent
facilement servir d’interface à l’API Windows. De plus, il existe des versions
correspondantes sous Linux, de sorte que vous pouvez utiliser ces routines
dans des applications multi-plates-formes. Pour utiliser une approche basée
sur un handle, ouvrez tout d’abord un fichier en utilisant la fonction FileOpen
ou créez un nouveau fichier en utilisant la fonction FileCreate. Lorsque vous
disposez du handle, utilisez les routines basées sur un handle pour manipuler
son contenu (écrire une ligne, lire le texte, etc.).

Utilisation de BaseCLX 4-5


Utilisation des fichiers

• La bibliothèque d’exécution C et la bibliothèque C++ standard contiennent un


certain nombre de fonctions et de classes pour manipuler des fichiers. Celles-ci
présentent l’avantage de pouvoir être utilisées dans des applications n’utilisant
pas la VCL ou CLX. Pour des informations sur ces fonctions, consultez la
documentation en ligne de la bibliothèque d’exécution C ou de la bibliothèque
C++ standard.

Utilisation de flux de fichier


TFileStream est une classe qui permet aux applications de lire et d’écrire dans un
fichier résidant sur le disque. Elle est utilisée pour une représentation objet de haut
niveau des flux de fichiers. Comme TFileStream est un objet flux, il partage les
méthodes de flux courantes. Vous pouvez utiliser ces méthodes pour lire ou
écrire dans le fichier, copier des données à destination ou à partir d’autres
classes de flux, et lire ou écrire des valeurs de composants. Consultez
“Utilisation des flux” à la page 4-2 pour des détails sur les capacités héritées par
les flux de fichiers du fait qu’ils sont des classes de flux.
Les flux de fichier vous permettent en outre d’accéder au handle du fichier, pour
que vous puissiez les utiliser avec des routines de gestion de fichiers globales
ayant besoin de ce handle.

Création et ouverture de fichiers en utilisant des flux de fichier


Pour créer ou ouvrir un fichier et accéder à son handle, il suffit d’instancier un
TFileStream. Cela crée ou ouvre le fichier spécifié et propose des méthodes qui
permettent de lire ou d’écrire dans le fichier. Si le fichier ne peut pas être ouvert,
le constructeur TFileStream déclenche une exception.
__fastcall TFileStream(const AnsiString FileName, Word Mode);
Le paramètre Mode spécifie comment le fichier doit être ouvert à la création du
flux de fichier. Le paramètre Mode est constitué d’un mode d’ouverture et d’un
mode de partage reliés par un OU logique. Le mode d’ouverture doit prendre
l’une des valeurs suivantes :

Tableau 4.1 Modes d’ouverture


Valeur Signification
fmCreate TFileStream crée un fichier portant le nom spécifié. S’il existe déjà un
fichier portant ce nom, il est ouvert en mode écriture.
fmOpenRead Ouvre le fichier en lecture seulement.
fmOpenWrite Ouvre le fichier en écriture seulement. L’écriture dans le fichier
remplace son contenu actuel.
fmOpenReadWrite Ouvre le fichier pour en modifier le contenu et non pour le
remplacer.

4-6 Guide du développeur


Utilisation des fichiers

Le mode de partage peut prendre l’une des valeurs suivantes, avec les
restrictions énumérées ci-dessous :

Tableau 4.2 Modes de partage


Valeur Signification
fmShareCompat Le partage est compatible avec la manière dont les FCB sont ouverts.
fmShareExclusive En aucun cas une autre application ne peut ouvrir le fichier.
fmShareDenyWrite Les autres applications peuvent ouvrir le fichier en lecture, mais pas
en écriture.
fmShareDenyRead Les autres applications peuvent ouvrir le fichier en écriture, mais pas
en lecture.
fmShareDenyNone Rien n’empêche les autres applications de lire ou d’écrire dans le
fichier.

Notez que le mode de partage utilisable dépend du mode d’ouverture utilisé.


Le tableau suivant montre les modes de partage associés à chaque mode
d’ouverture.

Tableau 4.3 Modes de partage disponibles pour chaque mode d’ouverture


Mode d’ouverture fmShareCompat fmShareExclusive fmShareDenyWrite fmShareDenyRead fmShareDenyNone
fmOpenRead Non utilisable Non utilisable Disponible Non utilisable Disponible
fmOpenWrite Disponible Disponible Non utilisable Disponible Disponible
fmOpenReadWrite Disponible Disponible Disponible Disponible Disponible

Les constantes d’ouverture et de partage de fichiers sont définies dans l’unité


SysUtils.

Utilisation du handle de fichier


En instanciant TFileStream, vous avez accès au handle de fichier. Le handle de
fichier est contenu dans la propriété Handle. Sous Windows, Handle est un handle
de fichier Windows. Sous les versions Linux de CLX, il s’agit d’un handle de
fichier Linux. Handle est en lecture seule et reflète le mode d’ouverture du
fichier. Si vous voulez modifier les attributs du handle de fichier, vous devez
créer un nouvel objet flux de fichier.
Certaines routines de manipulation de fichiers attendent comme paramètre un
handle de fichier. Quand vous disposez d’un flux de fichier, vous pouvez utiliser
la propriété Handle dans toutes les situations où vous utiliseriez un handle de
fichier. Attention car à la différence des handles de flux, les flux de fichiers
ferment les handles de fichiers quand l’objet est détruit.

Manipulation de fichiers
Plusieurs opérations courantes portant sur les fichiers sont prédéfinies dans la
bibliothèque d’exécution BaseCLX. Les procédures et fonctions manipulant les
fichiers agissent à un niveau élevé. Pour la plupart des routines, il vous suffit de

Utilisation de BaseCLX 4-7


Utilisation des fichiers

spécifier le nom du fichier, et la routine effectue alors pour vous les appels
nécessaires au système d’exploitation. Dans certains cas, vous utiliserez à la place
des handles de fichiers.
Attention Au contraire du langage Pascal Objet, le système d’exploitation Linux distingue
majuscules et minuscules. Faites attention à la casse des caractères lorsque vous
travaillez avec des fichiers dans des applications multi-plates-formes.

Suppression d’un fichier


La suppression efface un fichier du disque et retire son entrée du répertoire du
disque. Il n’y a pas d’opération inverse pour restaurer un fichier supprimé : les
applications doivent donc généralement demander à l’utilisateur de confirmer
avant de supprimer des fichiers. Pour supprimer un fichier, transmettez le nom
du fichier à la fonction DeleteFile :
DeleteFile(FileName);
DeleteFile renvoie true si le fichier a été supprimé, et false s’il ne l’a pas été (par
exemple, si le fichier n’existait pas ou s’il était en lecture seule). DeleteFile
supprime sur disque le fichier nommé NomFichier.

Recherche d’un fichier


Les trois routines suivantes permettent de chercher un fichier : FindFirst, FindNext
et FindClose. FindFirst recherche la première instance d’un nom de fichier ayant
un ensemble spécifié d’attributs dans un répertoire spécifié. FindNext renvoie
l’entrée suivante correspondant au nom et aux attributs spécifiés dans un appel
précédent de FindFirst. FindClose libère la mémoire allouée par FindFirst. Vous
devez toujours utiliser FindClose pour clore une séquence FindFirst/FindNext. Si
vous voulez simplement savoir si un fichier existe, une fonction FileExists renvoie
true si le fichier existe, false sinon.
Les trois routines de recherche de fichier attendent dans leurs paramètres un
TSearchRec. TSearchRec définit les informations du fichier recherché par FindFirst
ou FindNext. TSearchRec a la déclaration suivante :
struct TSearchRec
{
int Time; // marqueur date/heure du fichier
int Size; // taille du fichier en octets
int Attr; // indicateurs d’attributs du fichier
AnsiString Name; // nom et extension du fichier
int ExcludeAttr; // indicateurs d’attributs de fichier pour les fichiers à ignorer
unsigned FindHandle;
_WIN32_FIND_DATAA FindData; // structure avec informations supplémentaires
} ;
Si un fichier est trouvé, les champs du paramètre de type TSearchRec sont
modifiés pour décrire le fichier trouvé. Vous pouvez comparer Attr aux

4-8 Guide du développeur


Utilisation des fichiers

constantes ou valeurs d’attributs suivantes pour déterminer si un fichier possède


un attribut donné :

Tableau 4.4 Constantes et valeurs d’attributs


Constante Valeur Description
faReadOnly 0x00000001 Fichiers en lecture seule
faHidden 0x00000002 Fichiers cachés
faSysFile 0x00000004 Fichiers système
faVolumeID 0x00000008 Fichiers d’identification de volume
faDirectory 0x00000010 Fichiers répertoire
faArchive 0x00000020 Fichiers archive
faAnyFile 0x0000003F Tous les fichiers

Pour tester un attribut, combinez la valeur du champ Attr et la constante


d’attribut en utilisant l’opérateur &. Si le fichier possède cet attribut, le résultat
sera supérieur à 0. Par exemple, si le fichier trouvé est caché, l’évaluation de
l’expression suivante donnera true : (SearchRec.Attr & faHidden > 0). Il est possible
de combiner les attributs en associant avec l’opérateur OR leurs constantes ou
valeurs. Par exemple, pour rechercher les fichiers en lecture seule et les fichiers
cachés en plus des fichiers normaux, transmettez (faReadOnly | faHidden) comme
paramètre Attr.
Exemple : Cet exemple utilise une fiche contenant un libellé, un bouton nommé Search et
un bouton nommé Again. Quand l’utilisateur clique sur le bouton Search, le
premier fichier du répertoire spécifié est trouvé et son nom et sa taille en octets
sont affichés dans l’intitulé du libellé. A chaque fois que l’utilisateur clique sur
le bouton Again, le nom et la taille du fichier correspondant suivant sont affichés
dans le libellé :
TSearchRec SearchRec; // variable globale
void __fastcall TForm1::SearchClick(TObject *Sender)
{
FindFirst("c:\\Program Files\\bcb6\\bin\\*.*", faAnyFile, SearchRec);
Label1->Caption = SearchRec->Name + " occupe " + IntToStr(SearchRec.Size) + " octets";
}
void __fastcall TForm1::AgainClick(TObject *Sender)
{
if (FindNext(SearchRec) == 0)
Label1->Caption = SearchRec->Name + " occupe " + IntToStr(SearchRec.Size) + " octets";
else
FindClose(SearchRec);
}
Remarque Dans les applications multi-plates-formes, vous devez remplacer les chemins
d’accès codés en dur par le chemin d’accès correct du système, ou utiliser des
variables d’environnement (page Variables d’environnement après avoir choisi
Outils|Options d’environnement) pour les représenter.

Utilisation de BaseCLX 4-9


Utilisation des fichiers

Modification d’un nom de fichier


Pour changer le nom d’un fichier, utilisez la fonction RenameFile :
extern PACKAGE bool __fastcall RenameFile(const AnsiString OldName, const AnsiString
NewName);
RenameFile remplace un nom de fichier, identifié par OldFileName, par le nom
spécifié par NewFileName. Si l’opération réussit, RenameFile renvoie true. Si le
fichier ne peut pas être renommé (par exemple, si un fichier appelé NewFileName
existe déjà), RenameFile renvoie false. Par exemple :
if (!RenameFile("OLDNAME.TXT","NEWNAME.TXT"))
ErrorMsg("Erreur en renommant le fichier!");
Il n’est pas possible de renommer (déplacer) un fichier entre plusieurs lecteurs
en utilisant RenameFile. Pour ce faire, vous devez commencer par copier le
fichier, puis supprimer le fichier original.
Remarque RenameFile, dans la bibliothèque d’exécution BaseCLX, est une enveloppe pour la
fonction MoveFile de l’API Windows, et MoveFile ne fonctionne donc pas non
plus d’un lecteur à l’autre.

Routines date-heure de fichier


Les routines FileAge, FileGetDate et FileSetDate agissent sur les valeurs date-heure
du système d’exploitation. FileAge renvoie le marqueur date-heure d’un fichier,
ou -1 si le fichier n’existe pas. FileSetDate définit le marqueur date-heure du
fichier spécifié et renvoie zéro en cas de réussite ou un code d’erreur en cas
d’échec. FileGetDate renvoie un marqueur date-heure pour le fichier spécifié ou -1
si le handle est invalide.
Comme la plupart des routines de manipulation de fichier, FileAge utilise un
nom de fichier sous forme de chaîne. Par contre, FileGetDate et FileSetDate
utilisent un paramètre entier qui accepte un handle de fichier. Pour obtenir le
handle de fichier, vous pouvez
• Utiliser la fonction FileOpen ou la fonction FileCreate pour créer un nouveau
fichier ou ouvrir un fichier existant. FileOpen et FileCreate renvoient toutes
deux le handle du fichier.
• Instancier TFileStream pour créer ou ouvrir un fichier. Utilisez ensuite sa
propriété Handle. Voir “Utilisation de flux de fichier” à la page 4-6 pour plus
d’informations.

Copie d’un fichier


La bibliothèque d’exécution BaseCLX ne fournit pas de routines pour copier un
fichier. Mais si vous écrivez des applications uniquement pour Windows, vous
pouvez appeler directement la fonction CopyFile de l’API Windows pour copier
un fichier. Comme la plupart des routines de la bibliothèque d’exécution,
CopyFile accepte comme paramètre un nom de fichier et non un handle de
fichier. Faites attention lorsque vous copiez un fichier, car les attributs du fichier
existant sont copiés dans le nouveau fichier, alors que les attributs de sécurité ne
sont pas copiés. CopyFile est également utile pour déplacer des fichiers d’un

4-10 Guide du développeur


Utilisation des fichiers ini et du registre

lecteur à un autre, car ni la fonction RenameFile, ni la fonction MoveFile de l’API


Windows ne peuvent renommer ou déplacer des fichiers entre lecteurs. Pour
plus d’informations, voir l’aide en ligne de Windows.

Utilisation des fichiers ini et du registre


De nombreuses applications utilisent des fichiers ini pour stocker des
informations de configuration. BaseCLX inclut deux classes pour travailler avec
des fichiers ini : TIniFile et TMemIniFile. L’utilisation des fichiers ini présente
l’avantage qu’ils peuvent être utilisés dans des applications multi-plates-formes
et qu’ils sont faciles à lire et à modifier. Pour plus d’informations sur ces classes,
voir “Utilisation de TIniFile et TMemIniFile” à la page 4-11.
De nombreuses applications Windows remplacent l’utilisation des fichiers ini par
la base des registres. La base des registres Windows est une base de données
hiérarchique qui agit comme un espace de stockage centralisé pour les
informations de configuration. La VCL inclut des classes pour travailler avec la
base de registres. Alors qu’elles ne font techniquement pas partie de BaseCLX
(car elles sont uniquement disponibles sous Windows), deux de ces classes,
TRegistryIniFile et TRegistry, sont traitées ici à cause de leur similitude avec les
classes pour la manipulation des fichiers ini.
TRegistryIniFile est utile pour les applications multi-plates-formes, car elle partage
un ancêtre commun (TCustomIniFile) avec les classes fonctionnant avec les
fichiers ini. Si vous vous limitez aux méthodes de l’ancêtre commun
(TCustomIniFile), votre application peut travailler sur les deux applications avec
un minimum de code conditionnel. TRegistryIniFile est traitée dans “Utilisation
de TRegistryIniFile” à la page 4-13.
Pour les applications qui ne sont pas multi-plates-formes, vous pouvez utiliser la
classe TRegistry. Les propriétés et méthodes de TRegistry possèdent des noms qui
correspondent plus directement à la manière dont la base des registres est
organisée, car elles n’ont pas à être compatibles avec les classes pour les fichiers
ini. TRegistry est traitée dans “Utilisation de TRegistry” à la page 4-13.

Utilisation de TIniFile et TMemIniFile


Le format de fichier ini est toujours utilisé, et de nombreux fichiers de
configuration (comme le fichier DSK de configuration du bureau) sont dans ce
format. Ce format est particulièrement utile dans des applications multi-plates-
formes, où vous ne pouvez pas toujours compter sur une base de registres pour
stocker les informations de configuration. BaseCLX fournit deux classes, TIniFile
et TMemIniFile, pour faciliter grandement la lecture et l’écriture des fichiers ini.
Sous Linux, TMemIniFile et TIniFile sont identiques. Sous Windows, TIniFile
travaille directement avec le fichier ini sur disque, tandis que TMemIniFile stocke
toutes les modifications en mémoire et ne les écrit sur disque que lorsque vous
appelez la méthode UpdateFile.
Quand vous instanciez l’objet TIniFile ou TMemIniFile, il faut transmettre au
constructeur un paramètre spécifiant le nom du fichier ini. Si le fichier n’existe

Utilisation de BaseCLX 4-11


Utilisation des fichiers ini et du registre

pas déjà, il est créé automatiquement. Vous êtes alors libre de lire les valeurs en
utilisant différentes méthodes de lecture, comme ReadString, ReadDate, ReadInteger
ou ReadBool. Par ailleurs, si vous souhaitez lire une section entière du fichier ini,
vous pouvez utiliser la méthode ReadSection. De même, vous pouvez écrire des
valeurs en utilisant WriteBool, WriteInteger, WriteDate ou WriteString.
L’exemple suivant lit des informations de configuration d’un fichier ini dans le
constructeur d’une fiche et écrit des valeurs dans le gestionnaire d’événement
OnClose.
__fastcall TForm1::TForm1(TComponent *Owner) : TForm(Owner)
{
TIniFile *ini;
ini = new TIniFile( ChangeFileExt( Application->ExeName, ".INI" ) );

Top = ini->ReadInteger( "Form", "Top", 100 );


Left = ini->ReadInteger( "Form", "Left", 100 );
Caption = ini->ReadString( "Form", "Caption",
"Default Caption" );
ini->ReadBool( "Form", "InitMax", false ) ?
WindowState = wsMaximized :
WindowState = wsNormal;

delete ini;
}

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)


{
TIniFile *ini;
ini = new TIniFile(ChangeFileExt( Application->ExeName, ".INI" ) );
ini->WriteInteger( "Form", "Top", Top );
ini->WriteInteger( "Form", "Left", Left );
ini->WriteString ( "Form", "Caption", Caption );
ini->WriteBool ( "Form", "InitMax",
WindowState == wsMaximized );

delete ini;
}
Chacune des routines Read attend trois paramètres. Le premier identifie la
section du fichier ini. Le deuxième paramètre identifie la valeur à lire et le
troisième est une valeur par défaut à utiliser si la section ou la valeur n’existe
pas dans le fichier ini. De même que les méthodes Read gèrent de manière
élégante la non existence d’une section ou d’une valeur, les routines Write
crééent la section et/ou la valeur si elle n’existe pas. L’exemple précédent crée
un fichier ini la première fois qu’il est exécuté, et ce fichier est de la forme :
[Form]
Top=185
Left=280
Caption=Default Caption
InitMax=0
Lors des exécutions ultérieures de cette application, les valeurs ini sont lues lors
de la création de la fiche et réécrites dans l’événement OnClose.

4-12 Guide du développeur


Utilisation des fichiers ini et du registre

Utilisation de TRegistryIniFile
De nombreuses applications Windows 32 bits stockent leurs informations dans la
base de registres plutôt que dans des fichiers ini, car cette base est hiérarchique
et ne souffre pas des limitations de taille inhérentes aux fichiers ini. Si vous êtes
habitué à utiliser des fichiers ini et souhaitez transférer vos informations de
configuration dans la base de registres, vous pouvez utiliser la classe
TRegistryIniFile. Vous pouvez également utiliser TRegistryIniFile dans des
applications multi-plates-formes si vous voulez utiliser la base de registres sous
Windows et un fichier ini sous Linux. Vous pouvez écrire la plus grande partie
de votre application de façon à ce qu’elle utilise le type TCustomIniFile. Vous
devez uniquement introduire des conditions dans le code qui crée une instance
de TRegistryIniFile (sous Windows) ou TMemIniFile (sous Linux) et l’affecter à
l’objet TCustomIniFile utilisé par votre application.
TRegistryIniFile crée une similitude entre les entrées de la base de registres et
celles du fichier ini. Toutes les méthodes de TIniFile et TMemIniFile (lecture et
écriture) existent dans TRegistryIniFile.
Quand vous créez un objet TRegistryIniFile, le paramètre que vous transmettez au
constructeur (correspondant au nom du fichier pour un objet IniFile ou
TMemIniFile) devient une valeur de clé sous la clé de l’utilisateur dans la base de
registres. Toutes les sections et valeurs commencent à partir de la clé ainsi
transmise. TRegistryIniFile simplifie considérablement l’interfaçage avec la base de
registres, de sorte que vous pourriez vouloir l’utiliser à la place du composant
TRegistry, même si vous ne migrez pas un code existant ou si vous n’écrivez pas
une application multi-plates-formes.

Utilisation de TRegistry
Si vous écrivez une application uniquement sous Windows et si vous connaissez
bien la structure de la base de registres, vous pouvez utiliser TRegistry. A la
différence de TRegistryIniFile, qui utilise les mêmes propriétés et méthodes des
autres composants du fichier ini, les propriétés et les méthodes de TRegistry
correspondent plus directement à la structure de la base de registres. Par
exemple, TRegistry vous permet de spécifier la clé racine et la sous-clé, alors que
TRegistry adopte HKEY_CURRENT_USER comme clé racine. En plus des
méthodes pour l’ouverture, la fermeture, l’enregistrement, le déplacement et la
suppression des clés, TRegistry vous permet de spécifier le niveau d’accès que
vous voulez utiliser.
Remarque TRegistry ne peut pas être utilisé en programmation multiplates-formes.
L’exemple suivant lit une valeur dans une entrée de registre :
#include <Registry.hpp>

AnsiString GetRegistryValue(AnsiString KeyName)


{
AnsiString S;
TRegistry *Registry = new TRegistry(KEY_READ);
try
{
Registry->RootKey = HKEY_LOCAL_MACHINE;

Utilisation de BaseCLX 4-13


Utilisation des listes

// False car nous ne voulons pas la créer si elle n’existe pas


Registry->OpenKey(KeyName,false);
S = Registry->ReadString("VALUE1");
}
__finally
{
delete Registry;
}
return S;
}

Utilisation des listes


BaseCLX inclut de nombreuses classes représentant des listes ou des collections
d’éléments. Ces classes varient en fonction des types d’éléments qu’elles
contiennent, des opérations qu’elles supportent et de leur persistance.
Le tableau suivant énumère les différentes classes de listes et indique les types
d’éléments qu’elles contiennent :
Tableau 4.5 Classes pour la gestion de listes
Objet Gère
TList Une liste de pointeurs
TThreadList Une liste de pointeurs adaptée aux threads
TBucketList Une liste de pointeurs à accès direct
TObjectBucketList Une liste d’instances d’objet à accès direct
TObjectList Une liste d’instances d’objets, gérée en mémoire
TComponentList Une liste de composants gérée en mémoire (c’est-à-dire d’instances de
classes dérivées de TComponent)
TClassList Une liste de références de classes (métaclasses)
TInterfaceList Une liste de pointeurs d’interfaces.
TQueue Une liste de pointeurs premier entré, premier sorti
TStack Une liste de pointeurs dernier entré, premier sorti
TObjectQueue Une liste d’objets premier entré, premier sorti
TObjectStack Une liste d’objets dernier entré, premier sorti
TCollection Classe de base pour de nombreuses classes spécialisées d’éléments typés.
TStringList Une liste de chaînes
THashedStringList Une liste de chaînes de la forme Nom=Valeur, à accès direct pour les
performances.

Opérations de listes courantes


Bien que les différentes classes de listes contiennent différents types d’éléments
et possèdent différents ancêtres, la plupart d’entre elles partagent un ensemble
commun de méthodes pour l’ajout, la suppression, la réorganisation et l’accès
aux éléments de la liste.

4-14 Guide du développeur


Utilisation des listes

Ajout d’éléments de liste


La plupart des classes de listes possèdent une méthode Add qui vous permet
d’ajouter un élément à la fin de la liste (si la liste n’est pas triée) ou à sa position
appropriée (si la liste est triée). Généralement, la méthode Add prend comme
paramètre l’élément que vous ajoutez à la liste et renvoie la position dans la liste
où l’élément a été ajouté. Dans le cas de listes de compartiments (TBucketList et
TObjectBucketList), Add ne prend pas uniquement l’élément à ajouter, mais
également une donnée que vous pouvez lui associer. Dans le cas des collections,
Add ne prend aucun paramètre, mais crée un nouvel élément qu’il ajoute. La
méthode Add sur les collections renvoie l’élément qui a été ajouté, pour que vous
puissiez affecter des valeurs aux propriétés de ce nouvel élément.
Certaines classes de listes possèdent une méthode Insert en plus de la méthode
Add. Insert fonctionne de la même façon que la méthode Add, mais elle possède
un paramètre supplémentaire qui vous permet de spécifier la position dans la
liste où vous souhaitez voir le nouvel élément. Si une classe possède une
méthode Add, elle possède également une méthode Insert si la position des
éléments n’est pas prédéterminée. Par exemple, vous ne pouvez pas utiliser Insert
avec les listes triées, car les éléments doivent être dans l’ordre de tri, et vous ne
pouvez pas utiliser Insert avec les listes de compartiments, car l’algorithme de
hachage détermine la position de l’élément.
Les seules classes ne possédant pas de méthode Add sont les listes ordonnées.
Les listes ordonnées sont constituées de files et de piles. Pour ajouter des
éléments à une liste ordonnée, utilisez plutôt la méthode Push. Push, comme Add,
prend un élément comme paramètre et l’insère à la position correcte.

Suppression d’éléments de liste


Pour supprimer un seul élément d’une des classes de listes, utilisez soit la
méthode Delete soit la méthode Remove. Delete accepte un seul paramètre, l’indice
de l’élément à supprimer. Remove accepte également un seul paramètre, mais ce
paramètre est une référence de l’élément à supprimer, plutôt que son indice.
Certaines classes de listes prennent uniquement en charge une méthode Delete,
d’autres prennent uniquement en charge une méthode Remove et certaines
prennent en charge les deux.
Comme pour l’ajout d’éléments, les listes ordonnées se comportent différemment
de toutes les autres listes. Au lieu d’utiliser une méthode Delete ou Remove, vous
supprimez un élément d’une liste ordonnée en appelant sa méthode Pop. Pop
n’accepte aucun argument, car il n’existe qu’un seul élément qui puisse être
supprimé.
Si vous souhaitez supprimer tous les éléments de la liste, vous pouvez appeler la
méthode Clear. Clear est disponible pour toutes les listes à l’exception des listes
ordonnées.

Accès aux éléments de la liste


Toutes les classes de listes (à l’exception de TThreadList et des listes ordonnées)
possèdent une propriété qui vous permet d’accéder aux éléments de la liste.
Cette propriété s’appelle généralement Items. Pour les listes de chaînes, la

Utilisation de BaseCLX 4-15


Utilisation des listes

propriété s’appelle Strings, et pour les listes de compartiments, elle s’appelle


Data. La propriété Items, Strings ou Data est une propriété indexée, avec laquelle
vous pouvez spécifier l’élément auquel vous voulez accéder.
Avec TThreadList, vous devez verrouiller la liste avant de pouvoir accéder aux
éléments. Lorsque vous verrouillez la liste, la méthode LockList renvoie un objet
TList que vous pouvez utiliser pour accéder aux éléments.
Les listes ordonnées vous permettent d’accéder à l’élément “supérieur” de
la liste. Vous pouvez obtenir une référence sur cet élément en appelant la
méthode Peek.

Réorganisation d’éléments de liste


Certaines classes de listes possèdent des méthodes qui vous permettent de
réorganiser les éléments dans la liste. Certaines possèdent une méthode Exchange,
qui échange les positions de deux éléments. Certaines possèdent une méthode
Move qui vous permet de déplacer un élément vers un emplacement spécifié.
Certaines possèdent une méthode Sort qui vous permet de trier les éléments
dans la liste.
Pour connaître les méthodes disponibles, consultez l’aide en ligne pour la classe
de listes que vous utilisez.

Listes persistantes
Les listes persistantes peuvent être enregistrées dans un fichier de fiche. C’est la
raison pour laquelle elles sont souvent utilisées comme type d’une propriété
publiée sur un composant. Vous pouvez ajouter des éléments à la liste lors de la
conception, et ces éléments sont enregistrés avec l’objet afin d’être présents
lorsque le composant qui les utilise est chargé en mémoire à l’exécution. Il existe
deux types principaux de listes persistantes : les listes de chaînes et les
collections.
Parmi les listes de chaînes figurent TStringList et THashedStringList. Comme leur
nom l’indique, les listes de chaînes contiennent des chaînes. Elles fournissent une
prise en charge particulière des chaînes de la forme Nom=Valeur, pour vous
permettre de rechercher la valeur associée à un nom. De plus, la plupart des
listes de chaînes vous permettent d’associer un objet à chaque chaîne de la liste.
Les listes de chaînes sont décrites plus en détail dans “Utilisation des listes de
chaînes” à la page 4-17.
Les collections dérivent de la classe TCollection. Chaque descendant de TCollection
est spécialement conçu pour gérer une classe particulière d’éléments, où cette
classe dérive de TCollectionItem. Les collections prennent en charge de
nombreuses opérations de listes courantes. Toutes les collections sont conçues
pour être le type d’une propriété publiée, et un grand nombre ne peuvent pas
fonctionner indépendamment de l’objet qui les utilise pour une implémentation
sur la base de ses propriétés. Lors de la conception, la propriété dont la valeur
est une collection peut utiliser l’éditeur de collection pour vous permettre

4-16 Guide du développeur


Utilisation des listes de chaînes

d’ajouter, de supprimer et de réorganiser les éléments. L’éditeur de collection


fournit une interface utilisateur commune pour la manipulation des collections.

Utilisation des listes de chaînes


Un des types de listes les plus couramment utilisés est une liste de chaînes de
caractères. Par exemple, pour les éléments d’une boîte à options, les lignes d’un
mémo, les noms de fonte ou les noms des lignes et colonnes d’une grille de
chaînes. BaseCLX fournit une interface courante pour toute liste de caractères par
l’intermédiaire d’un objet appelé TStrings et ses descendants comme TStringList
et THashedStringList. TStringList implémente les propriétés et méthodes abstraites
introduites par TStrings, et introduit les propriétés, événements et méthodes pour
• Trier les chaînes de la liste,
• Interdire les chaînes en double dans les listes triées,
• Répondre aux changements du contenu de la liste.
Outre les fonctionnalités concernant la gestion de listes de chaînes, ces objets
permettent une interopérabilité simple ; vous pouvez ainsi modifier les lignes
d’un mémo (descendant de TStrings), puis utiliser ces lignes comme éléments
d’une boîte à options (également descendant de TStrings).
Une propriété liste de chaînes apparaît dans l’inspecteur d’objets avec TStrings
dans la colonne des valeurs. Double-cliquez sur TStrings pour ouvrir l’éditeur de
liste de chaînes qui vous permet de modifier, d’ajouter ou de supprimer des
chaînes.
Vous pouvez également manipuler les objets listes de chaînes lors de l’exécution
pour effectuer les opérations suivantes :
• Lecture et enregistrement des listes de chaînes
• Création d’une nouvelle liste de chaînes
• Manipulation des chaînes d’une liste
• Association d’objets à une liste de chaînes

Lecture et enregistrement des listes de chaînes


Les objets listes de chaînes disposent des méthodes SaveToFile et LoadFromFile qui
permettent de stocker une liste de chaînes dans un fichier texte ou de charger un
fichier texte dans une liste de chaînes. Chaque ligne du fichier texte correspond à
une chaîne de la liste. En utilisant ces méthodes, vous pouvez, par exemple,
créer un éditeur de texte simple en chargeant un fichier dans un composant
mémo ou enregistrer les listes d’éléments de boîtes à options.
L’exemple suivant charge une copie du fichier WIN.INI dans un champ mémo et
en effectue une copie de sauvegarde nommée WIN.BAK.
void __fastcall EditWinIni()
{
AnsiString FileName = "C:\\WINDOWS\\WIN.INI"; // définit le nom du fichier

Utilisation de BaseCLX 4-17


Utilisation des listes de chaînes

Form1->Memo1->Lines->LoadFromFile(FileName); // lit depuis le fichier


Form1->Memo1->Lines->SaveToFile(ChangeFileExt(FileName, ".BAK")); // enregistre
// la sauvegarde
}

Création d’une nouvelle liste de chaînes


Habituellement, les listes de chaînes font partie intégrante de composants.
Néanmoins, il est parfois commode de créer des listes de chaînes autonomes qui
n’ont pas de composant associé (par exemple, pour stocker les chaînes d’une
table de référence). La manière de créer et de gérer une liste de chaînes varie
selon que la liste est une liste à court terme (construite, utilisée et détruite dans
une même routine) ou une liste à long terme (disponible jusqu’à l’arrêt de
l’application). Quel que soit le type de liste de chaînes créé, n’oubliez pas que
c’est à vous de libérer la liste quand vous n’en n’avez plus besoin.

Listes de chaînes à court terme


Si vous utilisez une liste de chaînes uniquement pour la durée d’une seule
routine, vous pouvez la créer, l’utiliser et la détruire au même emplacement.
C’est la méthode la plus fiable pour utiliser des objets listes de chaînes. Comme
l’objet liste de chaînes alloue la mémoire pour lui-même et pour ses chaînes, il
est important de protéger l’allocation en utilisant un bloc try...__finally afin de
garantir que l’objet libère sa mémoire même si une exception a lieu.
1 Construire l’objet liste de chaînes.
2 Utiliser la liste de chaînes dans la partie try d’un bloc try...__finally.
3 Libérer l’objet liste de chaînes dans la partie __finally.
Le gestionnaire d’événement suivant répond au choix d’un bouton en
construisant un objet liste de chaînes, en l’utilisant puis en le détruisant :
void __fastcall TForm1::ButtonClick1(TObject *Sender)
{
TStringList *TempList = new TStringList; // déclare la liste
try{
// utilise la liste de chaînes
}
__finally{
delete TempList; // détruit l’objet liste
}
}

Listes de chaînes à long terme


Si la liste de chaînes doit être disponible tout au long de l’exécution de votre
application, vous devez construire la liste au démarrage de l’application et la
détruire avant la fermeture de l’application.
1 Dans le fichier unité de la fiche principale de votre application, ajoutez un
champ de type TStrings à la déclaration de la fiche.

4-18 Guide du développeur


Utilisation des listes de chaînes

2 Ecrivez un constructeur de la fiche principale qui s’exécute avant que la fiche


n’apparaisse. Ce gestionnaire d’événement doit créer une liste de chaînes et
l’affecter au champ déclaré dans la première étape.
3 Ecrivez un gestionnaire d’événement qui libère la liste de chaînes dans
l’événement OnClose de la fiche.
L’exemple suivant utilise une liste de chaînes à long terme pour stocker les clics
de la souris dans la fiche principale, puis enregistre la liste dans un fichier avant
l’arrêt de l’application.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ClickList = new TStringList;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
ClickList->SaveToFile(ChangeFileExt(Application->ExeName, ".LOG"));//enregistre la liste
delete ClickList;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
TVarRec v[] = {X,Y};
ClickList->Add(Format("Clic à (%d, %d)",v,ARRAYSIZE(v) - 1));// ajoute une chaîne
// à la liste
}
}

Manipulation des chaînes d’une liste


Les opérations couramment effectuées sur les listes de chaînes sont les suivantes :
• Comptage des chaînes d’une liste
• Accès à une chaîne spécifique
• Recherche de la position d’une chaîne dans la liste
• Parcours des chaînes d’une liste
• Ajout d’une chaîne à une liste
• Déplacement d’une chaîne dans une liste
• Suppression d’une chaîne d’une liste
• Copie de la totalité d’une liste de chaînes

Utilisation de BaseCLX 4-19


Utilisation des listes de chaînes

Comptage des chaînes d’une liste


La propriété en lecture seule Count renvoie le nombre de chaînes dans la liste.
Comme les listes de chaînes utilisent des indices de base zéro, Count correspond
à l’indice de la dernière chaîne plus un.

Accès à une chaîne spécifique


La propriété tableau Strings contient les chaînes de la liste, référencées par un
indice de base zéro.
StringList1->Strings[0] = “Première chaîne.”;

Recherche d’éléments dans une liste de chaînes


Pour rechercher une chaîne dans une liste de chaînes, utilisez la méthode
IndexOf. IndexOf renvoie l’indice de la première chaîne de la liste qui correspond
au paramètre transmis, et renvoie –1 si la chaîne transmise en paramètre n’est
pas trouvée. IndexOf recherche uniquement une correspondance exacte ; si vous
voulez obtenir des chaînes de correspondance partielle, vous devez parcourir la
liste de chaînes.
Vous pouvez, par exemple, utiliser IndexOf pour déterminer si un nom de fichier
donné se trouve dans les éléments Items d’une boîte liste :
if (FileListBox1->Items->IndexOf("WIN.INI") > -1) ...

Parcours des chaînes d’une liste


Pour parcourir les chaînes d’une liste, utilisez une boucle for allant de zéro à
Count – 1.
L’exemple suivant convertit en majuscules chaque chaîne d’une boîte liste.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (int i = 0; i < ListBox1->Items->Count; i++)
ListBox1->Items->Strings[i] = UpperCase(ListBox1->Items->Strings[i]);
}

Ajout d’une chaîne à une liste


Pour ajouter une chaîne à la fin d’une liste de chaînes, utilisez la méthode Add
en lui transmettant en paramètre la nouvelle chaîne. Pour insérer une chaîne
dans la liste, appelez la méthode Insert en lui transmettant deux paramètres : la
chaîne et l’indice à laquelle elle doit être placée. Si, par exemple, vous voulez
placer la chaîne “Trois” en troisième position dans une liste, utilisez :
StringList1->Insert(2, "Trois");
Pour ajouter à une liste les chaînes d’une autre liste, appelez AddStrings :
StringList1->AddStrings(StringList2); // ajoute à StringList1 les chaînes de StringList2

4-20 Guide du développeur


Utilisation des listes de chaînes

Déplacement d’une chaîne dans une liste


Pour déplacer une chaîne dans une liste de chaînes, appelez la méthode Move en
lui transmettant deux paramètres : l’indice en cours de la chaîne et son nouvel
indice. Par exemple, pour déplacer la troisième chaîne de la liste en cinquième
position, utilisez :
StringListObject->Move(2, 4);

Suppression d’une chaîne d’une liste


Pour supprimer une chaîne d’une liste de chaînes, appelez la méthode Delete de
la liste en lui transmettant l’indice de la chaîne à supprimer. Si vous ne
connaissez pas l’indice de la chaîne à supprimer, utilisez la méthode IndexOf
pour le déterminer. Pour supprimer toutes les chaînes de la liste, utilisez la
méthode Clear.
L’exemple suivant utilise IndexOf et Delete pour trouver et supprimer une
chaîne :
int BIndex = ListBox1->Items->IndexOf("bureaucratie");
if (BIndex > -1)
ListBox1->Items->Delete(BIndex);

Copie de la totalité d’une liste de chaînes


Vous pouvez utiliser la méthode Assign pour copier les chaînes d’une liste source
vers une liste de destination en remplaçant le contenu de la liste de destination.
Pour ajouter les chaînes sans remplacer la liste de destination, utilisez la
méthode AddStrings. Par exemple,
Memo1->Lines->Assign(ComboBox1->Item)s; // remplace les chaînes existantes
copie les lignes d’une boîte à options dans un mémo (en écrasant le contenu du
mémo), alors que :
Memo1->Lines->AddStrings(ComboBox1->Items);// ajoute les chaînes à la fin
ajoute au mémo les lignes de la boîte à options.
Quand vous effectuez une copie locale d’une liste de chaînes, utilisez la méthode
Assign. Si vous affectez une variable liste de chaînes à une autre :
StringList1 = StringList2;
l’objet liste de chaînes initial est perdu, ce qui peut donner des résultats
imprévisibles.

Association d’objets à une liste de chaînes


Outre les chaînes stockées dans sa propriété Strings, une liste de chaînes peut
gérer des références à des objets dans sa propriété Objects. Comme Strings, Objects
est un tableau d’indice zéro. Le plus souvent, Objects sert à associer des bitmaps
à des chaînes dans des contrôles dessinés par le propriétaire.
Utilisez la méthode AddObject ou InsertObject pour ajouter en une seule étape
une chaîne et un objet associé à la liste. IndexOfObject renvoie l’indice de la
première chaîne de la liste associée à l’objet spécifié. Les méthodes comme Delete,

Utilisation de BaseCLX 4-21


Utilisation des chaînes

Clear et Move agissent à la fois sur les chaînes et les objets ; ainsi, la suppression
d’une chaîne supprime également l’éventuel objet correspondant.
Pour associer un objet à une chaîne existante, affectez l’objet à la propriété
Objects pour le même indice. Vous ne pouvez pas ajouter d’objet sans ajouter
une chaîne correspondante.

Utilisation des chaînes


La bibliothèque d’exécution BaseCLX propose de nombreuses routines de
manipulation des chaînes spécialisées pour les différents types chaînes. Il existe
des routines pour les chaînes étendues, AnsiStrings et les chaînes à zéro terminal
(char *). Les routines gérant les chaînes à zéro terminal utilisent le zéro terminal
pour déterminer la longueur de la chaîne. Les rubriques suivantes fournissent
une présentation de nombreuses routines de manipulation de chaînes dans la
bibliothèque d’exécution.

Routines manipulant les caractères étendus


Les chaînes étendues sont utilisées dans diverses situations. Certaines
technologies, comme XML, utilisent des chaînes étendues comme type natif.
Vous pouvez également choisir d’utiliser des chaînes étendues car elles
simplifient certains problèmes de gestion de chaînes dans les applications avec
plusieurs paramètres régionaux cibles. L’utilisation d’un schéma de codage avec
des caractères étendus présente l’avantage que vous pouvez réaliser sur les
chaînes des hypothèses qui ne sont pas valables avec les systèmes MBCS. Il
existe en effet une relation directe entre le nombre d’octets de la chaîne et son
nombre de caractères. Il n’y a pas le risque, comme avec les jeux de caractères
MBCS, de couper un caractère en deux ou de confondre le deuxième octet d’un
caractère avec le début d’un autre caractère.
Un inconvénient de l’utilisation des caractères étendus réside dans le fait que la
plupart des contrôles VCL représentent les valeurs de type chaîne sous la forme
de chaînes mono-octets ou MBCS. (Les contrôles CLX utilisent généralement les
chaînes étendues.) La conversion entre le système de caractères étendus et le
système MBCS à chaque définition d’une propriété de chaîne ou d’une lecture de
sa valeur peut nécessiter d’énormes quantités de code supplémentaire et ralentir
votre application. Mais vous pouvez choisir la conversion en caractères étendus
pour certains algorithmes de traitement des chaînes qui tirent profit de la
correspondance 1:1 entre caractères et WideChar.
Les fonctions suivantes effectuent des conversions entre les chaînes de caractères
mono-octet standards (ou les chaînes MBCS) et les chaînes Unicode :
• StringToWideChar
• WideCharLenToString
• WideCharLenToStrVar
• WideCharToString
• WideCharToStrVar

4-22 Guide du développeur


Utilisation des chaînes

De plus, les fonctions suivantes effectuent des conversions entre WideStrings et


d’autres représentations :
• UCS4StringToWideString
• WideStringToUCS4String
• VarToWideStr
• VarToWideStrDef
Les routines suivantes fonctionnent directement avec des WideStrings :
• WideCompareStr
• WideCompareText
• WideSameStr
• WideSameText
• WideSameCaption (uniquement CLX)
• WideFmtStr
• WideFormat
• WideLowerCase
• WideUpperCase
Enfin, certaines routines incluent des surcharges pour travailler avec des chaînes
étendues :
• UniqueString
• Length
• Trim
• TrimLeft
• TrimRight

Routines couramment utilisées pour les AnsiStrings


Les routines de gestion AnsiString couvrent plusieurs domaines fonctionnels.
Dans ces domaines, certaines routines sont utilisées dans le même but mais
varient dans l’utilisation de critères particuliers dans leurs calculs. Les tableaux
suivants énumèrent ces routines en les regroupant selon les domaines
fonctionnels suivants :
• Comparaison
• Conversion majuscules/minuscules
• Modification
• Sous-chaînes
Lorsqu’il y a lieu, les tableaux indiquent également si la routine satisfait le
critère suivant :
• Différence majuscules/minuscules : si les paramètres de localisation sont
utilisés, ils déterminent la définition des caractères majuscules/minuscules. Si
la routine n’utilise pas les paramètres de localisation, les analyses sont fondées
sur la valeur scalaire des caractères. Si la routine ne tient pas compte des
différences majuscules/minuscules, une fusion logique des caractères
majuscules et minuscules déterminée par un modèle prédéfini est effectuée.

Utilisation de BaseCLX 4-23


Utilisation des chaînes

• Utilisation des paramètres de localisation : cela permet de personnaliser votre


application pour des localisations spécifiques, en particulier dans le cas des
environnements pour les langues asiatiques. Dans la plupart des localisations,
les caractères minuscules sont censés être inférieurs aux caractères majuscules
correspondants. C’est l’opposé de l’ordre ASCII dans lequel les caractères
minuscules sont supérieurs aux caractères majuscules. Les routines qui
utilisent la localisation Windows commencent généralement par Ansi
(AnsiXXX).
• Gestion des jeux de caractères multi-octets (MBCS) : les MBCS sont utilisés
pour écrire du code pour les localisations extrême-orientales. Les caractères
multi-octets sont représentés par un mélange de codes de caractères sur un à
deux octets, le nombre d’octets ne correspond donc pas systématiquement à la
longueur de la chaîne. Les routines qui gèrent les MBCS analysent les
caractères sur un ou deux octets.
ByteType et StrByteType déterminent si un octet donné est l’octet de tête d’un
caractère sur deux octets. Faites attention en manipulant des caractères multi-
octets à ne pas tronquer une chaîne en coupant en deux un caractère sur deux
octets. Ne transmettez pas de caractères comme paramètre d’une fonction ou
d’une procédure, puisque la taille d’un caractère ne peut pas être déterminée à
l’avance. Il faut, à la place, transmettre un pointeur sur un caractère ou une
chaîne. Pour davantage d’informations sur MBCS, voir “Codage de l’application”
à la page 16-2 dans le chapitre 16, “Création d’applications internationales”.

Tableau 4.6 Routines de comparaison de chaînes


Utilisation
des paramètres
Routine Différence MAJ/min de localisation Gestion MBCS
AnsiCompareStr Oui Oui Oui
AnsiCompareText Non Oui Oui
AnsiCompareFileName Non Oui Oui
AnsiMatchStr Oui Oui Oui
AnsiMatchText Non Oui Oui
AnsiContainsStr Oui Oui Oui
AnsiContainsText Non Oui Oui
AnsiStartsStr Oui Oui Oui
AnsiStartsText Non Oui Oui
AnsiEndsStr Oui Oui Oui
AnsiEndsText Non Oui Oui
AnsiIndexStr Oui Oui Oui
AnsiIndexText Non Oui Oui
CompareStr Oui Non Non
CompareText Non Non Non
AnsiResemblesText Non Non Non

4-24 Guide du développeur


Utilisation des chaînes

Tableau 4.7 Routines de conversion majuscules/minuscules


Utilisation
des paramètres
Routine de localisation Gestion MBCS
AnsiLowerCase Oui Oui
AnsiLowerCaseFileName Oui Oui
AnsiUpperCaseFileName Oui Oui
AnsiUpperCase Oui Oui
LowerCase Non Non
UpperCase Non Non

Remarque Les routines utilisées pour les noms de fichiers sous forme de chaîne,
AnsiCompareFileName, AnsiLowerCaseFileName et AnsiUpperCaseFileName, utilisent
la localisation Windows. Vous devez toujours utiliser des noms de fichiers
portables, car la localisation (le jeu de caractères) utilisée pour les noms de
fichiers peut différer de celle de l’interface utilisateur par défaut.

Tableau 4.8 Routines de modification de chaîne


Routine Différence MAJ/min Gestion MBCS
AdjustLineBreaks ND Oui
AnsiQuotedStr ND Oui
AnsiReplaceStr Oui Oui
AnsiReplaceText Non Oui
StringReplace précisé par un indicateur Oui
ReverseString ND Non
StuffString ND Non
Trim ND Oui
TrimLeft ND Oui
TrimRight ND Oui
WrapText ND Oui

Tableau 4.9 Routines de sous-chaînes


Routine Différence MAJ/min Gestion MBCS
AnsiExtractQuotedStr ND Oui
AnsiPos Oui Oui
IsDelimiter Oui Oui
IsPathDelimiter Oui Oui
LastDelimiter Oui Oui
LeftStr ND Non
RightStr ND Non
MidStr ND Non
QuotedStr Non Non

Utilisation de BaseCLX 4-25


Utilisation des chaînes

Routines couramment utilisées pour les chaînes à zéro terminal


Il est possible de regrouper les routines manipulant des chaînes à zéro terminal
en plusieurs catégories fonctionnelles. Dans ces catégories, certaines routines sont
utilisées dans le même but mais varient dans l’utilisation de critères particuliers
dans leurs calculs. Les tableaux suivants présentent ces routines en les
regroupant selon les catégories suivantes :
• Comparaison
• Conversion majuscules/minuscules
• Modification
• Sous-chaînes
• Copie
Lorsqu’il y a lieu, les tableaux indiquent également si la routine tient compte de
la casse, si elle utilise la configuration locale et/ou accepte les jeux de caractères
MBCS (Multi-Byte character Sets).

Tableau 4.10 Routines de comparaison de chaînes à zéro terminal


Utilisation
des paramètres
Routine Différence MAJ/min de localisation Gestion MBCS
AnsiStrComp Oui Oui Oui
AnsiStrIComp Non Oui Oui
AnsiStrLComp Oui Oui Oui
AnsiStrLIComp Non Oui Oui
StrComp Oui Non Non
StrIComp Non Non Non
StrLComp Oui Non Non
StrLIComp Non Non Non

Tableau 4.11 Routines de conversion majuscules/minuscules pour les chaînes à zéro terminal
Utilisation
des paramètres
Routine de localisation Gestion MBCS
AnsiStrLower Oui Oui
AnsiStrUpper Oui Oui
StrLower Non Non
StrUpper Non Non

Tableau 4.12 Routines de modification de chaîne


Routine
StrCat
StrLCat

4-26 Guide du développeur


Impression

Tableau 4.13 Routines de sous-chaînes


Routine Différence MAJ/min Gestion MBCS
AnsiStrPos Oui Oui
AnsiStrScan Oui Oui
AnsiStrRScan Oui Oui
StrPos Oui Non
StrScan Oui Non
StrRScan Oui Non

Tableau 4.14 Routines de copie de chaînes


Routine
StrCopy
StrLCopy
StrECopy
StrMove
StrPCopy
StrPLCopy

Impression
Techniquement parlant, la classe TPrinter n’appartient pas à BaseCLX car il
existe deux versions séparées, une pour la VCL (dans l’unité Printers) et une
pour CLX (dans l’unité QPrinters). L’objet VCL TPrinter encapsule les détails de
l’impression sous Windows. L’objet CLX TPrinter est un dispositif de peinture
qui opère sur une imprimante. Il génère du code postscript et l’envoie à lpr, lp
ou à toute autre commande d’impression. Les deux versions de TPrinter sont
toutefois très similaires.
Pour obtenir une liste des imprimantes installées et disponibles, utilisez la
propriété Printers. Les deux objets imprimante utilisent un TCanvas (similaire au
TCanvas de la fiche), ce qui signifie que tout ce qui peut être dessiné sur une
fiche peut également être imprimé. Pour imprimer une image, appelez d’abord la
méthode BeginDoc, puis les routines des dessins de canevas à imprimer (y
compris du texte en utilisant la méthode TextOut), et envoyez la tâche à
l’imprimante en appelant la méthode EndDoc.
Cet exemple utilise un bouton et un mémo sur une fiche. Quand l’utilisateur
clique sur le bouton, le contenu du mémo s’imprime avec une marge de
200 pixels autour de la page.
Pour exécuter cet exemple, vous devez inclure <Printers.hpp> dans votre fichier
d’unité.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TPrinter *Prntr = Printer();
TRect r = Rect(200,200,Prntr->PageWidth - 200,Prntr->PageHeight- 200);

Utilisation de BaseCLX 4-27


Conversion de mesures

Prntr->BeginDoc();
for( int i = 0; i < Memo1->Lines->Count; i++)
Prntr->Canvas->TextOut(200,200 + (i *
Prntr->Canvas->TextHeight(Memo1->Lines->Strings[i])),
Memo1->Lines->Strings[i]);
Prntr->Canvas->Brush->Color = clBlack;
Prntr->Canvas->FrameRect(r);
Prntr->EndDoc();
}
Pour davantage d’informations sur l’utilisation de l’objet TPrinter, voir dans
l’aide en ligne la rubrique TPrinter.

Conversion de mesures
L’unité ConvUtils déclare une fonction Convert que vous pouvez utiliser pour
convertir des mesures entre plusieurs unités. Vous pouvez effectuer des
conversions entre unités compatibles, par exemple des pouces et des pieds ou
des jours et des semaines. Les unités mesurant les mêmes types d’éléments sont
dites appartenir à la même famille de conversion. Les unités que vous convertissez
doivent appartenir à la même famille de conversion. Pour plus d’informations
sur les conversions, reportez-vous à la section suivante “Exécution des
conversions” et à Convert dans l’aide en ligne.
L’unité StdConvs définit plusieurs familles de conversion et les unités de mesure
de chacune de ces familles. De plus, vous pouvez créer vos propres familles de
conversion et leurs unités associées en utilisant les fonctions
RegisterConversionType et RegisterConversionFamily. Pour savoir comment étendre
les conversions et les unités de conversion, reportez-vous à la section “Ajout de
nouveaux types de mesure” à la page 4-29 et à Convert dans l’aide en ligne.

Exécution des conversions


Vous pouvez utiliser la fonction Convert pour exécuter des conversions simples
ou complexes. Cette fonction emploie une syntaxe simple et une syntaxe moins
simple réservée aux conversions entre types de mesure complexes.

Exécution des conversions simples


Vous pouvez utiliser la fonction Convert pour convertir une mesure d’une unité
vers une autre. La fonction Convert effectue des conversions entre unités
mesurant le même type d’objet (distance, surface, temps, température, etc.).
Pour utiliser Convert, vous devez spécifier l’unité à partir de laquelle la
conversion s’effectue et l’unité de destination. Vous utilisez le type TConvType
pour identifier les unités de mesure.
Par exemple, le code qui suit convertit une température de degrés Fahrenheit en
degrés Kelvin :
TempInKelvin = Convert(StrToFloat(Edit1->Text), tuFahrenheit, tuKelvin);

4-28 Guide du développeur


Conversion de mesures

Exécution des conversions complexes


Vous pouvez aussi utiliser la fonction Convert pour effectuer des conversions
plus complexes entre des rapports de deux types de mesure. C’est le cas lorsque
vous effectuez des conversions de miles par heure en mètres par minute pour
exprimer une vitesse ou de gallons par minute en litres par heure pour exprimer
un débit.
Par exemple, l’appel suivant convertit des miles par gallon en kilomètres
par litre :
double nKPL = Convert(StrToFloat(Edit1.Text), duMiles, vuGallons, duKilometers, vuLiter);
Les unités que vous convertissez doivent appartenir à la même famille de
conversion (elles doivent mesurer la même chose). Si les unités ne sont pas
compatibles, Convert déclenche une exception EConversionError. Vous pouvez
vérifier si deux valeurs TConvType appartiennent à la même famille de
conversion en appelant CompatibleConversionTypes.
L’unité StdConvs définit plusieurs familles de valeurs TConvType. Voir Variables
des familles de conversion dans l’aide en ligne pour avoir la liste des familles
d’unités de mesure prédéfinies et les unités de mesure de chaque famille.

Ajout de nouveaux types de mesure


Si vous voulez effectuer des conversions entre unités de mesure non encore
définies dans l’unité StdConvs, il vous faut créer une nouvelle famille de
conversion pour représenter ces unités de mesure (valeurs TConvType). Quand
deux valeurs TConvType sont recensées dans la même famille de conversion, la
fonction Convert peut effectuer la conversion entre ces mesures en utilisant les
unités représentées par ces valeurs TConvType.
Vous devez d’abord obtenir les valeurs de TConvFamily en recensant une famille
de conversion à l’aide de la fonction RegisterConversionFamily. Une fois que vous
avez obtenu une valeur de TConvFamily (en recensant une nouvelle famille de
conversion ou en utilisant une des variables globales de l’unité StdConvs), vous
pouvez utiliser la fonction RegisterConversionType pour ajouter les nouvelles
unités à la famille de conversion. Les exemples suivants montrent comment
procéder.

Création d’une famille de conversion simple et ajout d’unités


Vous pouvez, par exemple, créer une nouvelle famille de conversion et ajouter
de nouveaux types de mesure lorsque vous effectuez entre de longues périodes
de temps (mois ou siècles) des conversions qui risquent d’être inexactes.
Pour mieux comprendre, la famille cbTime utilise le jour comme unité de base.
L’unité de base est celle qui est utilisée pour effectuer toutes les conversions à
l’intérieur de cette famille. Donc, toutes les conversions doivent être faites en
jours. Une perte de précision peut se produire lors de conversions utilisant
comme unités le mois ou plus (année, décennie, siècle, millénaire), car la

Utilisation de BaseCLX 4-29


Conversion de mesures

conversion entre jours et mois, jours et années, etc. n’est pas exacte. Les mois ont
différentes longueurs, les années ont des facteurs de correction pour les années
bissextiles, les secondes supplémentaires, etc.
Si vous utilisez uniquement des unités de mesure égales ou supérieures au mois,
vous pouvez créer une famille de conversion plus précise en prenant l’année
comme unité de base. Cet exemple crée une nouvelle famille de conversion
nommée cbLongTime.

Déclaration des variables


D’abord, vous devez déclarer des variables pour les identificateurs. Les
identificateurs sont utilisés dans la famille de conversion LongTime et les unités
de mesure qui sont ses membres :
tConvFamily cbLongTime;
TConvType ltMonths;
TConvType ltYears;
TConvType ltDecades;
TConvType ltCenturies;
TConvType ltMillennia;

Recensement de la famille de conversion


Ensuite, recensez la famille de conversion :
cbLongTime := RegisterConversionFamily (‘Longues durées’);
Bien que la procédure UnregisterConversionFamily soit fournie, il n’est pas
nécessaire de dé-recenser les familles de conversion si l’unité qui les définit n’est
pas supprimée à l’exécution. Elles sont automatiquement nettoyées quand
l’application s’arrête.

Recensement des unités de mesure


Ensuite, vous devez recenser les unités de mesure dans la famille de conversion
que vous venez de créer. Utilisez la fonction RegisterConversionType, qui recense
les unités de mesure dans une famille spécifiée. Vous devez définir l’unité de
base, ici l’année, et les autres unités en utilisant un facteur indiquant leur
rapport avec l’unité de base. Le facteur de ltMonths est ainsi 1/12 puisque l’unité
de base de la famille LongTime est l’année. Vous fournissez également la
description des unités dans lesquelles vous effectuez la conversion.
Le code de recensement des unités de mesure est le suivant :
ltMonths = RegisterConversionType(cbLongTime,”Months”,1/12);
ltYears = RegisterConversionType(cbLongTime,”Years”,1);
ltDecades = RegisterConversionType(cbLongTime,”Decades”,10);
ltCenturies = RegisterConversionType(cbLongTime,”Centuries”,100);
ltMillennia = RegisterConversionType(cbLongTime,”Millennia”,1000);

Utilisation des nouvelles unités


Vous pouvez maintenant utiliser les unités que vous venez de recenser afin
d’effectuer des conversions. La fonction Convert globale peut effectuer la

4-30 Guide du développeur


Conversion de mesures

conversion entre tous les types recensés dans la famille de conversion


cbLongTime.
Ainsi, au lieu d’utiliser l’appel Convert suivant,
Convert(StrToFloat(Edit1->Text),tuMonths,tuMillennia);
vous pouvez utiliser celui-ci pour obtenir une meilleure précision :
Convert(StrToFloat(Edit1->Text),ltMonths,ltMillennia);

Utilisation d’une fonction de conversion


Dans les cas où la conversion est plus complexe, vous pouvez utiliser une
syntaxe différente et spécifier une fonction qui effectue la conversion au lieu
d’utiliser un facteur de conversion. Par exemple, vous ne pouvez pas convertir
des températures à l’aide d’un facteur de conversion, puisque les échelles de
température ont des origines différentes.
Cet exemple, qui est converti à partir de l’unité StdConvs, montre comment
recenser un type de conversion en fournissant des fonctions de conversion à
partir et à destination des unités de base.

Déclaration des variables


D’abord, vous devez déclarer des variables pour les identificateurs. Les
identificateurs sont utilisés dans la famille de conversion cbTemperature et les
unités de mesure sont ses membres :
TConvFamily cbTemperature;
TConvType tuCelsius;
TConvType tuKelvin;
TConvType tuFahrenheit;
Remarque Les unités de mesure présentées ici forment un sous-ensemble des unités de
température réellement recensées dans l’unité StdConvs.

Recensement de la famille de conversion


Ensuite, recensez la famille de conversion :
cbTemperature = RegisterConversionFamily (“Temperature”);

Recensement de l’unité de base


Ensuite, définissez et recensez l’unité de base de la famille de conversion, qui est
dans cet exemple le degré Celsius. Remarquez que dans le cas de l’unité de base,
nous pouvons utiliser un facteur de conversion simple, car il n’y a pas de
conversion réelle à effectuer :
tuCelsius = RegisterConversionType(cbTemperature,”Celsius”,1);

Utilisation de BaseCLX 4-31


Conversion de mesures

Ecriture des méthodes de conversion à destination et à partir de l’unité de


base
Vous devez écrire le code qui effectue la conversion pour chaque échelle de
température à destination et à partir des degrés Celsius, car celles-ci ne peuvent
pas se baser sur un facteur simple. Ces fonctions sont traduites à partir de
l’unité StdConvs :
double __fastcall FahrenheitToCelsius(const double AValue)
{
return (((AValue - 32) * 5) / 9);
}
double __fastcall CelsiusToFahrenheit(const double AValue)
{
return (((AValue * 9) / 5) + 32);
}
double __fastcall KelvinToCelsius(const double AValue)
{
return (AValue - 273.15);
}
double __fastcall CelsiusToKelvin(const double AValue)
{
return (AValue + 273.15);
}

Recensement des autres unités


Maintenant que vous disposez des fonctions de conversion, vous pouvez
recenser les autres unités de mesure dans la famille de conversion. Vous incluez
également la description des unités.
Le code de recensement des autres unités de la famille est le suivant :
tuKelvin = RegisterConversionType(cbTemperature, “Kelvin”, KelvinToCelsius,
CelsiusToKelvin);
tuFahrenheit = RegisterConversionType(cbTemperature, “Fahrenheit”, FahrenheitToCelsius,
CelsiusToFahrenheit);

Utilisation des nouvelles unités


Vous pouvez maintenant utiliser les unités que vous venez de recenser pour
effectuer des conversions dans vos applications. La fonction Convert globale peut
effectuer la conversion entre tous les types recensés dans la famille de conversion
cbTemperature. Par exemple, le code suivant permet de convertir en degrés Kelvin
une valeur exprimée en degrés Fahrenheit.
Convert(StrToFloat(Edit1->Text), tuFahrenheit, tuKelvin);

Utilisation d’une classe pour gérer les conversions


Vous pouvez toujours utiliser des fonctions de conversion pour recenser une
unité de conversion. Il existe cependant des cas où il est nécessaire de créer un

4-32 Guide du développeur


Conversion de mesures

nombre inutilement grand de fonctions qui font toutes essentiellement la même


chose.
Si vous pouvez écrire un ensemble de fonctions de conversion qui diffèrent
uniquement par la valeur d’un paramètre ou d’une variable, vous pouvez créer
une classe pour gérer ces conversions. Par exemple, il existe un ensemble de
techniques standard pour les conversions entre les différentes monnaies
européennes depuis l’introduction de l’euro. Bien que les facteurs de conversion
restent constants (contrairement au facteur de conversion entre les dollars et les
euros, par exemple), vous ne pouvez pas utiliser un facteur de conversion simple
pour convertir correctement les monnaies européennes, pour deux raisons :
• La conversion doit arrondir à un nombre de décimales spécifique à la
monnaie.
• L’approche facteur de conversion utilise un facteur inverse à celui spécifié par
les conversions standard en euro.
Tout peut cependant être géré par les fonctions de conversion de la façon
suivante :
double __fastcall FromEuro(const double AValue, const double Factor, TRoundToRange FRound)
{
return(RoundTo(AValue * Factor, FRound));
}
double __fastcall ToEuro(const double AValue, const double Factor)
{
return (AValue / Factor);
}
Le problème est que cette approche nécessite des paramètres supplémentaires
pour la fonction de conversion, ce qui signifie que vous ne pouvez pas recenser
simplement la même fonction pour chaque monnaie européenne. Afin d’éviter
d’écrire deux nouvelles fonctions de conversion pour chacune des monnaies
européennes, vous pouvez utiliser le même couple de fonctions en les rendant
membres d’une classe.

Création de la classe de conversion


La classe doit être un descendant de TConvTypeFactor. TConvTypeFactor définit
deux méthodes, ToCommon et FromCommon, pour convertir à destination et à
partir des unités de base d’une famille de conversion (dans ce cas, à destination
et à partir des euros). Comme les fonctions que vous utilisez directement pour le
recensement d’une unité de conversion, ces méthodes n’ont pas de paramètres
supplémentaires, et vous devez fournir le nombre de décimales de l’arrondi et le
facteur de conversion en tant que membres privés de votre classe de conversion.
Ce point est illustré dans l’exemple EuroConv du répertoire demos\ConvertIt
(voir euroconv.pas) :
class PASCALIMPLEMENTATION TConvTypeEuroFactor : public Convutils::TConvTypeFactor
{
private:
TRoundToRange FRound;
public:

Utilisation de BaseCLX 4-33


Conversion de mesures

__fastcall TConvTypeEuroFactor(const TConvFamily AConvFamily,


const AnsiString ADescription, const double AFactor, const TRoundToRange ARound);
TConvTypeFactor(AConvFamily, ADescription, AFactor);
virtual double ToCommon(const double AValue);
virtual double FromCommon(const double AValue);
}
Le constructeur attribue des valeurs à ces membres privés :
__fastcall TConvTypeEuroFactor::TConvTypeEuroFactor(const TConvFamily AConvFamily,
const AnsiString ADescription, const double AFactor, const TRoundToRange ARound):
TConvTypeFactor(AConvFamily, ADescription, AFactor);
{
FRound = ARound;
}
Les deux fonctions de conversion utilisent tout simplement ces membres privés :
virtual double TConvTypeEuroFactor::ToCommon(const double AValue)
{
return (RoundTo(AValue * Factor, FRound));
}

virtual double TConvTypeEuroFactor::ToCommon(const double AValue)


{
return (AValue / Factor);
}

Déclaration des variables


Maintenant que vous disposez d’une classe de conversion, commencez comme
avec toute autre famille de conversion, en déclarant les identificateurs :
TConvFamily cbEuro;
TConvType euEUR; // Euros
TConvType euBEF; // Francs belges
TConvType euDEM; // Marks allemands
TConvType euGRD; // Drachmes grecs
TConvType euESP; // Pesetas espagnoles
TConvType euFFR; // Francs français
TConvType euIEP; // Livres irlandaises
TConvType euITL; // Lires italiennes
TConvType euLUF; // Francs luxembourgeois
TConvType euNLG; // Florins hollandais
TConvType euATS; // Schillings autrichiens
TConvType euPTE; // Escudos portugais
TConvType euFIM; // Marks finlandais

Recensez la famille de conversion et les autres unités


Vous êtes maintenant prêt à recenser la famille de conversion et les unités
monétaires européennes, en utilisant votre nouvelle classe de conversion.
Recensez cette famille de conversion de la même manière que vous avez recensé
les autres :
cbEuro := RegisterConversionFamily (‘Monnaie européenne’);

4-34 Guide du développeur


Conversion de mesures

Pour recencer chaque type de conversion, créez une instance de la classe de


conversion qui reflète les propriété de facteur et d’arrondi de cette monnaie, et
appelez la méthode RegisterConversionType :
TConvTypeInfo *pInfo = new TConvTypeEuroFactor(cbEuro, “EUEuro”, 1.0, -2);
if (!RegisterConversionType(pInfo, euEUR))
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “BelgianFrancs”, 40.3399, 0);
if (!RegisterConversionType(pInfo, euBEF))
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “GermanMarks”, 1.95583, -2);
if (!RegisterConversionType(pInfo, euDEM))
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “GreekDrachmas”, 340.75, 0);
if (!RegisterConversionType(pInfo, euGRD)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “SpanishPesetas”, 166.386, 0);
if (!RegisterConversionType(pInfo, euESP)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “FrenchFrancs”, 6.55957, -2);
if (!RegisterConversionType(pInfo, euFFR)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “IrishPounds”, 0.787564, -2);
if (!RegisterConversionType(pInfo, euIEP)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “ItalianLire”, 1936.27, 0);
if (!RegisterConversionType(pInfo, euITL)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “LuxembourgFrancs”, 40.3399, -2);
if (!RegisterConversionType(pInfo, euLUF)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “DutchGuilders”, 2.20371, -2);
if (!RegisterConversionType(pInfo, euNLG)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “AutstrianSchillings”, 13.7603, -2);
if (!RegisterConversionType(pInfo, euATS)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “PortugueseEscudos”, 200.482, -2);
if (!RegisterConversionType(pInfo, euPTE)
delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, “FinnishMarks”, 5.94573, 0);
if (!RegisterConversionType(pInfo, euFIM)
delete pInfo;

Utilisation des nouvelles unités


Vous pouvez maintenant utiliser les unités que vous venez de recenser pour
effectuer des conversions dans vos applications. La fonction Convert globale peut
convertir toutes les monnaies européennes que vous avez recensées avec la
nouvelle famille cbEuro. Par exemple, le code suivant convertit en marks
allemands une valeur exprimée en lires italiennes :
Edit2->Text = FloatToStr(Convert(StrToFloat(Edit1->Text), euITL, euDEM));

Utilisation de BaseCLX 4-35


Création d’espaces de dessin

Création d’espaces de dessin


La classe TCanvas encapsule un contexte de périphérique Windows dans la VCL
et un périphérique de dessin (dispositif de dessin Qt) dans CLX. Elle gère tous
les dessins pour les deux fiches, les conteneurs visuels (tels que les volets) et
l’objet imprimante (voir “Impression” page 4-27). En utilisant l’objet canevas,
vous n’avez plus besoin d’allouer crayons, pinceaux ou palettes : ils sont alloués
et libérés automatiquement.
TCanvas propose un grand nombre de routines de dessin primitives pour
dessiner des lignes, des formes, des polygones, du texte, etc. dans tout contrôle
contenant un canevas. Par exemple, voici un gestionnaire d’événement de bouton
qui dessine une ligne du coin supérieur gauche vers le milieu de la fiche, et
affiche du texte brut sur cette fiche :
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Canvas->Pen->Color = clBlue;
Canvas->MoveTo( 10, 10 );
Canvas->LineTo( 100, 100 );
Canvas->Brush->Color = clBtnFace;
Canvas->Font->Name = "Arial";
Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y,"Fin de la ligne" );
}
Dans les applications Windows, l’objet TCanvas vous protège également contre
les erreurs graphiques courantes de Windows, par exemple en restaurant les
contextes de périphériques, crayons, pinceaux, etc. à la valeur qu’ils avaient
avant l’opération de dessin. TCanvas est utilisé partout dans C++Builder lorsqu’il
est nécessaire ou possible de dessiner, et il permet de le faire d’une manière à la
fois simple et fiable.
Pour une liste complète des propriétés et méthodes de TCanvas, voir la référence
en ligne.

4-36 Guide du développeur


Chapitre

Utilisation des composants


Chapitre 5
5
De nombreux composants sont fournis par l’environnement intégré de
développement (EDI) dans la palette des composants. Vous sélectionnez des
composants dans la palette et les déposez dans une fiche ou un module de
données. Vous concevez l’interface utilisateur de l’application en disposant des
composants visuels, boutons ou listes, sur une fiche. Vous pouvez également
placer des composants non visuels, comme les composants d’accès aux données,
dans une fiche ou un module de données.
A première vue, les composants C++Builder ressemblent aux autres classes C++.
Mais, il existe des différences entre les composants de C++Builder et les
hiérarchies de classes standard C++ avec lesquelles travaillent la plupart des
programmeurs C++. Voici certaines de ces différences :
• Tous les composants C++Builder dérivent de TComponent.
• Les composants sont la plupart du temps utilisés tels quels et modifiés par le
biais de leurs propriétés, au lieu de servir de “classes de base” à sous-classer
pour ajouter des fonctionnalités ou modifier celles qui existent. Quand un
composant est dérivé, on ajoute généralement du code spécifique aux
fonctions membres de gestion des événements existants.
• Les composants sont alloués uniquement sur le tas et non sur la pile (c’est-à-
dire, qu’ils doivent être créés avec l’opérateur new).
• Les propriétés des composants contiennent de façon intrinsèque des
informations de type à l’exécution.
• Des composants peuvent être ajoutés à la palette de l’interface utilisateur de
C++Builder et manipulés sur une fiche.
Les composants offrent souvent un meilleur degré d’encapsulation que les classes
C++ standard. Considérez, par exemple, l’utilisation d’une boîte de dialogue
contenant un bouton poussoir. Dans un programme Windows C++ développé en
utilisant les composants de la VCL, lorsqu’un utilisateur clique sur le bouton, le
système génère un message WM_LBUTTONDOWN. Le programme doit

Utilisation des composants 5-1


Initialisation des propriétés d’un composant

intercepter ce message (généralement dans une instruction switch, une


correspondance de message ou une table de réponse) et le diriger vers une
routine qui s’exécutera en réponse au message.
La plupart des messages Windows (VCL) ou événements système (CLX) sont
gérés par les composants de C++Builder. Quand vous voulez répondre à un
message, il vous suffit de fournir un gestionnaire d’événement.
Le chapitre 8, “Conception de l’interface utilisateur des applications”, donne des
détails sur l’utilisation des fiches, comme la création dynamique de fiches
modales, la transmission de paramètres aux fiches et la récupération de données
à partir des fiches.

Initialisation des propriétés d’un composant


Les propriétés publiées peuvent être initialisées à la conception avec l’inspecteur
d’objets ou, dans certains cas, avec des éditeurs de propriétés spécifiques. Pour
spécifier des propriétés à l’exécution, il suffit d’initialiser leur valeur dans le code
source de votre application.
Pour des informations sur les propriétés de chaque composant, consultez l’aide
en ligne.

Initialisation des propriétés à la conception


A la conception, quand vous sélectionnez un composant d’une fiche, l’inspecteur
d’objets affiche ses propriétés publiées et vous permet (si c’est approprié) de les
modifier. Utilisez la touche Tab pour vous déplacer entre la colonne des valeurs
(à droite) et la colonne des propriétés (à gauche). Si le curseur est dans la
colonne des propriétés, vous pouvez vous positionner sur une propriété en
tapant les premières lettres de son nom. Pour les propriétés de type booléen ou
énuméré, vous pouvez choisir une valeur dans une liste déroulante ou parcourir
les valeurs en double-cliquant dans la colonne des valeurs.
Si un symbole plus (+) apparaît à côté du nom de la propriété, vous pouvez
faire apparaître une liste de sous-valeurs pour la propriété en cliquant sur le
symbole plus ou en tapant ‘+’. Si un symbole moins (-) apparaît à côté du nom
de la propriété, vous pouvez faire apparaître une liste de sous-valeurs pour la
propriété en cliquant sur le symbole moins ou en tapant ‘-’.
Par défaut, les propriétés de la catégorie Héritage ne sont pas affichées. Pour
modifier les filtres d’affichage, cliquez avec le bouton droit de la souris dans
l’inspecteur d’objets et choisissez Voir. Pour davantage d’informations, voir
“catégories de propriétés” dans l’aide en ligne.
Si plusieurs composants sont sélectionnés, l’inspecteur d’objets affiche toutes les
propriétés, sauf Name, communes aux composants sélectionnés. Si la valeur d’une
propriété partagée n’est pas la même pour tous les composants sélectionnés,
l’inspecteur d’objets affiche soit la valeur par défaut, soit la valeur de la

5-2 Guide du développeur


Appel de méthodes

propriété pour le premier composant sélectionné. Quand vous modifiez une


propriété partagée, la modification s’applique à tous les composants sélectionnés.
La modification de propriétés liées au code dans l’inspecteur d’objets, comme le
nom d’un gestionnaire d’événement, modifie automatiquement le code source
correspondant. De plus la modification du code source, par exemple le nom
d’une méthode gestionnaire d’événement dans la déclaration de classe d’une
fiche, est immédiatement reflétée dans l’inspecteur d’objets.

Utilisation des éditeurs de propriétés


Certaines propriétés, comme Font utilisent des éditeurs de propriétés spécifiques.
Quand une telle propriété est sélectionnée dans l’inspecteur d’objets, un bouton
points de suspension (...) apparaît à côté de sa valeur. Pour ouvrir l’éditeur de
propriété, double-cliquez dans la colonne des valeurs, cliquez sur le bouton points
de suspension ou tapez Ctrl+Entrée quand la focalisation se trouve sur la propriété
ou sur sa valeur. Pour certains composants, il suffit de double-cliquer sur le
composant dans la fiche pour ouvrir un éditeur de propriété.
Les éditeurs de propriétés permettent de définir des propriétés complexes à
partir d’une seule boîte de dialogue. Elles valident les saisies et permettent
souvent de prévisualiser les effets d’une affectation.

Initialisation des propriétés à l’exécution


Vous pouvez à l’exécution utiliser votre code source pour affecter une valeur à
toute propriété accessible en écriture. Vous pouvez ainsi, définir de manière
dynamique le libellé d’une fiche :
Form1->Caption = MyString;

Appel de méthodes
Une méthode s’appelle comme une procédure ou une fonction ordinaire. Par
exemple, les contrôles visuels disposent de la méthode Repaint qui rafraîchit
l’image du contrôle à l’écran. Vous pouvez appeler la méthode Repaint d’un objet
grille de dessin de la manière suivante :
DrawGrid1->Repaint;
Comme pour les propriétés, c’est la portée d’une méthode qui impose ou pas
l’utilisation de qualificateurs. Par exemple, pour redessiner une fiche depuis le
gestionnaire d’événement de l’un des contrôles enfant de la fiche, il n’est pas
nécessaire de préfixer l’appel de méthode avec le nom de la fiche :
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Repaint;
}

Utilisation des composants 5-3


Utilisation des événements et des gestionnaires d’événements

Utilisation des événements et des gestionnaires d’événements


Dans C++Builder, l’essentiel du code que vous écrivez est exécuté, directement
ou indirectement, en réponse à des événements. Un événement est un type
particulier de propriété qui représente une situation à l’exécution, généralement
une action de l’utilisateur. Le code qui répond directement à un événement, ce
qu’on appelle un gestionnaire d’événement, est une méthode d’un objet. Les
sections suivantes expliquent comment :
• Générer un nouveau gestionnaire d’événement
• Générer le gestionnaire de l’événement par défaut d’un composant
• Rechercher un gestionnaire d’événement
• Associer un événement à un gestionnaire d’événement existant
• Associer des événements de menu à des gestionnaires d’événements
• Supprimer un gestionnaire d’événement

Génération d’un nouveau gestionnaire d’événement


C++Builder peut créer le squelette de gestionnaires d’événements pour les fiches
et les autres composants. Pour créer un gestionnaire d’événement,
1 Sélectionnez un composant.
2 Cliquez dans la page Evénements de l’inspecteur d’objets. La page
Evénements de l’inspecteur d’objets affiche tous les événements définis pour le
composant sélectionné.
3 Sélectionnez l’événement de votre choix puis double-cliquez dans la colonne
valeur ou appuyez sur Ctrl+Entrée.
4 Entrez le code que vous voulez exécuter lorsque l’événement se produit.

Génération du gestionnaire de l’événement par défaut d’un


composant
Certains composants ont un événement par défaut, celui que le composant a le
plus souvent besoin de gérer. Par exemple, l’événement par défaut d’un bouton
est OnClick. Pour créer un gestionnaire de l’événement par défaut, double-cliquez
sur le composant dans le concepteur de fiche, cela génère le squelette de la
procédure de gestion de l’événement et ouvre l’éditeur de code en plaçant le
curseur à l’intérieur du corps de la procédure où il ne vous reste plus qu’à
ajouter du code.
Certains composants n’ont pas d’événement par défaut. D’autres, comme le
biseau (TBevel), n’ont pas du tout d’événement. D’autres composants encore
peuvent réagir différemment si vous double-cliquez dessus dans le concepteur
de fiche. Par exemple, plusieurs composants ouvrent un éditeur de propriété par
défaut ou une autre boîte de dialogue quand on double-clique dessus à la
conception.

5-4 Guide du développeur


Utilisation des événements et des gestionnaires d’événements

Recherche de gestionnaires d’événements


Si vous avez généré le gestionnaire de l’événement par défaut d’un composant
en double-cliquant dessus dans le concepteur de fiche, vous pouvez revenir
dessus en recommençant. Double-cliquez sur le composant ; l’éditeur de code
s’ouvre, le curseur positionné sur le début du corps du gestionnaire
d’événement.
Pour rechercher le gestionnaire d’un événement qui n’est pas l’événement par
défaut,
1 Dans la fiche, sélectionnez le composant dont vous recherchez le gestionnaire
d’événement.
2 Dans l’inspecteur d’objets, cliquez sur l’onglet Evénements.
3 Sélectionnez l’événement dont vous recherchez le gestionnaire et double-
cliquez dans la colonne des valeurs. L’éditeur de code s’ouvre, le curseur
positionné sur le début du corps du gestionnaire d’événement.

Association d’un événement à un gestionnaire d’événement


existant
Vous pouvez réutiliser le code en écrivant des gestionnaires d’événements qui
gèrent plusieurs événements de composants. Par exemple, de nombreuses
applications proposent des turboboutons qui sont l’équivalent de commandes de
la barre des menus. Quand un bouton initie la même action qu’une commande
de menu, vous pouvez écrire un seul gestionnaire d’événement et l’affecter à
l’événement OnClick du bouton et de l’élément de menu.
Pour associer un événement à un gestionnaire d’événement existant,
1 Dans la fiche, sélectionnez le composant dont vous voulez gérer un
événement.
2 Dans la page Evénements de l’inspecteur d’objets, sélectionnez l’événement
auquel vous voulez attacher un gestionnaire.
3 Cliquez sur le bouton flèche vers le bas à côté de l’événement afin d’ouvrir
une liste des gestionnaires d’événements existants. La liste ne propose que les
gestionnaires d’événements écrits pour des événements portant le même nom
dans la même fiche. Sélectionnez dans la liste en cliquant sur un nom de
gestionnaire d’événement.
Cette manière de procéder est un moyen simple de réutiliser des gestionnaires
d’événements. Cependant, les listes d’actions et dans la VCL, les bandes
d’actionsconstituent un outil plus puissant permettant de centraliser l’organisation
du code répondant à des commandes de l’utilisateur. Les listes d’actions peuvent
être utilisées dans les applications multiplates-formes, alors que les bandes
d’actions ne le peuvent pas. Pour davantage d’informations sur les listes
d’actions et les bandes d’actions, voir “Organisation des actions pour les barres
d’outils et les menus” à la page 8-18.

Utilisation des composants 5-5


Utilisation des événements et des gestionnaires d’événements

Utilisation du paramètre Sender


Dans un gestionnaire d’événement, le paramètre Sender indique le composant qui
a reçu l’événement et qui a donc appelé le gestionnaire. Il est parfois pratique de
partager entre plusieurs composants un même gestionnaire d’événement qui doit
se comporter différemment selon le composant qui l’a appelé. Pour ce faire, vous
pouvez utiliser le paramètre Sender.

Affichage et codage d’événements partagés


Si des composants partagent des événements, vous pouvez afficher leurs
événements partagés dans l’inspecteur d’objets. Commencez par sélectionner les
composants en maintenant enfoncée la touche Maj et en cliquant dessus dans le
concepteur de fiche ; puis, choisissez l’onglet Evénements de l’inspecteur d’objets.
Dans la colonne des valeurs de l’inspecteur d’objets, vous pouvez alors créer un
nouveau gestionnaire d’événement ou affecter un gestionnaire d’événement
existant aux événements partagés.

Association d’événements de menu à des gestionnaires


d’événements
Le concepteur de menus, utilisé pour les composants MainMenu et PopupMenu,
vous permet de spécifier simplement des menus déroulants ou surgissants dans
une application. Pour que les menus fonctionnent, il faut néanmoins que chaque
élément de menu réponde à l’événement OnClick qui se produit à chaque fois
que l’utilisateur choisit l’élément de menu ou appuie sur sa touche de raccourci.
Cette section explique comment associer des gestionnaires d’événements aux
éléments de menu. Pour plus d’informations sur le concepteur de menus et les
composants associés, voir “Création et gestion de menus” à la page 8-32.
Pour créer un gestionnaire d’événement pour un élément de menu,
1 Ouvrez le concepteur de menus en double-cliquant sur un composant
MainMenu ou PopupMenu.
2 Sélectionnez un élément de menu dans le concepteur de menus. Dans
l’inspecteur d’objets, vérifiez qu’une valeur est attribuée à la propriété Name
de l’élément.
3 Dans le concepteur de menus, double-cliquez sur l’élément de menu.
C++Builder génère un gestionnaire d’événement dans l’éditeur de code.
4 Entrez le code que vous voulez exécuter lorsque l’utilisateur choisit la
commande de menu.
Pour associer un élément de menu à un gestionnaire d’événement OnClick
existant :
1 Ouvrez le concepteur de menus en double-cliquant sur un composant
MainMenu ou PopupMenu.

5-6 Guide du développeur


Composants multiplates-formes ou non multiplates-formes

2 Sélectionnez un élément de menu dans le concepteur de menus. Dans


l’inspecteur d’objets, vérifiez qu’une valeur est attribuée à la propriété Name
de l’élément.
3 Dans la page Evénements de l’inspecteur d’objets, cliquez sur le bouton flèche
vers le bas à côté de OnClick afin d’ouvrir une liste des gestionnaires
d’événements existants. La liste ne propose que les gestionnaires d’événements
écrits pour des événements OnClick dans la fiche. Sélectionnez un gestionnaire
d’événement en cliquant sur son nom dans la liste.

Suppression de gestionnaires d’événements


Quand vous supprimez un composant d’une fiche en utilisant le concepteur de
fiche, C++Builder retire le composant de la déclaration de type de la fiche. Mais,
il ne supprime pas les méthodes associées car elles peuvent être appelées par
d’autres composants de la fiche. Vous pouvez supprimer manuellement une
méthode (comme un gestionnaire d’événement) mais si vous le faites, vous
devez supprimer la déclaration avancée de la méthode et son implémentation ;
sinon, vous obtiendrez une erreur de compilation lors de la génération du projet.

Composants multiplates-formes ou non multiplates-formes


La palette de composants contient une sélection de composants qui gèrent une
grande variété d’opérations de programmation. Les composants ayant des
fonctions similaires sont regroupés en pages. Par exemple, les composants les
plus utilisés, comme ceux qui créent des menus, des boîtes d’édition ou des
boutons, se trouvent dans la page Standard de la palette des composants. Les
pages apparaissant dans la configuration par défaut dépendent de la version que
vous utilisez.
Le tableau 5.1 énumère les pages définies par défaut et les composants, y
compris ceux qui ne sont pas multiplates-formes, disponibles pour la création
des applications. Vous pouvez utiliser tous les composants CLX dans les
applications Windows et Linux. Vous pouvez utiliser certains composants non
visuels spécifiques à la VCL dans les applications CLX uniquement Windows,
cependant, les applications ne seront pas multiplates-formes sauf si vous isolez
ces parties du code.

Tableau 5.1 Pages de la palette de composants


Nom de page Description Multiplate-forme ?
Standard Contrôles standard, menus Oui
Supplément Contrôles spécialisés Oui sauf ApplicationEvents,
ActionManager, ActionMainMenuBar,
ActionToolBar et CustomizeDlg.
LCDNumber existe uniquement en CLX.

Utilisation des composants 5-7


Composants multiplates-formes ou non multiplates-formes

Tableau 5.1 Pages de la palette de composants (suite)


Nom de page Description Multiplate-forme ?
Win32 (VCL)/ Contrôles Windows courants La plupart des composants de la page
Contrôles Win32 sont proposés dans la page
communs Contrôles Windows courants affichée
(CLX) lors de la création d’une application
CLX.
RichEdit, UpDown, HotKey, Animate,
DataTimePicker, MonthCalendar,
Coolbar, PageScroller et ComboBoxEx
existent uniquement dans la VCL.
TextBrowser, TextViewer, IconViewer et
SpinEdit sont CLX uniquement.
Système Composants et contrôles Non, sauf Timer et PaintBox qui sont
permettant un accès au niveau dans la page Supplément lors de la
du système, y compris les création d’une application CLX.
timers, le multimédia et le
DDE.
AccèsBD Composants pour le travail Oui sauf XMLTransform,
avec les données des bases de XMLTransformProvider et
données qui ne sont pas liées à XMLTransformClient.
un mécanisme d’accès aux
données particulier
ContrôleBD Contrôles visuels orientés Oui sauf pour DBRichEdit,
données DBCtrlGrid et DBChart.
dbExpress Contrôles de bases de données Oui
qui utilisent dbExpress, une
couche multiplate-forme
indépendante des bases de
données qui fournit des
méthodes pour le traitement
SQL dynamique. Elle définit
une interface commune
permettant d’accéder aux
serveurs SQL.
DataSnap Composants utilisés pour créer Non
des applications de bases de
données multiniveaux.
BDE Composants qui fournissent Non
l’accès aux données via le BDE
(Borland Database Engine).
ADO Composants permettant Non
d’accéder aux données par le
biais du modèle ADO.
InterBase Composants fournissant un Oui
accès direct aux bases de
données InterBase.
InterBaseAdmin Composants accèdant aux Oui
appels de l’API InterBase
Services.

5-8 Guide du développeur


Composants multiplates-formes ou non multiplates-formes

Tableau 5.1 Pages de la palette de composants (suite)


Nom de page Description Multiplate-forme ?
InternetExpress Composants qui sont Non
simultanément une application
serveur web et le client d’une
application de base de données
multiniveau.
Internet Composants pour les protocoles Non
de communication Internet et
les applications Web.
WebSnap Composants pour la Non
construction d’applications
serveur Web.
FastNet Contrôles Internet NetMasters. Non
QReport Composants QuickReport Non
utilisés pour créer des états
incorporés.
Dialogues Boîtes de dialogue les plus Oui sauf pour OpenPictureDialog,
utilisées. SavePictureDialog, PrintDialog et
PrinterSetupDialog.
Win 3.1 Ancien style des composants Non
Win 3.1
Exemples Composants personnalisés Non
exemple.
ActiveX Exemples de contrôles ActiveX ; Non
voir la documentation Microsoft
(msdn.microsoft.com).
COM+ Composant pour la gestion des Non
événements COM+.
WebServices Composants pour écrire des Non
applications qui implémentent
ou utilisent des services Web
basés sur SOAP
Serveurs Exemples serveur COM pour Non
Microsoft Excel, Word, etc. (voir
la documentation MSDN
Microsoft)
Indy - Clients Composants Internet Oui
multiplates-formes pour le
client (composants Internet
Winshoes à code source libre).
Indy - Serveurs Composants Internet Oui
multiplates-formes pour le
serveur (composants Internet
Winshoes à code source libre).
Indy - Divers Composants Internet Oui
multiplates-formes
supplémentaires (composants
Internet Winshoes à code
source libre).

Utilisation des composants 5-9


Composants multiplates-formes ou non multiplates-formes

Vous pouvez ajouter, retirer ou réorganiser les composants de la palette et vous


pouvez créer des modèles de composants et des cadres qui regroupent plusieurs
composants.
L’aide en ligne propose des informations sur les composants de la palette.
Cependant, certains des composants des pages ActiveX, Serveurs et Exemples
sont proposés uniquement à titre d’exemple et ne sont pas documentés.
Pour davantage d’informations sur les différences entre la VCL et CLX, voir
chapitre 14, “Développement d’applications multiplates-formes”.

Ajout de composants personnalisés à la palette des composants


Vous pouvez installer des composants personnalisés, conçus par vous ou acquis
séparément, dans la palette de composants et les utiliser dans vos applications.
Pour écrire un composant, voir Partie V, “Création de composants personnalisés”
Pour installer un composant existant, voir “Installation de paquets de
composants” à la page 15-6.

5-10 Guide du développeur


Chapitre

Manipulation des contrôles


Chapitre 6
6
Les contrôles sont des composants visuels avec lesquels l’utilisateur peut
interagir à l’exécution. Ce chapitre décrit un ensemble de fonctionnalités
communes à de nombreux contrôles.

Implémentation du glisser-déplacer dans les contrôles


Le glisser-déplacer est souvent une façon pratique de manipuler des objets.
Les utilisateurs peuvent ainsi faire glisser des contrôles entiers, ou bien extraire
des éléments de contrôles (tels que des boîtes liste ou des vues arborescentes) en
les faisant glisser sur d’autres contrôles.
• Début de l’opération glisser-déplacer
• Acceptation des éléments à déplacer
• Déplacement des éléments
• Fin de l’opération glisser-déplacer
• Personnalisation du glisser-déplacer avec un objet déplacement
• Changement du pointeur de la souris

Début de l’opération glisser-déplacer


Chaque contrôle possède une propriété appelée DragMode qui détermine la façon
dont les opérations glisser sont démarrées. Si la propriété DragMode est à
dmAutomatic, l’opération glisser commence automatiquement quand l’utilisateur
clique sur le bouton de la souris alors que le curseur se trouve au-dessus d’un
contrôle. Le plus souvent, vous donnerez à DragMode la valeur dmManual (la
valeur par défaut) et lancerez l’opération glisser en gérant les événements bouton
de souris enfoncé.
Pour faire glisser un contrôle manuellement, appelez la méthode BeginDrag du
contrôle. BeginDrag requiert un paramètre booléen appelé Immediate et un

Manipulation des contrôles 6-1


Implémentation du glisser-déplacer dans les contrôles

paramètre entier appelé Threshold. Si vous transmettez true pour Immediate,


l’opération glisser commence immédiatement. Si vous transmettez false,
l’opération glisser ne commence pas avant que l’utilisateur ne déplace la souris
du nombre de pixels spécifié par Threshold. Si Threshold vaut -1, la valeur par
défaut est utilisée. L’appel de
BeginDrag (false, -1);
permet au contrôle d’accepter les clics de la souris sans lancer une opération
glisser.
Vous pouvez imposer des conditions pour commencer l’opération glisser, par
exemple vérifier le bouton de souris enfoncé par l’utilisateur, en testant les
paramètres du gestionnaire de l’événement bouton de souris enfoncé, avant
l’appel à BeginDrag. Le code qui suit, par exemple, gère l’événement bouton de
souris enfoncé dans une boîte liste de fichiers en ne lançant l’opération glisser
que si le bouton gauche de la souris a été enfoncé.
void __fastcall TFMForm::FileListBox1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if (Button == mbLeft)// ne glisser que si le bouton gauche est enfoncé
{
TFileListBox *pLB = (TFileListBox *)Sender; // transtypage sur TFileListBox
if (pLB->ItemAtPos(Point(X,Y), true) >= 0) // y a-t-il un élément ici ?
pLB->BeginDrag(false, -1); // si oui, le faire glisser
}
}

Acceptation des éléments à déplacer


Quand l’utilisateur fait glisser quelque chose sur un contrôle, celui-ci reçoit un
événement OnDragOver. Il doit alors indiquer s’il peut accepter l’élément dans le
cas où l’utilisateur le lâcherait à cet emplacement. L’aspect du curseur change
pour indiquer si le contrôle peut accepter l’élément que l’utilisateur fait glisser.
Pour accepter les éléments que l’utilisateur fait glisser sur un contrôle, attachez
un gestionnaire à l’événement OnDragOver du contrôle.
L’événement “glisser-dessus” a un paramètre appelé Accept que le gestionnaire
d’événement peut définir à true pour indiquer qu’il accepte l’élément. Accept
change le type de curseur en curseur d’acceptation ou pas.
L’événement “glisser-dessus” présente d’autres paramètres, dont la source de
l’opération glisser et l’emplacement actuel du curseur de la souris, que le
gestionnaire d’événement peut utiliser pour déterminer s’il doit accepter le
déplacement. Dans l’exemple ci-dessous, une arborescence de répertoires accepte
les objets déplacés seulement s’ils viennent d’une boîte liste de fichiers.
void __fastcall TForm1::TreeView1DragOver(TObject *Sender, TObject *Source,
int X, int Y, TDragState State, bool &Accept)
{
if (Source->InheritsFrom(__classid(TFileListBox)))
Accept = true;
}

6-2 Guide du développeur


Implémentation du glisser-déplacer dans les contrôles

Déplacement des éléments


Si un contrôle indique qu’il peut accepter un élément déplacé, il doit le traiter
s’il est effectivement lâché. Pour gérer les éléments lâchés, attachez un
gestionnaire à l’événement OnDragDrop du contrôle qui accepte l’opération
lâcher. Comme l’événement “glisser-dessus”, l’événement “glisser-déplacer”
indique la source de l’élément déplacé et les coordonnées du curseur de la souris
lorsqu’il est au-dessus du contrôle acceptant l’élément. Le dernier paramètre
vous permet de contrôler le chemin emprunté par un élément au cours de
l’opération glisser ; vous pouvez, par exemple, utiliser ces informations pour
modifier la couleur affichée par les composants si un élément est déposé.
Dans l’exemple suivant, une arborescence de répertoires, qui accepte les éléments
déplacés depuis une boîte liste de fichiers, répond en déplaçant les fichiers vers
le répertoire sur lequel ils sont lâchés :
void __fastcall TForm1::TreeView1DragDrop(TObject *Sender, TObject *Source,
int X, int Y){
if (Source->InheritsFrom(__classid(TFileListBox)))
{
TTreeNode *pNode = TreeView1->GetNodeAt(X,Y); // pNode est la cible du déplacement
AnsiString NewFile = pNode->Text + AnsiString("/") +
ExtractFileName(FileList->FileName); // crée un nom de fichier pour la cible
MoveFileEx(FileListBox1->FileName.c_str(), NewFile.c_str(),
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED); // déplace le fichier
}
}

Fin de l’opération glisser-déplacer


Une opération glisser se termine lorsque l’élément est déplacé avec succès ou
qu’il est relâché au-dessus d’un contrôle qui ne peut pas l’acccepter. A ce stade
un événement “fin-glisser” est envoyé au contrôle à partir duquel le déplacement
a commencé. Pour permettre à un contrôle de répondre quand des éléments en
sont extraits, attachez un gestionnaire à l’événement OnEndDrag du contrôle.
Le paramètre le plus important dans un événement OnEndDrag est appelé Target,
il indique quel contrôle, le cas échéant, accepte l’élément déplacé. Si Target est
null, cela signifie qu’aucun contrôle ne l’accepte. L’événement OnEndDrag
comprend aussi les coordonnées du contrôle de réception.
Dans cet exemple, une boîte liste de fichiers gère un événement “fin-glisser” en
mettant à jour sa liste de fichiers.
void __fastcall TFMForm::FileListBox1EndDrag(TObject *Sender, TObject *Target, int X, int
Y)
if (Target)
FileListBox1->Update();
};

Manipulation des contrôles 6-3


Implémentation du glisser-ancrer dans les contrôles

Personnalisation du glisser-déplacer avec un objet déplacement


Vous pouvez utiliser un descendant de TDragObject pour personnaliser le
comportement glisser-déplacer d’un objet. Les événements “glisser-dessus” et
“glisser-déplacer” standard indiquent la source de l’élément glissé et les
coordonnées du curseur de souris au-dessus du contrôle qui l’accepte. Pour
obtenir des informations supplémentaires sur l’état en cours, dérivez un objet
glissé de TDragObject ou TDragObjectEx (VCL uniquement) et surchargez ses
méthodes virtuelles. L’objet glissé doit être créé dans l’événement OnStartDrag.
Normalement, le paramètre source des événements “glisser-dessus” et “glisser-
déplacer” est le contrôle qui commence l’opération glisser. Si plusieurs sortes de
contrôles peuvent commencer une opération impliquant le même type de
données, la source doit gérer chaque sorte de contrôle. Lorsque vous utilisez un
descendant de TDragObject, toutefois, la source est l’objet glissé lui-même ; si
chaque contrôle crée le même type d’objet glissé dans son événement
OnStartDrag, la cible doit gérer uniquement une sorte d’objet. Les événements
“glisser-dessus” et “glisser-déplacer” peuvent indiquer si la source est un objet
glissé, en opposition au contrôle, en appelant la fonction IsDragObject.
Les descendants de TDragObjectEx (VCL uniquement) sont libérés
automatiquement alors que les descendants de TDragObject ne le sont pas. Si
vous avez des descendants de TDragObject qui ne sont pas explicitement libérés,
vous pouvez les modifier de façon à ce qu’ils dérivent de TDragObjectEx au lieu
de surveiller les perte de mémoire.
Les objets glissés vous permettent de déplacer des éléments entre une fiche
implémentée dans le fichier exécutable principal de l’application et une fiche
implémentée en utilisant une DLL, ou entre des fiches implémentées en utilisant
différentes DLL.

Changement du pointeur de la souris


Il est possible de personnaliser l’aspect du pointeur de la souris lors d’opérations
glisser en définissant la propriété DragCursor du composant source (VCL
seulement).

Implémentation du glisser-ancrer dans les contrôles


Les descendants de TWinControl peuvent faire office de sites ancrés et les
descendants de TControl peuvent faire office de fenêtres enfant ancrées dans les
sites d’ancrage. Par exemple, pour fournir un site d’ancrage sur le bord gauche
de la fenêtre d’une fiche, alignez un volet sur le bord gauche de la fiche et
faites-en un site d’ancrage. Lorsque des contrôles ancrables sont déplacés vers le
volet puis lâchés, ils deviennent des contrôles enfant du volet.
• Transformation d’un contrôle fenêtré en un site d’ancrage
• Transformation d’un contrôle en un enfant ancrable

6-4 Guide du développeur


Implémentation du glisser-ancrer dans les contrôles

• Contrôle de l’ancrage des contrôles enfant


• Contrôle du désancrage des contrôles enfant
• Contrôle de la réponse des contrôles enfant aux opérations glisser-ancrer
Remarque Les propriétés de glisser-ancrer sont disponibles dans la VCL, mais non
dans CLX.

Transformation d’un contrôle fenêtré en un site d’ancrage


Pour transformer un contrôle fenêtré en un site d’ancrage :
1 Mettez la propriété DockSite à true.
2 Si l’objet site ancré ne doit apparaître que lorsqu’il contient un client ancré,
mettez sa propriété AutoSize à true. Lorsque AutoSize est à true, le site ancré a
pour taille 0 jusqu’à ce qu’il accepte d’ancrer un contrôle enfant, après quoi il
est redimensionné de sorte qu’il englobe le contrôle enfant.

Transformation d’un contrôle en un enfant ancrable


Pour transformer un contrôle en un enfant ancrable :
1 Mettez sa propriété DragKind à dkDock. Lorsque DragKind est à dkDock, le fait
de faire glisser le contrôle déplace ce dernier vers un nouveau site d’ancrage
ou désancre le contrôle qui devient une fenêtre flottante. Lorsque DragKind est
à dkDrag (valeur par défaut), le fait de faire glisser le contrôle démarre une
opération glisser-déplacer qui doit être implémentée à l’aide des événements
OnDragOver, OnEndDrag et OnDragDrop.
2 Mettez sa propriété DragMode à dmAutomatic. Lorsque DragMode est à
dmAutomatic, le glissement (glisser-déplacer ou ancrage, suivant DragKind) est
automatiquement lancé lorsque l’utilisateur commence à faire glisser le
contrôle avec la souris. Lorsque DragMode est à dmManual, vous pouvez
commencer une opération glisser-ancrer (ou glisser-déplacer) en appelant la
méthode BeginDrag.
3 Définissez sa propriété FloatingDockSiteClass pour indiquer le descendant
TWinControl qui doit héberger le contrôle lorsqu’il est désancré et devient une
fenêtre flottante. Lorsque le contrôle est libéré et hors d’un site d’ancrage, un
contrôle fenêtré de cette classe est dynamiquement créé et devient le parent de
l’enfant ancrable. Si le contrôle enfant ancrable est un descendant de
TWinControl, il n’est pas nécessaire de créer un site ancré flottant séparé pour
héberger le contrôle, bien qu’il soit possible de spécifier une fiche pour obtenir
une bordure et une barre de titre. Pour ignorer une fenêtre conteneur
dynamique, attribuez à FloatingDockSiteClass la même classe que le contrôle et
elle deviendra une fenêtre flottante sans parent.

Manipulation des contrôles 6-5


Implémentation du glisser-ancrer dans les contrôles

Contrôle de l’ancrage des contrôles enfant


Un site d’ancrage accepte automatiquement les contrôles enfant lorsqu’ils sont
libérés au-dessus de lui. Pour la plupart des contrôles, le premier enfant est
ancré pour remplir la zone client, le deuxième divise cette dernière en différentes
régions, et ainsi de suite. Les contrôles de page ancrent les enfants dans de
nouvelles feuilles à onglets (ou fusionnent dans des feuilles à onglets si l’enfant
est un autre contrôle de page).
Trois événements permettent aux sites d’influer sur l’ancrage des contrôles
enfant :
__property TGetSiteInfoEvent OnGetSiteInfo = {read=FOnGetSiteInfo, write=FOnGetSiteInfo};
typedef void __fastcall (__closure *TGetSiteInfoEvent)(System::TObject* Sender, TControl*
DockClient, Windows::TRect &InfluenceRect, const Windows::TPoint &MousePos, bool &CanDock);
OnGetSiteInfo intervient sur le site d’ancrage lorsque l’utilisateur fait glisser un
enfant ancrable sur le contrôle. Il permet au site d’indiquer s’il accepte en tant
qu’enfant le contrôle spécifié par le paramètre DockClient et, si tel est le cas, où
l’enfant doit se trouver en vue de son ancrage. Lorsque OnGetSiteInfo intervient,
InfluenceRect est initialisée selon les coordonnées d’écran du site d’ancrage et
CanDock est intialisée à true. Une région d’ancrage plus limitée peut être créée en
changeant InfluenceRect et l’enfant peut être rejeté en mettant CanDock à false.
__property TDockOverEvent OnDockOver = {read=FOnDockOver, write=FOnDockOver};
typedef void __fastcall (__closure *TDockOverEvent)(System::TObject* Sender,
TDragDockObject* Source, int X, int Y, TDragState State, bool &Accept);
OnDockOver intervient sur le site d’ancrage lorsque l’utilisateur fait glisser un
enfant ancrable sur le contrôle. Il est analogue à l’événement OnDragOver au
cours d’une opération normale de glisser-déposer. Utilisez-le pour indiquer que
l’enfant peut être relâché en vue de son ancrage, en initialisant la propriété
Accept. Si le contrôle ancrable est rejeté par le gestionnaire d’événement
OnGetSiteInfo (par exemple, si le type de contrôle est incorrect), OnDockOver ne
se produit pas.
__property TDockDropEvent OnDockDrop = {read=FOnDockDrop, write=FOnDockDrop};
typedef void __fastcall (__closure *TDockDropEvent)(System::TObject* Sender,
TDragDockObject* Source, int X, int Y);
OnDockDrop intervient sur le site d’ancrage lorsque l’utilisateur relâche l’enfant
ancrable sur le contrôle. Il est analogue à l’événement OnDragDrop au cours
d’une opération normale de glisser-déposer. Utilisez-le pour faire en sorte
d’accepter le contrôle en tant que contrôle enfant. L’accès au contrôle enfant peut
être obtenu à l’aide de la propriété Control de TDockObject spécifié par le
paramètre Source.

Contrôle du désancrage des contrôles enfant


Un site d’ancrage permet de désancrer automatiquement les contrôles enfant
lorsqu’ils sont déplacés et que leur propriété DragMode vaut dmAutomatic.

6-6 Guide du développeur


Manipulation du texte dans les contrôles

Les sites d’ancrage peuvent réagir lorsque les contrôles enfant sont retirés, et
même empêcher le désancrage, dans un gestionnaire d’événement OnUnDock :
__property TUnDockEvent OnUnDock = {read=FOnUnDock, write=FOnUnDock};
typedef void __fastcall (__closure *TUnDockEvent)(System::TObject* Sender, TControl*
Client, TWinControl* NewTarget, bool &Allow);
Le paramètre Client indique le contrôle enfant qui tente un désancrage et le
paramètre Allow permet au site d’ancrage (Sender) de rejeter le désancrage.
Lorsque vous implémentez un gestionnaire d’événement OnUnDock, il peut être
utile de connaître les autres enfants éventuellement ancrés. Ces informations
figurent dans la propriété en lecture seule DockClients, qui est un tableau indexé
de TControl. Le nombre de clients ancrés est donné par la propriété en lecture
seule DockClientCount.

Contrôle de la réponse des contrôles enfant aux opérations


glisser-ancrer
Les contrôles enfant ancrables disposent de deux événements qui interviennent
au cours des opérations glisser-ancrer. OnStartDock, analogue à l’événement
OnStartDrag d’une opération glisser-déposer, permet au contrôle enfant ancrable
de créer un objet glisser personnalisé. OnEndDock, comme OnEndDrag, se produit
lorsque l’opération glisser s’achève.

Manipulation du texte dans les contrôles


Les sections suivantes expliquent comment utiliser les différentes fonctions des
contrôles éditeur de texte formaté et des contrôles mémo. Certaines de ces
fonctions peuvent aussi être utilisées avec les contrôles éditeur.
• Définition de l’alignement du texte
• Ajout de barres de défilement en mode exécution
• Ajout de l’objet presse-papiers
• Sélection de texte
• Sélection de la totalité d’un texte
• Opérations couper, copier et coller
• Suppression du texte sélectionné
• Désactivation des éléments de menu
• Ajout d’un menu surgissant
• Gestion de l’événement OnPopup

Définition de l’alignement du texte


Dans un composant mémo ou éditeur de texte formaté, le texte peut être aligné
à gauche, à droite ou centré. Pour modifier l’alignement du texte, spécifiez la
propriété Alignment du composant. L’alignement n’est appliqué que si la
propriété WordWrap est à true ; si le retour à la ligne automatique est désactivé, il
n’existe pas de marge sur laquelle s’aligner.

Manipulation des contrôles 6-7


Manipulation du texte dans les contrôles

Par exemple, le code suivant de l’exemple RichEdit définit l’alignement selon le


bouton choisi :
switch((int)RichEdit1->Paragraph->Alignment)
{
case 0: LeftAlign->Down = true; break;
case 1: RightAlign->Down = true; break;
case 2: CenterAlign->Down = true; break;
}

Ajout de barres de défilement en mode exécution


Les composants mémo ou éditeur de texte formaté peuvent contenir des barres
de défilement horizontales ou verticales ou les deux, selon les besoins. Lorsque
le retour à la ligne automatique est actif, le composant n’a besoin que d’une
barre de défilement vertical. Si l’utilisateur désactive le retour à la ligne
automatique, le composant a besoin aussi d’une barre de défilement horizontal,
puisque le texte n’est plus limité par le bord droit de l’éditeur.
Pour ajouter des barres de défilement en mode exécution :
1 Déterminez si le texte peut dépasser la marge droite. Dans la majorité des cas,
cela implique de tester si le retour à la ligne automatique est activé. Vous
devrez aussi vérifier qu’il existe réellement des lignes dépassant la largeur du
contrôle.
2 Définissez la propriété ScrollBars du composant mémo ou éditeur de texte
formaté de façon à inclure ou à exclure les barres de défilement.
L’exemple suivant attache le gestionnaire de l’événement OnClick à l’élément de
menu Caractères | Retour à la ligne.
void __fastcall TEditForm::WordWrap1Click(TObject *Sender)
{
Editor->WordWrap = !(Editor->WordWrap); // inverser le passage à la ligne
if (Editor->WordWrap)
Editor->ScrollBars = ssVertical; // si passage à la ligne besoin seulement
// d’une verticale
else
Editor->ScrollBars = ssBoth; // s’il n’a a pas passage à la ligne, il peut
// avoir besoin des deux
WordWrap1->Checked = Editor->WordWrap; // Vérifier l’élément de menu pour être
// cohérent avec la propriété
}
Les composants mémo ou éditeur de texte formaté ne gèrent pas les barres de
défilement exactement de la même manière. Le composant éditeur de texte
formaté peut dissimuler ses barres de défilement si le texte ne sort pas des
limites du composant. Le composant Mémo affiche toujours les barres de
défilement lorsqu’elles ont été activées.

6-8 Guide du développeur


Manipulation du texte dans les contrôles

Ajout de l’objet Clipboard


La plupart des applications manipulant du texte permettent aux utilisateurs de
déplacer un texte sélectionné d’un document vers un autre, même s’il s’agit
d’une autre application. L’objet Clipboard de C++Builder encapsule un presse-
papiers (comme le Presse-papiers de Windows) et inclut les méthodes permettant
de couper, de copier et de coller du texte (ainsi que d’autres formats, par
exemple les graphiques). L’objet Clipboard est déclaré dans l’unité Clipbrd.
Pour ajouter l’objet Clipboard à une application,
1 Sélectionnez l’unité utilisant le presse-papiers.
2 Dans le fichier .h de la fiche, ajoutez
#include <vcl\Clipbrd.hpp>

Sélection de texte
Pour transférer du texte d’un contrôle de saisie dans le presse-papiers, il faut
d’abord sélectionner ce texte. La possibilité de mettre en surbrillance le texte
sélectionné est intégrée aux composants éditeur. Lorsque l’utilisateur sélectionne
un texte, celui-ci apparaît en surbrillance.
Le tableau suivant dresse la liste des propriétés fréquemment utilisées pour la
manipulation du texte sélectionné.

Tableau 6.1 Propriétés du texte sélectionné


Propriété Description
SelText Contient une chaîne représentant le texte sélectionné dans le composant.
SelLength Contient la longueur d’une chaîne sélectionnée.
SelStart Contient la position de départ d’une chaîne relativement au début du
tampon de texte d’un contrôle de saisie.

Sélection de la totalité d’un texte


La méthode SelectAll sélectionne la totalité du texte présent dans le composant
mémo ou éditeur de texte formaté. C’est particulièrement utile quand le contenu
de l’éditeur dépasse la zone visible du composant. Dans les autres cas, les
utilisateurs peuvent sélectionner du texte à l’aide du clavier ou de la souris.
Pour sélectionner la totalité du contenu d’un contrôle de saisie comme le
composant mémo ou éditeur de texte formaté, appelez la méthode SelectAll du
contrôle RichEdit1.
Par exemple,
void __fastcall TMainForm::SelectAll(TObject *Sender)
{
RichEdit1->SelectAll(); // Sélectionner tout le texte du contrôle RichEdit1
}

Manipulation des contrôles 6-9


Manipulation du texte dans les contrôles

Couper, copier et coller du texte


Les applications utilisant l’unité Clipbrd peuvent couper, copier et coller du texte,
des graphiques et des objets, dans le presse-papiers. Les composants éditeur qui
encapsulent les contrôles de manipulation de texte standard disposent tous de
méthodes intégrées autorisant les interactions avec le presse-papiers. Pour plus
d’informations sur l’utilisation des graphiques et du presse-papiers, voir
“Utilisation du presse-papiers avec les graphiques” à la page 10-23.
Pour couper, copier ou coller du texte avec le presse-papiers, appelez
respectivement les méthodes CutToClipboard, CopyToClipboard et
PasteFromClipboard du composant.
Par exemple, le code suivant attache des gestionnaires aux événements OnClick
des commandes Edition | Couper, Edition | Copier et Edition | Coller :
void __fastcall TMainForm::EditCutClick(TObject* Sender)
{ RichEdit1->CutToClipboard();
}
void __fastcall TMainForm::EditCopyClick(TObject* Sender)
{ RichEdit1->CopyToClipboard();
}
void __fastcall TMainForm::EditPasteClick(TObject* Sender)
{ RichEdit1->PasteFromClipboard();
}

Effacement du texte sélectionné


Vous pouvez effacer le texte sélectionné dans un éditeur sans le placer dans le
presse-papiers. Pour ce faire, appelez la méthode ClearSelection de l’éditeur. Par
exemple, s’il existe un élément Supprimer dans le menu Edition, votre code peut
ressembler à :
void __fastcall TMainForm::EditDeleteClick(TObject *Sender)
{
RichEdit1->ClearSelection();
}

Désactivation des éléments de menu


Il est souvent utile de désactiver des commandes de menus sans pour autant les
retirer du menu. Dans un éditeur de texte, par exemple, si aucun texte n’est
sélectionné, les commandes Couper, Copier et Supprimer du menu Edition sont
inapplicables. L’activation ou la désactivation des éléments de menu peut être
déclenchée lorsque l’utilisateur sélectionne le menu. Pour désactiver un élément
de menu, donnez la valeur false à sa propriété Enabled.
Dans l’exemple suivant, un gestionnaire est attaché à l’événement OnClick d’un
élément Edition appartenant à la barre de menu d’une fiche enfant. Il définit la
propriété Enabled des éléments Couper, Copier et Supprimer dans le menu
Edition, selon que du texte est sélectionné ou non dans le composant RichEdit1.

6-10 Guide du développeur


Manipulation du texte dans les contrôles

La commande Coller sera activée ou désactivée selon que le presse-papiers


contient ou non du texte.
void __fastcall TMainForm::EditEditClick(TObject *Sender)
{
// Active ou désactive l’élément de menu Coller
Paste1->Enabled = Clipboard()->HasFormat(CF_TEXT);
bool HasSelection = (RichEdit1->SelLength > 0); // true si du texte est sélectionné
Cut1->Enabled = HasSelection; // activer l’élément de menu si HasSelection vaut true
Copy1->Enabled = HasSelection;
Delete1->Enabled = HasSelection;
}
La méthode HasFormat du presse-papiers renvoie une valeur booléenne indiquant
si le presse-papiers contient des objets, du texte ou des images d’un format
particulier. En appelant HasFormat avec le paramètre CF_TEXT, vous pouvez
déterminer si le presse-papiers contient du texte, et activer ou désactiver
l’élément Coller selon le cas.
Pour plus d’informations sur l’utilisation du presse-Papiers avec des graphiques,
voir chapitre 10, “Utilisation des graphiques et du multimédia”.

Ajout d’un menu surgissant


Les menus surgissants (ou locaux) sont d’un usage courant et faciles à mettre en
œuvre dans toute sorte d’application. Ils réduisent le nombre d’opérations
nécessaires à la réalisation des tâches : en cliquant avec le bouton droit de la
souris sur l’espace de travail de l’application, l’utilisateur accède à une liste
regroupant les commandes les plus fréquemment utilisées.
Dans une application éditeur de texte, par exemple, vous pouvez ajouter un
menu surgissant qui comporte les commandes d’édition Couper, Copier et
Coller. Ces éléments de menu surgissant peuvent utiliser les mêmes gestionnaires
d’événements que les éléments correspondants du menu Edition. Il n’est pas
nécessaire de créer des raccourcis clavier, ni des touches raccourci pour les
menus surgissants, car les éléments des menus qui leur correspondent en
possèdent généralement.
La propriété PopupMenu d’une fiche indique quel menu surgissant doit s’afficher
lorsque l’utilisateur clique avec le bouton droit de la souris sur la fiche. Les
différents contrôles possèdent aussi leurs propriétés PopupMenu qui ont priorité
sur la propriété de la fiche, permettant de définir des menus personnalisés pour
des contrôles particuliers.
Pour ajouter un menu surgissant à une fiche,
1 Placez un composant menu surgissant sur la fiche.
2 Utilisez le concepteur de menus pour définir les éléments du menu surgissant.
3 Définissez par le nom du composant menu surgissant la propriété PopupMenu
de la fiche ou du contrôle devant faire apparaître le menu.

Manipulation des contrôles 6-11


Ajout de graphiques à des contrôles

4 Attachez les gestionnaires aux événements OnClick des éléments du menu


surgissant.

Gestion de l’événement OnPopup


Il peut être nécessaire de préparer certains éléments d’un menu surgissant avant
d’afficher celui-ci, comme vous devez spécifier les éléments activés ou désactivés
d’un menu normal. Avec un menu normal, l’événement OnClick correspondant à
l’affichage du menu est généralement associé au titre de ce menu, comme décrit
dans la section “Désactivation des éléments de menu” à la page 6-10.
Comme les menus surgissants n’ont pas de barre de menu, vous devez gérer
l’événement dans le composant lui-même. Le composant menu surgissant offre
pour cela un événement particulier appelé OnPopup.
Pour préparer des éléments d’un menu surgissant avant de les afficher,
1 Sélectionnez le composant menu surgissant.
2 Attachez un gestionnaire à son événement OnPopup.
3 Ecrivez dans le gestionnaire d’événement le code activant, désactivant,
dissimulant ou affichant les éléments du menu.
Dans le code suivant, un gestionnaire existant pour l’événement Edit1Click décrit
précédemment dans la section “Désactivation des éléments de menu” à la
page 6-10, est attaché à l’événement OnPopup du composant menu surgissant.
Une ligne de code est ajoutée à Edit1Click pour chaque élément du menu
surgissant.
void __fastcall TMainForm::EditEditClick(TObject *Sender)
{
// activer ou désactiver l’élément de menu Coller
Paste1->Enabled = Clipboard()->HasFormat(CF_TEXT);
Paste2->Enabled = Paste1->Enabled; // Ajouter cette ligne
bool HasSelection = (RichEdit1->SelLength > 0); // true si le texte est sélectionné
Cut1->Enabled = HasSelection; // activer l’élément de menu si HasSelection vaut true
Cut2->Enabled = HasSelection; // ajouter cette ligne
Copy1->Enabled = HasSelection;
Copy2->Enabled = HasSelection; // ajouter cette ligne
Delete1->Enabled = HasSelection;
}

Ajout de graphiques à des contrôles


Plusieurs contrôles permettent de personnaliser la manière dont le contrôle est
restitué. Ce sont les boîtes liste, boîtes à options, menus, en-têtes, contrôles
onglets, vues liste, barres d’état, vues arborescentes et barres d’état. Au lieu
d’utiliser la méthode standard dessinant un contrôle ou chacun de ses éléments,
le propriétaire du contrôle (généralement la fiche) dessine ces éléments en mode
exécution. L’utilisation la plus courante de ces contrôles dessinés par le
propriétaire est de remplacer le texte par des dessins ou d’ajouter des dessins au

6-12 Guide du développeur


Ajout de graphiques à des contrôles

texte des éléments. Pour des informations sur l’utilisation du style “dessiné par
le propriétaire” pour ajouter des images aux menus, voir “Ajout d’images à des
éléments de menu” à la page 8-39.
Les contrôles dessinés par le propriétaire ont un point commun : ils contiennent
tous des listes d’éléments. Généralement, il s’agit de listes de chaînes qui sont
affichées sous forme de texte ou de liste d’objets contenant des chaînes qui sont
affichées sous forme de texte. Il est possible d’associer un objet à chaque élément
de ces listes et d’utiliser l’objet lorsque vous dessinez un élément.
Dans C++Builder, la création d’un contrôle dessiné par le propriétaire se fait
généralement en trois étapes :
1 Spécification du style dessiné par le propriétaire
2 Ajout d’objets graphiques à une liste de chaînes
3 Dessiner des éléments dessinés par le propriétaire

Spécification du style dessiné par le propriétaire


Pour personnaliser le dessin d’un contrôle, vous devez spécifier des gestionnaires
d’événements qui restituent l’image du contrôle quand il doit être dessiné.
Certains contrôles reçoivent automatiquement ces événements. Par exemple, les
vues liste ou arborescentes et les barres d’outils reçoivent les événements aux
diverses étapes du processus de dessin sans avoir à définir la moindre propriété.
Ces événements ont des noms de la forme “OnCustomDraw” ou
“OnAdvancedCustomDraw”.
D’autres contrôles nécessitent l’initialisation d’une propriété avant de recevoir
les événements de dessin personnalisé. Les boîtes liste, les boîtes à options, les
en-têtes et les barres d’état ont une propriété appelée Style. La propriété Style
détermine si le contrôle utilise le dessin par défaut (appelé style “standard”) ou
bien le dessin effectué par le propriétaire. Les grilles utilisent une propriété
appelée DefaultDrawing qui permet d’activer ou de désactiver le dessin par
défaut. Les vues listes et les contrôles onglets ont une propriété appelée
OwnerDraw qui active ou désactive le dessin par défaut.
Pour les boîtes liste et les boîtes à options, il y a plusieurs styles dessinés par
le propriétaire, appelés fixed et variable, comme décrit dans le tableau suivant.
Les autres contrôles sont toujours “fixes” : bien que la taille de l’élément
contenant du texte soit variable, la taille de chaque élément est fixée avant le
dessin du contrôle.

Tableau 6.2 Comparaison entre les styles “fixed” et “variable”


Styles dessinés
par le propriétaire Signification Exemples
Fixed Chaque élément est de la même hauteur, lbOwnerDrawFixed,
déterminée par la propriété ItemHeight. csOwnerDrawFixed
Variable Chaque élément peut avoir une hauteur lbOwnerDrawVariable,
différente qui dépend des données au csOwnerDrawVariable
moment de l’exécution.

Manipulation des contrôles 6-13


Ajout de graphiques à des contrôles

Ajout d’objets graphiques à une liste de chaînes


Toute liste de chaînes est capable de contenir une liste d’objets en plus de sa
liste de chaînes.
Dans une application de gestion de fichiers, par exemple, vous devez ajouter un
bitmap indiquant le type du lecteur à la lettre le désignant. Pour cela, vous
devez ajouter les images bitmap à l’application, puis les copier à l’endroit
approprié dans la liste de chaînes, comme le décrivent les sections suivantes.

Ajout d’images à une application


Un contrôle image est un contrôle non visuel qui contient une image graphique
(un bitmap, par exemple). Les contrôles image servent à afficher des images
graphiques sur une fiche, mais vous pouvez aussi les utiliser pour stocker des
images cachées que vous utiliserez dans votre application. Par exemple, il est
possible de stocker des images bitmap pour les contrôles dessinés par le
propriétaire dans des contrôles image cachés, comme décrit ci-dessous :
1 Ajoutez des contrôles image à la fiche principale.
2 Définissez leurs propriétés Name.
3 Donnez la valeur false à la propriété Visible de chaque contrôle image.
4 Définissez la propriété Picture de chaque contrôle image par le bitmap
souhaité en utilisant l’éditeur d’image depuis l’inspecteur d’objets.
Les contrôles image seront invisibles lorsque vous exécuterez l’application.

Ajout d’images à une liste de chaînes


Une fois que vous avez des images graphiques dans une application, vous
pouvez les associer aux chaînes de la liste. Vous pouvez soit ajouter les objets
en même temps que les chaînes, soit les associer à des chaînes qui ont déjà été
ajoutées. Si vous disposez de toutes les données dont vous avez besoin, vous
ajouterez sans doute les chaînes et les objets en même temps.
L’exemple suivant montre comment ajouter des images à une liste de chaînes.
Ce code est extrait d’une application de gestion de fichiers dans laquelle chaque
lecteur correct est représenté par une lettre et est associé à un bitmap indiquant
le type du lecteur. L’événement OnCreate se présente comme suit :
void __fastcall TFMForm::FormCreate(TObject *Sender)
{
int AddedIndex;
char DriveName[4] = "A:\\";
for (char Drive = ’A’; Drive <= ’Z’; Drive++) // Essayer tous les lecteurs
{
DriveName[0] = Drive;
switch (GetDriveType(DriveName))
{
case DRIVE_REMOVABLE:// Ajouter un élément à la liste
DriveName[1] = ’\0’; // convertir la lettre du lecteur en chaîne
AddedIndex = DriveList->Items->AddObject(DriveName,

6-14 Guide du développeur


Ajout de graphiques à des contrôles

Floppy->Picture->Graphic);
DriveName[1] = ’:’ // Remplacer le deux points
break;
case DRIVE_FIXED:// Ajouter un élément à la liste
DriveName[1] = ’\0’; // convertir la lettre du lecteur en chaîne
AddedIndex = DriveList->Items->AddObject(DriveName,
Fixed->Picture->Graphic);
DriveName[1] = ’:’ // Remplacer le deux points
break;
case DRIVE_REMOTE:// Ajouter un élément à la liste
DriveName[1] = ’\0’; // convertir la lettre du lecteur en chaîne
AddedIndex = DriveList->Items->AddObject(DriveName,
Network->Picture->Graphic);
DriveName[1] = ’:’ // Remplacer le deux points
break;
}
if ((int)(Drive - ’A’) == getdisk()) // lecteur en cours?
DriveList->ItemIndex = AddedIndex; // en faire l’élément en cours de la liste
}
}

Dessiner des éléments dessinés par le propriétaire


Lorsque vous avez spécifié qu’un contrôle est dessiné par le propriétaire
(en initialisant une propriété ou en définissant un gestionnaire d’événement),
le contrôle n’est plus dessiné à l’écran. Au lieu de cela, le système d’exploitation
génère un événement pour chaque élément visible du contrôle. C’est votre
application qui gère ces événements et dessine les éléments.
Pour dessiner les éléments d’un contrôle dessiné par le propriétaire, suivez les
étapes indiquées ci-après. Ces étapes se répètent pour chaque élément visible
du contrôle, mais vous utiliserez le même gestionnaire d’événement pour tous.
1 Le cas échéant, dimensionnez l’élément.
Si les éléments sont tous de même taille (par exemple, avec un style de boîte liste
lsOwnerDrawFixed), cette opération n’est pas nécessaire.
2 Dessinez l’élément.

Dimensionnement des éléments dessinés par le propriétaire


Avant de laisser votre application dessiner chaque élément d’un contrôle de taille
variable lorsqu’il est dessiné par le propriétaire, le système d’exploitation génère
un événement de type measure-item. Cet événement indique à l’application
l’endroit où l’élément apparaîtra sur le contrôle.
C++Builder détermine la taille probable de l’élément (généralement juste assez
grand pour afficher le texte de l’élément dans la police de caractères active).
Votre application peut gérer l’événement et modifier la zone rectangle choisie.
Par exemple, si vous comptez remplacer le texte de l’élément par une image
bitmap, vous modifierez le rectangle pour qu’il soit de la taille du bitmap.

Manipulation des contrôles 6-15


Ajout de graphiques à des contrôles

Si vous voulez avoir à la fois l’image et le texte, vous ajusterez la taille du


rectangle pour qu’il puisse contenir les deux.
Pour changer la taille d’un élément dessiné par le propriétaire, attachez un
gestionnaire à l’événement measure-item dans le contrôle dessiné par le
propriétaire. Le nom de l’événement peut varier en fonction du contrôle. Les
boîtes liste et les boîtes à options utilisent OnMeasureItem. Les grilles n’ont pas ce
type d’événement.
L’événement définissant la taille utilise deux paramètres importants : l’indice et
la taille de l’élément. Cette taille est variable : l’application peut l’augmenter ou
la diminuer. La position des éléments suivants dépend de la taille des éléments
précédents.
Par exemple, dans une boîte liste variable dessinée par le propriétaire, si
l’application définit la hauteur du premier élément à cinq pixels, le second
élément commence au sixième pixel depuis le haut, et ainsi de suite. Dans les
boîtes liste et dans les boîtes à options, le seul aspect des éléments que
l’application puisse changer est la hauteur. La largeur de l’élément est toujours
celle du contrôle.
Les grilles dessinées par le propriétaire ne peuvent pas modifier la taille des
cellules au fur et à mesure qu’elles sont dessinées. En effet, la taille des lignes et
des colonnes est définie avant le dessin par les propriétés ColWidths et
RowHeights.
Le code suivant, attaché à l’événement OnMeasureItem du composant boîte liste
dessinée par le propriétaire, augmente la hauteur de chaque élément de liste
pour permettre de placer l’image bitmap associée.
void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control, int Index,
int &Height) // Remarquez que Height est transmis par adresse
{
int BitmapHeight = ((TBitmap *)ListBox1->Items->Objects[Index])->Height + 2;
// S’assurer que l’élément de la liste est assez haut pour le bitmap (plus 2)
if (BitmapHeight > Height)
Height = BitmapHeight;
}
Remarque Vous devez transtyper les éléments à partir de la propriété Objects dans la liste
de chaînes. Objects est une propriété de type TObject, aussi peut-elle contenir
n’importe quel type d’objet. Lorsque vous extrayez un objet d’un tableau, vous
devez le transtyper afin qu’il reprenne le type des éléments.

Dessin des éléments par le propriétaire


Lorsqu’une application doit dessiner ou redessiner un contrôle dessiné par le
propriétaire, le système d’exploitation génère un événement de type draw-item
pour chaque élément visible du contrôle. Selon le contrôle, l’élément peut
également recevoir les événements de dessin pour l’élément pris comme un tout
ou comme sous-éléments.

6-16 Guide du développeur


Ajout de graphiques à des contrôles

Pour dessiner chaque élément d’un contrôle dessiné par le propriétaire, attachez
un gestionnaire à l’événement draw-item de ce contrôle.
Les noms des événements relatifs aux objets dessinés par le propriétaire
commencent généralement par :
• OnDraw, comme OnDrawItem ou OnDrawCell
• OnCustomDraw, comme OnCustomDrawItem
• OnAdvancedCustomDraw, comme OnAdvancedCustomDrawItem
L’événement draw-item contient des paramètres identifiant l’élément à dessiner, le
rectangle dans lequel il s’inscrit et, habituellement, des informations sur son état
(actif, par exemple). L’application gère chaque événement en plaçant l’élément
approprié dans le rectangle transmis.
Par exemple, le code suivant montre comment dessiner des éléments dans une
boîte liste ayant un bitmap associé à chaque chaîne. Il attache ce gestionnaire à
l’événement OnDrawItem :
void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control, int Index,
TRect &Rect, TOwnerDrawState State)

TBitmap *Bitmap = (TBitmap *)ListBox1->Items->Objects[Index];


ListBox1->Canvas->Draw(R.Left, R.Top + 2, Bitmap); // dessiner le bitmap
ListBox1->Canvas->TextOut(R.Left + Bitmap->Width + 2, R.Top + 2,
ListBox1->Items->Strings[Index]); // et écrire le texte à sa droite
}

Manipulation des contrôles 6-17


6-18 Guide du développeur
Chapitre

Création d’applications,
Chapitre 7
7
de composants et de bibliothèques
Ce chapitre donne un aperçu de la manière d’utiliser C++Builder pour créer des
applications, des bibliothèques et des composants.

Création d’applications
L’utilisation principale de C++Builder est la conception et la génération des types
d’applications suivants :
• Les applications d’interface utilisateur graphique
• Les applications console
• Les applications service (pour les applications Windows seulement)
• Paquets et DLL
Les applications d’interface utilisateur graphique (GUI) ont en général une
interface qui facilite leur utilisation. Les applications console s’exécutent dans
une fenêtre console. Les applications service s’exécutent en tant que services
Windows. Ces applications sont compilées en tant qu’exécutables, avec du code
de démarrage.
Vous pouvez créer d’autres types de projets, comme les paquets et les DLL,
bibliothèques de liaison dynamique. Ces applications produisent du code
exécutable sans code de démarrage. Reportez-vous à “Création de paquets et de
DLL” à la page 7-10.

Applications d’interface utilisateur graphique


Une application d’interface utilisateur graphique, GUI, est une application conçue
en utilisant des fonctionnalités graphiques, fenêtres, menus, boîtes de dialogue,
et des fonctionnalités qui rendent cette application facile à utiliser. Quand vous

Création d’applications, de composants et de bibliothèques 7-1


Création d’applications

compilez une application GUI, un fichier exécutable contenant du code de


démarrage est créé. Généralement, l’exécutable fournit les fonctions de base de
votre programme et les programmes simples sont souvent composés uniquement
d’un fichier exécutable. Vous pouvez aussi étendre une application en appelant
des DLL, des paquets ou d’autres bibliothèques complétant un exécutable.
C++Builder offre deux modèles d’interface utilisateur d’application :
• L’interface de document unique (abrégé en anglais par SDI)
• L’interface de document multiple (abrégé en anglais par MDI)
Outre le modèle d’implémentation de votre application, le comportement de
votre projet à la conception, comme celui de l’application à l’exécution, peut être
manipulé par des options de projet de l’EDI.

Modèles d’interfaces utilisateur


Toute fiche peut être implémentée comme une fiche d’interface de document
multiple (MDI) ou comme une fiche d’interface de document unique (SDI). Dans
une application MDI, plusieurs documents ou fenêtres enfant peuvent être
ouverts dans une seule fenêtre parent. Cela est courant dans les applications
comme les tableurs ou les traitements de texte. Par contre, une application SDI
ne contient normalement qu’une seule vue de document. Pour faire de votre
fiche une application SDI, affectez la valeur fsNormal à la propriété FormStyle de
votre objet Form.
Pour davantage d’informations sur le développement de l’interface utilisateur
d’une application, voir chapitre 8, “Conception de l’interface utilisateur des
applications”.

Applications SDI
Pour créer une nouvelle application SDI :
1 Sélectionnez Fichier|Nouveau|Autre pour afficher la boîte de dialogue
Nouveaux éléments.
2 Cliquez sur l’onglet Projets et double-cliquez sur Application SDI.
3 Cliquez sur OK.
Par défaut, la propriété FormStyle de l’objet Form a la valeur fsNormal,
C++Builder suppose que toute nouvelle application est une application SDI.

Applications MDI
Pour créer une nouvelle application MDI :
1 Sélectionnez Fichier|Nouveau|Autre pour afficher la boîte de dialogue
Nouveaux éléments.
2 Cliquez sur l’onglet Projets et double-cliquez sur Application MDI.
3 Cliquez sur OK.
Les applications MDI nécessitent plus de réflexion et sont plus complexes à
concevoir que les applications SDI. Les applications MDI contiennent des fenêtres

7-2 Guide du développeur


Création d’applications

enfant qui se trouvent dans la fenêtre client ; la fiche principale contient des
fiches enfant. Affectez la propriété FormStyle de l’objet TForm pour spécifier si la
fiche est un enfant (fsMDIForm) ou si c’est la fiche principale (fsMDIChild). Pour
éviter d’avoir à redéfinir à plusieurs reprises les propriétés des fenêtres enfant,
vous avez intérêt à définir une classe de base pour les fiches enfant et à dériver
chaque fiche enfant de cette classe.
Les applications MDI proposent souvent des options du menu principal comme
Cascade et Mosaïque pour afficher plusieurs fenêtres de diverses manières.
Quand une fenêtre enfant est réduite, son icône est placée dans la fenêtre parent
MDI.
Pour résumer, pour créer les fenêtres d’une application MDI :
1 Créez la fenêtre principale, ou fenêtre parent MDI. Initialisez sa propriété
FormStyle à fsMDIForm.
2 Créez un menu pour la fenêtre principale proposant les options Fichier|
Ouvrir, Fichier|Enregistrer et un menu Fenêtre proposant les options Cascade,
Mosaïque et Réorganiser.
3 Créez les fiches enfant MDI et initialisez leur propriété FormStyle à fsMDIChild.

Définition des options de l’EDI, du projet et de la compilation


Choisissez Projet|Options pour spécifier les diverses options de votre projet.
Pour plus d’informations, voir l’aide en ligne.

Définition des options de projet par défaut


Pour modifier les options de projet par défaut qui s’appliquent à tout nouveau
projet, définissez les options de la boîte de dialogue Options de projet, puis
cochez la case Défaut en bas à droite de la fenêtre. Tous les nouveaux projets
utiliseront ensuite les options en cours comme options par défaut.

Modèles de programmation
Les modèles de programmation sont des structures communément appelées
squelettes que vous pouvez ajouter au code source puis remplir. Certains modèles
de code standard, comme les déclarations de tableaux, de classes ou de fonction,
ainsi que de nombreuses instructions, sont livrés avec C++Builder.
Vous pouvez aussi écrire vos propres modèles de code pour les structures que
vous utilisez souvent. Par exemple, si vous voulez utiliser une boucle for dans
votre code, insérez le modèle suivant :
for (; ;)
{

}
Pour insérer un modèle de code dans l’éditeur de code, appuyez sur Ctrl-j et
sélectionnez le modèle que vous voulez utiliser. Vous pouvez ajouter vos propres
modèles à cette collection.

Création d’applications, de composants et de bibliothèques 7-3


Création d’applications

Pour ajouter un modèle :


1 Choisissez Outils|Options de l’éditeur.
2 Choisissez l’onglet Audit de code.
3 Dans la section Modèles, choisissez Ajouter.
4 Saisissez le nom du modèle après Raccourci et entrez une description brève
du nouveau modèle, puis cliquez sur OK.
5 Ajoutez le modèle de code dans la boîte de saisie Code.
6 Cliquez sur OK.

Applications console
Les applications console sont des programmes 32 bits exécutés sans interface
graphique, généralement dans une fenêtre console. Habituellement, ces
applications ne nécessitent pas une saisie utilisateur importante et accomplissent
un jeu limité de fonctions.
Pour créer une nouvelle application console :
1 Choisissez Fichier|Nouveau|Autre puis double-cliquez sur Expert Console
dans la boîte de dialogue Nouveaux éléments.
2 Dans la boîte de dialogue Expert console, cochez l’option Application console,
choisissez le type de source (C ou C++) de la fiche principale du projet ou
spécifiez un fichier préexistant contenant une fonction main ou winmain, puis
choisissez le bouton OK.
C++Builder crée alors un fichier projet pour le type de fichier source spécifié et
affiche l’éditeur de code.

Utilisation de la VCL et de la CLX dans les applications console


Remarque A la création d’une nouvelle application console, l’EDI ne crée pas une nouvelle
fiche. Seul l’éditeur de code apparaît.
Vous pouvez néanmoins utiliser des objets VCL et CLX dans les applications
console. Pour ce faire, vous devez spécifier dans l’expert Console que vous
utiliserez la VCL ou la CLX (cochez l’option Utiliser VCL ou Utiliser CLX). Si
vous ne le faites pas, vous ne pourrez pas utiliser ultérieurement les classes de la
VCL ou de la CLX dans cette application. Sinon, des erreurs du lieur se
produiront.
Les applications console doivent gérer toutes les exceptions afin d’empêcher des
fenêtres d’afficher une boîte de dialogue lors de l’exécution.

Applications service
Les applications service reçoivent les requêtes des applications client, traitent ces
requêtes et renvoient les informations aux applications client. Habituellement,
elles s’exécutent en arrière-plan, sans nécessiter de saisie utilisateur importante.

7-4 Guide du développeur


Création d’applications

Un serveur Web, FTP ou de messagerie électronique est un exemple


d’application service.
Pour créer une application qui implémente un service Win32 :
1 Choisissez Fichier|Nouveau|Autre et double-cliquez sur Application Service
dans la boîte de dialogue Nouveaux éléments. Cela ajoute à votre projet une
variable globale appelée Application de type TServiceApplication.
2 La fenêtre Service qui apparaît correspond à un service (TService).
Implémentez le service en initialisant ses propriétés et ses gestionnaires
d’événements dans l’inspecteur d’objets.
3 Vous pouvez ajouter des services supplémentaires en choisissant Fichier|
Nouveau|Autre et en double-cliquant sur Service dans la boîte de dialogue
Nouveaux éléments. N’ajoutez pas de services à une application qui n’est pas
une application service. En effet, même si un objet TService est ajouté,
l’application ne génère pas les événements nécessaires, ni ne fait les appels
Windows appropriés au service.
4 Une fois que votre application service est construite, vous pouvez installer ses
services avec le SCM (Service Control Manager). Les autres applications
peuvent alors lancer vos services en envoyant des requêtes au SCM.
Pour installer les services de votre application, exécutez-la à l’aide de l’option /
INSTALL. L’application installe ses services puis quitte, en affichant un message
de confirmation si les services sont correctement installés. Vous pouvez
supprimer l’affichage du message de confirmation en exécutant l’application
service à l’aide de l’option /SILENT.
Pour désinstaller les services de votre application, exécutez-la depuis la ligne de
commande à l’aide de l’option /UNINSTALL. (Vous pouvez aussi utiliser
l’option /SILENT pour supprimer le message de confirmation lors de la
désinstallation).
Exemple Le service suivant contient un TServerSocket dont le port est initialisé à 80. C’est
le port par défaut des navigateurs Web pour envoyer des requêtes à des
serveurs Web et celui utilisé par les serveurs Web pour répondre aux
navigateurs Web. Cet exemple spécifique produit, dans le répertoire C:\Temp,
un document texte appelé WebLogxxx.log (où xxx correspond au ThreadID). Il
ne doit y avoir qu’un seul serveur surveillant un port donné, donc si vous
utilisez déjà un serveur Web, vous devez vous assurer qu’il n’est pas à l’écoute
(le service doit être arrêté).
Pour voir les résultats : ouvrez un navigateur Web sur la machine locale, et pour
l’adresse, entrez “localhost” (sans les guillemets). Eventuellement, le navigateur
va faire une erreur de dépassement de délai mais vous devez obtenir un fichier
appelé Weblogxxx.log dans le répertoire C:\Temp.
1 Pour créer l’exemple, choisissez Fichier|Nouveau|Autre et sélectionnez
Application Service dans la boîte de dialogue Nouveaux éléments. La fenêtre
Service1 apparaît.
2 Ajoutez un composant ServerSocket de la page Internet de la palette de
composants à la fenêtre service (Service1).

Création d’applications, de composants et de bibliothèques 7-5


Création d’applications

3 Ajoutez une donnée membre privée de type TMemoryStream à la classe


TService1. L’en-tête de l’unité doit ressembler à :
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Classes.hpp>
#include <SvcMgr.hpp>
#include <ScktComp.hpp>
//---------------------------------------------------------------------------
class TService1 : public TService
{
__published:// IDE-managed Components
TServerSocket *ServerSocket1;
private:// Déclarations utilisateur
TMemoryStream *Stream; // ajoutez cette ligne
public:// Déclarations utilisateur
__fastcall TService1(TComponent* Owner);
PServiceController __fastcall GetServiceController(void);

friend void __stdcall ServiceController(unsigned CtrlCode);


};
//---------------------------------------------------------------------------
extern PACKAGE TService1 *Service1;
//---------------------------------------------------------------------------
#endif
4 Sélectionnez ServerSocket1, le composant ajouté à l’étape 1. Dans l’inspecteur
d’objets, double-cliquez sur l’événement OnClientRead et ajoutez le gestionnaire
d’événement suivant :
void __fastcall TService1::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
char *Buffer = NULL;
int len = Socket->ReceiveLength();
while (len > 0)
{
try
{
Buffer = (char *)malloc(len);
Socket->ReceiveBuf((void *)Buffer, len);
Stream->Write(Buffer, len);
}
__finally
{
free(Buffer);
}
Stream->Seek(0, soFromBeginning);
AnsiString LogFile = "C:\\Temp\\WebLog";
LogFile = LogFile + IntToStr(ServiceThread->ThreadID) + ".log";
Stream->SaveToFile(LogFile);
}
}

7-6 Guide du développeur


Création d’applications

5 Sélectionnez enfin Service1 en cliquant sur la zone client de la fenêtre (mais


pas sur le composant ServiceSocket). Dans l’inspecteur d’objets, double-cliquez
sur l’événement OnExecute et ajoutez le gestionnaire d’événement suivant :
void __fastcall TService1::Service1Execute(TService *Sender)
{
Stream = new TMemoryStream();
try
{
ServerSocket1->Port = 80; // port WWW
ServerSocket1->Active = true;
while (!Terminated)
ServiceThread->ProcessRequests(true);
ServerSocket1->Active = false;
}
__finally
{
delete Stream;
}
}
Quand vous écrivez votre application service, vous devez tenir compte des
éléments suivants :
• Threads de service
• Propriétés de nom d’un service
• Débogage d’applications service
Remarque Les applications service fonctionnement uniquement sous Windows.

Threads de service
Chaque service dispose de son propre thread (TServiceThread), donc si votre
application service implémente plusieurs services, vous devez vous assurer que
l’implémentation de vos services est compatible avec l’utilisation de threads. La
classe TServiceThread est ainsi conçue de façon à implémenter le service dans le
gestionnaire d’événement OnExecutede TService. Le thread du service dispose de
sa propre méthode Execute qui contient une boucle appelant les gestionnaires
OnStart et OnExecute du service avant de traiter de nouvelles requêtes.
Comme le traitement des requêtes de service peut prendre longtemps et que
l’application service peut recevoir simultanément plusieurs requêtes d’un ou de
plusieurs clients, il est plus efficace de lancer un nouveau thread (dérivé de
TThread et non de TServiceThread) pour chaque requête et de déplacer
l’implémentation du service dans la méthode Execute du nouveau thread. Cela
permet à la boucle Execute du thread du service de traiter continuellement de
nouvelles requêtes sans avoir à attendre la fin du gestionnaire OnExecute du
service. L’exemple suivant en est une illustration.
Exemple Ce service sonne tous les 500 millisecondes depuis le thread standard. Il gère la
pause, la reprise et l’arrêt du thread quand on indique au service de se
suspendre, de reprendre ou de s’arrêter.
1 Choisissez Fichier|Nouveau|Autre et double-cliquez sur Application Service
dans la boîte de dialogue Nouveaux éléments. La fenêtre Service1 apparaît.

Création d’applications, de composants et de bibliothèques 7-7


Création d’applications

2 Dans le fichier en-tête de l’unité, déclarez un nouveau descendant de TThread


nommé TSparkyThread. C’est le thread qui réalise le travail pour le service.
Il doit être déclaré comme suit :
class TSparkyThread : public TThread
{
private:
protected:
void __fastcall Execute();
public:
__fastcall TSparkyThread(bool CreateSuspended);
};
3 Dans le fichier .cpp de l’unité, créez une variable globale pour une instance de
TSparkyThread :
TSparkyThread *SparkyThread;
4 Ajoutez le code suivant au fichier .cpp pour le constructeur de
TSparkyThread :
__fastcall TSparkyThread::TSparkyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
5 Ajoutez le code suivant au fichier .cpp pour la méthode Execute de
TSparkyThread (la fonction thread) :
void __fastcall TSparkyThread::Execute()
{
while (!Terminated)
{
Beep();
Sleep(500);
}
}
6 Sélectionnez la fenêtre service (Service1) et double-cliquez sur l’événement
OnStart dans l’inspecteur d’objets. Ajoutez le gestionnaire d’événement
OnStart suivant :
void __fastcall TService1::Service1Start(TService *Sender, bool &Started)
{
SparkyThread = new TSparkyThread(false);
Started = true;
}
7 Double-cliquez sur l’événement OnContinue dans l’inspecteur d’objets. Ajoutez
le gestionnaire d’événement OnContinue suivant :
void __fastcall TService1::Service1Continue(TService *Sender, bool &Continued)
{
SparkyThread->Resume();
Continued = true;
}

7-8 Guide du développeur


Création d’applications

8 Double-cliquez sur l’événement OnPause dans l’inspecteur d’objets. Ajoutez le


gestionnaire d’événement OnPause suivant :
void __fastcall TService1::Service1Pause(TService *Sender, bool &Paused)
{
SparkyThread->Suspend();
Paused = true;
}
9 Enfin, double-cliquez sur l’événement OnStop dans l’inspecteur d’objets.
Ajoutez le gestionnaire d’événements OnStop suivant :
void __fastcall TService1::Service1Stop(TService *Sender, bool &Stopped)
{
SparkyThread->Terminate();
Stopped = true;
}
Dans le cadre du développement d’applications serveur, la décision de lancer un
nouveau thread dépend de la nature du service rendu, du nombre prévu de
connexions et du nombre prévu de processeurs dont dispose la machine
exécutant le service.

Propriétés de nom d’un service


La VCL propose des classes permettant de créer des applications service sur le
plate-forme Windows (non disponible pour les applications multiplates-formes).
Il s’agit de TService et de TDependency. Quand vous utilisez ces classes, les
diverses propriétés de nom peuvent être source de confusion. Cette section décrit
leurs différences.
Les services ont des noms d’utilisateur (appelés Nom de démarrage du service)
qui sont associés à des mots de passe, des noms d’affichage utilisés pour
l’affichage dans les fenêtres gestionnaire et éditeur et des noms réels (le nom du
service). Les dépendances peuvent être des services ou des groupes d’ordre de
chargement. Elles ont également des noms et des noms d’affichage. De plus,
comme les objets service dérivent de TComponent, ils héritent de la propriété
Name. Les paragraphes suivants décrivent ces diverses propriétés de nom.

Propriétés de TDependency
La propriété DisplayName de TDependency est à la fois le nom d’affichage et le
nom réel du service. Elle est presque toujours identique à la propriété Name
TDependency.

Propriétés de nom de TService


La propriété Name de TService est héritée de TComponent. C’est le nom du
composant et également le nom du service. Pour les dépendances qui sont des
services, cette propriété est identique aux propriétés Name et DisplayName de
TDependency.
TService::DisplayName est le nom affiché dans la fenêtre du gestionnaire de
service. Il diffère souvent du nom réel du service (TService::Name,
TDependency::DisplayName, TDependency::Name). Remarquez que généralement le

Création d’applications, de composants et de bibliothèques 7-9


Création de paquets et de DLL

nom d’affichage (DisplayName) n’est pas le même pour le service et pour la


dépendance.
Les noms de démarrage de service sont distincts du nom d’affichage et du nom
réel du service. Un ServiceStartName est la valeur saisie du nom d’utilisateur
dans la boîte de dialogue de démarrage sélectionnée depuis le gestionnaire de
contrôle de service.

Débogage d’applications service


Vous pouvez déboguer les applications service en attachant le processus de
l’application service lors de son exécution (c’est-à-dire en commençant par
démarrer le service puis en l’attachant au débogueur). Pour effectuer
l’attachement au processus d’application service, choisissez Exécuter|Attacher au
processus et sélectionnez l’application service dans la boîte de dialogue
résultante.
Dans certains cas, cette approche peut échouer en raison de droits insuffisants.
Si cela se produit, vous pouvez utiliser le gestionnaire de contrôle de service
pour permettre à votre service de fonctionner avec le débogueur :
1 Créez une clé (options d’exécution du fichier image) dans l’emplacement de
registre suivant :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
2 Créez une sous-clé portant le même nom que votre service (par exemple,
MONSERV.EXE). Ajoutez à cette sous-clé une valeur de type REG_SZ,
nommée Debugger. Utilisez le chemin complet de BCB.exe comme valeur de
chaîne.
3 Dans l’applet Services du panneau de configuration, sélectionnez votre service,
cliquez sur l’option de démarrage et activez l’option permettant au service
d’interagir avec le bureau.
Avec les systèmes Windows NT, vous pouvez utiliser une autre approche pour
déboguer les applications service. Cependant cette approche peut être difficile car
elle nécessite des intervalles de temps courts :
1 Lancez d’abord l’application dans le débogueur. Patientez quelques secondes
jusqu’à la fin du chargement.
2 Démarrez rapidement le service à partir du panneau de configuration ou de la
ligne de commande :
start MyServ
Vous devez lancer le service rapidement (dans les 15 à 30 secondes du
démarrage de l’application) car l’application se terminera si aucun service n’est
lancé.

Création de paquets et de DLL


Les bibliothèques de liaison dynamique (DLL) sont des modules de code
compilés qui fonctionnent en conjonction avec un exécutable pour proposer des

7-10 Guide du développeur


Création de paquets et de DLL

fonctionnalités à une application. Vous pouvez créer des DLL dans des
programmes multiplates-formes. Cependant, sous Linux, les DLL et les paquets
sont recompilés en tant qu’objets partagés.
Les paquets sont des DLL spéciales utilisées par les applications C++Builder, par
l’EDI ou les deux à la fois. Il y a deux sortes de paquets : les paquets d’exécution
et les paquets de conception. Les paquets d’exécution fournissent des
fonctionnalités à un programme lors de son exécution. Les paquets de conception
permettent d’étendre les fonctionnalités de l’EDI.
Les DLL et les bibliothèques doivent gérer toutes les exceptions pour empêcher
l’affichage d’erreurs ou d’avertissements dans des boîtes de dialogue Windows.
Les directives du compilateur suivantes peuvent être placées dans les fichiers
projet bibliothèque :

Tableau 7.1 Directives de compilation pour les bibliothèques


Directive
de compilation Description
{$LIBPREFIX ’chaîne’} Ajoute le préfixe spécifié au nom du fichier de destination. Par
exemple, vous pouvez spécifier {$LIBPREFIX ’dcl’} pour un paquet
de conception, ou utiliser {$LIBPREFIX ’ ’} pour éliminer totalement
le préfixe.
{$LIBSUFFIX ’chaîne} Ajoute le suffixe spécifié au nom du fichier de destination, avant
l’extension. Par exemple, utilisez {$LIBSUFFIX ’-2.1.3’} dans
quelquechose.cpp pour générer quelquechose-2.1.3.bpl.
{$LIBVERSION Ajoute une seconde extension au nom du fichier de destination
’chaîne’} après l’extension .bpl. Par exemple, utilisez {$LIBVERSION ’2.1.3’}
dans quelquechosecpp pour générer quelquechose.bpl.2.1.3.

Pour davantage d’informations sur les paquets, voir chapitre 15, “Utilisation des
paquets et des composants”.

Utilisation des paquets et des DLL


Pour la plupart des applications écrites avec C++Builder, les paquets offrent une
plus grande flexibilité et sont plus simples à créer que les DLL. Dans certaines
situations, les DLL sont mieux adaptées à vos projets que des paquets :
• Votre module de code doit être appelé par une application qui n’a pas été
conçue avec C++Builder.
• Vous étendez les fonctionnalités d’un serveur Web.
• Vous créez un module de code qui doit être utilisé par des développeurs
extérieurs.
• Votre projet est un conteneur OLE.
Vous ne pouvez pas transmettre des informations de type à l’exécution (RTTI)
entre DLL ou d’une DLL à un exécutable. C’est parce que les DLL maintiennent
leurs propres informations sur les symboles. Si vous avez besoin de transmettre

Création d’applications, de composants et de bibliothèques 7-11


Utilisation des DLL dans C++Builder

un objet TStrings à partir d’une DLL en utilisant un opérateur is ou as, créez un


paquet plutôt qu’une DLL. Les paquets partagent les informations sur les
symboles.

Utilisation des DLL dans C++Builder


Une DLL Windows peut être utilisée dans une application C++Builder comme
dans n’importe quelle application C++.
Pour charger statiquement une DLL lors du chargement de votre application
C++Builder, liez le fichier d’importation de bibliothèque de cette DLL à
l’application C++Builder lors de la liaison. Pour ajouter une bibliothèque
d’importation dans une application C++Builder, choisissez Projet|Ajouter au
projet et sélectionnez le fichier .LIB à ajouter.
Les fonctions exportées de la DLL sont alors disponibles dans l’application.
Prototypez les fonctions de la DLL utilisées dans l’application avec le
modificateur __declspec (dllimport) :
__declspec(dllimport) type_renvoyé nom_fonction_importée(paramètres);
Pour charger dynamiquement une DLL pendant l’exécution d’une application
C++Builder, incluez la bibliothèque d’importation comme pour un chargement
statique, puis spécifiez l’option de délai de chargement du lieur dans la page
Projet|Options|Lieur évolué. Vous pouvez également utiliser la fonction
LoadLibrary() de l’API Windows pour charger la DLL, puis utilisez la fonction
GetProcAddress() de l’API pour disposer d’un pointeur sur les fonctions
spécifiques à utiliser.
Pour plus d’informations sur l’utilisation des DLL, voir la Référence Win32 SDK
de Microsoft®.

Création de DLL dans C++Builder


La création de DLL est la même en C++Builder et en C++ standard :
1 Choisissez Fichier|Nouveau|Autre pour afficher la boîte de dialogue
Nouveaux éléments.
2 Double-cliquez sur l’icône Expert DLL.
3 Choisissez le type de fichier source (C ou C++) du module principal.
4 Si vous voulez utiliser le style MSVC++ et employer DllMain comme point
d’entrée de la DLL, cochez l’option VC++, sinon DllEntryPoint est utilisé
comme point d’entrée.
5 Cochez l’option Utiliser VCL ou Utiliser CLX pour créer une DLL contenant
des composants VCL ou CLX. Cette option est disponible uniquement pour les
modules source C++.
Voir “Création de DLL contenant des composants VCL et CLX” à la page 7-13.

7-12 Guide du développeur


Création de DLL contenant des composants VCL et CLX

6 Si la DLL doit être multithread, cochez l’options Multithread.


7 Cliquez sur OK.
Les fonctions exportées doivent être identifiées dans le code par le modificateur
__declspec (dllexport) comme en Borland C++ ou en Microsoft Visual C++. Par
exemple, le code suivant est correct en C++Builder, comme dans les autres
compilateurs C++ :
// MyDLL.cpp
double dblValue(double);
double halfValue(double);
extern "C" __declspec(dllexport) double changeValue(double, bool);

double dblValue(double value)


{
return value * value;
};

double halfValue(double value)


{
return value / 2.0;
}

double changeValue(double value, bool whichOp)


{
return whichOp ? dblValue(value) : halfValue(value);
}
Dans le code ci-dessus, la fonction changeValue est exportée, et de ce fait
utilisable par les applications appelantes. Les fonctions dblValue et halfValue sont
internes et ne peuvent être appelées hors de la DLL.
Pour plus d’informations sur la création de DLL, voir la Référence Win32 SDK de
Microsoft®.

Création de DLL contenant des composants VCL et CLX


L’un des avantages des DLL consiste à pouvoir utiliser une DLL créée avec un
outil de développement dans une application utilisant un autre outil de
développement. Si une DLL contient des composants VCL ou CLX (par exemple,
une fiche) devant être utilisés par les applications appelantes, il est nécessaire de
fournir des routines d’interface exportées utilisant les conventions d’appel
standard, en évitant le substantypage C++ et sans exiger pour fonctionner que
l’application appelante gère les bibliothèques VCL et CLX. Pour créer des
composants VCL ou CLX pouvant être exportés, utilisez les paquets d’exécution.
Pour plus d’informations, voir chapitre 15, “Utilisation des paquets
et des composants”.

Création d’applications, de composants et de bibliothèques 7-13


Création de DLL contenant des composants VCL et CLX

Par exemple, vous voulez créer une DLL afin d’afficher une simple boîte de
dialogue :

Voici le code de la DLL boîte de dialogue :


// DLLMAIN.H
//---------------------------------------------------------------------
#ifndef dllMainH
#define dllMainH
//---------------------------------------------------------------------
#include <Classes.hpp>
#include <vcl\Controls.hpp>
#include <vcl\StdCtrls.hpp>
#include <vcl\Forms.hpp>
//---------------------------------------------------------------------
class TYesNoDialog : public TForm
{
__published: // Composants gérés par l’EDI
TLabel *LabelText;
TButton *YesButton;
TButton *NoButton;
void __fastcall YesButtonClick(TObject *Sender);
void __fastcall NoButtonClick(TObject *Sender);
private: // Déclarations de l’utilisateur
bool returnValue;
public: // Déclarations de l’utilisateur
virtual __fastcall TYesNoDialog(TComponent *Owner);
bool __fastcall GetReturnValue();
};

// fonction d’interface exportée


extern "C" __declspec(dllexport) bool InvokeYesNoDialog();

//---------------------------------------------------------------------
extern TYesNoDialog *YesNoDialog;
//---------------------------------------------------------------------
#endif

// DLLMAIN.CPP
//---------------------------------------------------------------------
#include <vcl\vcl.h>
#pragma hdrstop

#include "dllMain.h"
//---------------------------------------------------------------------
#pragma resource "*.dfm"
TYesNoDialog *YesNoDialog;
//---------------------------------------------------------------------

7-14 Guide du développeur


Création de DLL contenant des composants VCL et CLX

__fastcall TYesNoDialog::TYesNoDialog(TComponent *Owner)


: TForm(Owner)
{
returnValue = false;
}
//---------------------------------------------------------------------
void __fastcall TYesNoDialog::YesButtonClick(TObject *Sender)
{
returnValue = true;
Close();
}
//---------------------------------------------------------------------
void __fastcall TYesNoDialog::NoButtonClick(TObject *Sender)
{
returnValue = false;
Close();
}
//---------------------------------------------------------------------
bool __fastcall TYesNoDialog::GetReturnValue()
{
return returnValue;
}
//---------------------------------------------------------------------
// fonction exportée d’interface C++ standard appelant la VCL
bool InvokeYesNoDialog()
{
bool returnValue;
TYesNoDialog *YesNoDialog = new TYesNoDialog(NULL);
YesNoDialog->ShowModal();
returnValue = YesNoDialog->GetReturnValue();
delete YesNoDialog;
return returnValue;
}
//---------------------------------------------------------------------
Le code de cet exemple affiche la boîte de dialogue et enregistre la valeur true
dans la donnée membre privée returnValue si le bouton “Oui” est choisi. Sinon,
returnValue prend la valeur false. La fonction membre publique GetReturnValue()
renvoie la valeur en cours de returnValue.
Pour appeler la boîte de dialogue et déterminer le bouton choisi, l’application
appelante doit utiliser la fonction exportée InvokeYesNoDialog(). Cette fonction est
déclarée dans DLLMAIN.H comme fonction exportée utilisant le lieur C (afin
d’éviter le substantypage C++) et la convention d’appel standard C. La fonction
est définie dans DLLMAIN.CPP.
L’utilisation d’une fonction C standard comme interface de la DLL permet à
toute application appelante, créée ou non avec C++Builder, d’utiliser la DLL. Les
fonctionnalités VCL et CLX nécessaires au fonctionnement de la boîte de
dialogue sont liées dans la DLL elle-même sans que l’application appelante en
sache quoique ce soit.
Toutefois la création d’une DLL utilisant VCL ou CLX nécessite la liaison des
composants VCL ou CLX nécessaires dans la DLL, ce qui en augmente la taille.

Création d’applications, de composants et de bibliothèques 7-15


Liaison de DLL

L’impact de cette augmentation sur la taille totale de l’application peut être


réduite en combinant plusieurs composants dans une seule DLL qui ne nécessite
qu’une seule copie des composants de gestion VCL ou CLX.

Liaison de DLL
Vous pouvez définir les options du lieur pour votre DLL sur la page Lieur de la
boîte de dialogue Options du projet. La case à cocher par défaut de cette page
permet également de créer une bibliothèque d’importation pour votre DLL. Si la
compilation est effectuée à partir de la ligne de commande, appelez le lieur,
ILINK32.EXE, avec le commutateur -Tpd. Par exemple :
ilink32 /c /aa /Tpd c0d32.obj mydll.obj, mydll.dll, mydll.map, import32.lib cw32mt.lib
Si vous avez besoin d’une bibliothèque d’importation, utilisez aussi le
commutateur -Gi, qui permet de la générer.
Vous pouvez, si vous le souhaitez, créer une bibliothèque d’importation avec
l’utilitaire de ligne de commande IMPLIB.EXE. Par exemple :
implib mydll.lib mydll.dll
Pour plus d’informations sur les différentes options de liaison de DLL et leur
utilisation avec d’autres modules statiquement ou dynamiquement liés à la
bibliothèque d’exécution, voir l’aide en ligne.

Ecriture d’applications de bases de données


Un des atouts de C++Builder est sa possibilité de créer des applications de bases
de données sophistiquées. C++Builder fournit des outils intégrés permettant de
vous connecter aux serveurs et bases de données SQL, comme Oracle, Sybase,
InterBase, MySQL, MS-SQL, Informix et DB2, tout en assurant un partage des
données transparent entre les différentes applications.
C++Builder comprend de nombreux composants permettant d’accéder aux bases
de données et de représenter les informations qu’elles contiennent. Sur la palette
de composants, les composants base de données sont regroupés selon le
mécanisme et la fonction d’accès aux données.

Tableau 7.2 Page base de données de la palette des composants


Page
de palette Contenu
BDE Composants qui utilisent le moteur de bases de données Borland (BDE), une
importante API permettant d’interagir avec les bases de données. Le moteur
BDE supporte la plus vaste gamme de fonctions et la plupart des utilitaires
dont Database Desktop, l’explorateur de base de données, le moniteur SQL
et l’administrateur BDE. Pour plus de détails, voir chapitre 24, “Utilisation
du moteur de bases de données Borland”.

7-16 Guide du développeur


Ecriture d’applications de bases de données

Tableau 7.2 Page base de données de la palette des composants (suite)


Page
de palette Contenu
ADO Composants qui utilisent les objets de données ActiveX (ADO), développés
par Microsoft, pour accéder aux informations des bases de données. De
nombreux pilotes ADO sont disponibles pour la connexion à différents
serveurs de bases de données. Les composants ADO vous permettent
d’intégrer votre application à l’environnement ADO. Pour plus de détails,
voir chapitre 25, “Utilisation des composants ADO”.
dbExpress Composants multiplates-formes qui utilisent dbExpress pour accéder aux
informations des bases de données. Les pilotes dbExpress fournissent un
accès rapide aux bases de données, mais doivent être utilisés avec
TClientDataSet et TDataSetProvider pour effectuer des mises à jour. Pour plus
de détails, voir chapitre 26, “Utilisation d’ensembles de données
unidirectionnels”.
InterBase Composants qui accèdent directement aux bases de données InterBase, sans
passer par une couche moteur distincte. Pour plus d’informations sur
l’utilisation des composants InterBase, voir l’aide en ligne.
AccèsBD Composants qui peuvent être utilisés avec n’importe quel mécanisme d’accès
aux données comme TClientDataSet et TDataSetProvider. Voir chapitre 27,
“Utilisation d’ensembles de données client”, pour avoir des informations sur
les ensembles de données client. Voir chapitre 28, “Utilisation des
composants fournisseur”, pour avoir des informations sur les fournisseurs.
ContrôleBD Contrôles orientés données qui peuvent accéder aux informations d’une
source de données. Voir chapitre 19, “Utilisation de contrôles de données”,
pour plus de détails.

Lorsque vous concevez une application de base de données, vous devez choisir
le mécanisme d’accès aux données à utiliser. Chaque mécanisme d’accès aux
données diffère par l’éventail des fonctions prises en charge, la facilité de
déploiement et la capacité des pilotes à gérer divers serveurs de bases de
données.
Voir la partie II, “Développement d’applications de bases de données”, dans ce
manuel, pour plus de détails sur la façon d’utiliser C++Builder pour créer des
applications de bases de données client ou serveur. Reportez-vous à
“Déploiement d’applications de bases de données” à la page 17-7 pour avoir des
informations sur le déploiement.
Remarque Les éditions de C++Builder n’offrent pas toutes le support des bases de données.

Distribution d’applications de bases de données


C++Builder permet de créer des applications de bases de données distribuées en
utilisant un ensemble de composants liés. Il est ainsi possible d’écrire des
applications de bases de données en utilisant divers protocoles de
communication, dont DCOM, TCP/IP et SOAP.
Pour davantage d’informations sur la conception d’applications de bases de
données distribuées, voir chapitre 29, “Création d’applications multiniveaux”.

Création d’applications, de composants et de bibliothèques 7-17


Création d’applications serveur Web

Le déploiement d’applications de bases de données nécessite souvent le


déploiement du moteur de bases de données Borland (BDE) en plus des fichiers
de l’application. Pour des informations sur le déploiement du BDE, voir
“Déploiement d’applications de bases de données” à la page 17-7.

Création d’applications serveur Web


Les applications serveur Web sont des applications s’exécutant sur des serveurs
qui fournissent du contenu web, c’est-à-dire des pages HTML ou des documents
XML, sur Internet. Les applications serveur Web sont par exemple des
applications qui contrôlent l’accès à un site web, génèrent des bons de
commande ou répondent à des demandes d’informations.
Vous pouvez créer différents types d’applications serveur Web en utilisant les
technologies C++Builder suivantes :
• WebBroker
• WebSnap
• InternetExpress
• Services Web

Utilisation de WebBroker
Vous pouvez utiliser WebBroker (appelé aussi architecture NetCLX) pour créer
des applications serveur Web comme les applications CGI ou les bibliothèques
de liaison dynamiques (DLL). Ces applications serveur web peuvent ne contenir
aucun composant visuel. Les composants de la page Internet de la palette de
composants vous permettent de créer des gestionnaires d’événements, de
construire par programme des documents HTML ou XML et de les transférer
au client.
Pour créer une nouvelle application serveur Web en utilisant l’architecture
WebBroker, choisissez Fichier|Nouveau|Autre et double-cliquez sur Application
serveur Web dans la boîte de dialogue Nouveaux éléments. Choisissez ensuite le
type d’application serveur Web :

Tableau 7.3 Applications serveur Web


Type d’application
serveur Web Description
DLL ISAPI/NSAPI Les applications serveur Web ISAPI et NSAPI sont des DLL qui sont
chargées par le serveur Web. Les informations de requête client sont
transmises à la DLL sous forme de structure et sont évaluées par
TISAPIApplication. Chaque message de requête est géré dans un
thread d’exécution distinct.
Sélectionner ce type d’application ajoute l’en-tête bibliothèque des
fichiers du projet et les entrées nécessaires à la liste uses et à la
clause exports du fichier projet.

7-18 Guide du développeur


Création d’applications serveur Web

Tableau 7.3 Applications serveur Web (suite)


Type d’application
serveur Web Description
Exécutable autonome Les applications serveur Web CGI sont des applications console qui
CGI reçoivent les requêtes des clients sur l’entrée standard, traitent ces
requêtes et renvoient le résultat sur la sortie standard afin qu’il soit
renvoyé au client.
Exécutable autonome Les applications serveur Web Win-CGI sont des applications
Win-CGI Windows qui reçoivent les requêtes des clients à partir d’un fichier
de paramètres de configuration (INI) écrit par le serveur et qui
écrivent le résultat dans un fichier que le serveur renvoie au client.
Le fichier INI est évalué par TCGIApplication. Chaque message de
requête est géré par une instance distincte de l’application.
Module Apache La sélection de ce type d’application configure votre projet comme
partagé (DLL) une DLL. Les applications serveur Web Apache sont des DLL
chargées par le serveur Web. Les informations sont transmises à la
DLL, traitées puis renvoyées au client par le serveur Web.
Exécutable La sélection de ce type d’application configure un environnement
débogueur pour développer et tester des applications serveur Web. Les
d’application Web applications Débogueur d’application Web sont des fichiers
exécutables chargées par le serveur Web. Ce type d’application n’est
pas destiné au déploiement.

Les applications CGI et Win-CGI utilisent davantage de ressources système sur le


serveur, les applications complexes sont mieux gérées si elles sont créées sous la
forme d’applications ISAPI, NSAPI ou Apache DLL. Si vous écrivez des
applications multiplates-formes, vous devez sélectionner autonome CGI ou
Module Apache partagé (DLL) pour le développement de serveur Web. Vous
avez les mêmes options lorsque vous créez des applications WebSnap et service
Web.
Pour plus d’informations sur la construction d’applications serveur Web, voir
chapitre 32, “Création d’applications serveur Internet”.

Création d’applications WebSnap


WebSnap fournit un ensemble de composants et d’experts permettant de
construire des serveurs Web évolués qui interagissent avec les navigateurs web.
Les composants WebSnap génèrent du HTML ou d’autre contenu MIME pour les
pages Web. WebSnap est destiné au développement côté serveur. WebSnap ne
peut pas, pour l’instant, être utilisé dans des applications multiplates-formes.
Pour créer une nouvelle application WebSnap, sélectionnez Fichier|Nouveau|
Autre et sélectionnez l’onglet WebSnap dans la boîte de dialogue Nouveaux
éléments. Choisissez Application WebSnap. Ensuite, sélectionnez le type
d’application serveur Web (ISAPI/NSAPI, CGI, Win-CGI, Apache). Voir le
tableau 7.3, “Applications serveur Web”, pour plus de détails.
Pour plus d’informations sur WebSnap, voir chapitre 34, “Création d’applications
serveur Web avec WebSnap”.

Création d’applications, de composants et de bibliothèques 7-19


Ecriture d’applications en utilisant COM

Utilisation d’InternetExpress
InternetExpress est un ensemble de composants permettant d’étendre
l’architecture d’application serveur Web de base pour qu’elle agisse en tant que
client d’une application serveur. Vous utilisez InternetExpress pour les
applications dans lesquelles les clients dans un navigateur peuvent accéder aux
données d’un fournisseur, résoudre les mises à jour du fournisseur tout en
s’exécutant sur un client.
Les applications InternetExpress génèrent des pages HTML qui associent HTML,
XML et javascript. HTML régit la disposition et l’aspect des pages affichées dans
le navigateur des utilisateurs finals. XML code les paquets de données et les
paquets delta qui représentent les informations base de données. Javascript
permet aux contrôles HTML d’interpréter et de manipuler les données des
paquets XML sur la machine client.
Pour plus d’informations sur InternetExpress, voir chapitre “Construction des
applications Web avec InternetExpress” à la page 29-35.

Création d’applications services Web


Les services Web sont des applications modulaires indépendantes qui peuvent
être publiées ou invoquées sur un réseau (comme le web). Les services Web
fournissent des interfaces bien définies qui décrivent les services fournis. Vous
utilisez les services Web pour fournir ou utiliser des services programmables sur
Internet en faisant appel aux derniers standards comme XML, XML Schema,
SOAP (Simple Object Access Protocol) et WSDL (Web Service Definition
Language).
Les services Web utilisent SOAP, un protocole léger standard permettant
d’échanger des informations dans une environnement distribué. Il utilise HTTP
comme protocole de communication et XML pour coder les appels des
procédures distantes.
Vous pouvez utiliser C++Builder pour construire des serveurs qui implémentent
des services Web et des clients qui font appel à ces services. Vous pouvez écrire
des clients pour que des serveurs quelconques implémentent des services Web
qui répondent aux messages SOAP et des serveurs C++Builder pour publier des
services Web à utiliser par des clients quelconques.
Pour plus d’informations sur services Web, voir chapitre 36, “Utilisation de
services Web”.

Ecriture d’applications en utilisant COM


COM (Component Object Model) propose une architecture d’objet distribué sous
Windows conçue pour assurer une interopérabilité des objets en utilisant des
routines prédéfinies appelées des interfaces. Les applications COM utilisent des
objets implémentés par un processus différent ou, si vous utilisez DCOM, sur

7-20 Guide du développeur


Ecriture d’applications en utilisant COM

une machine différente. Vous pouvez aussi utiliser COM+, ActiveX et les pages
Active Server.
COM est un modèle de composant logiciel indépendant du langage qui permet
l’interaction entre des composants logiciels et des applications s’exécutant sous
Windows. L’aspect fondamental de COM est de permettre la communication
entre composants, entre applications et entre clients et serveurs, par le biais
d’interfaces clairement définies. Les interfaces offrent aux clients un moyen de
demander à un composant COM quelles fonctionnalités il supporte à l’exécution.
Pour fournir d’autres fonctionnalités à votre composant, il suffit d’ajouter une
autre interface pour ces fonctionnalités.

Utilisation de COM et de DCOM


C++Builder contient des classes et des experts qui simplifient la création
d’applications COM, OLE ou ActiveX. Vous pouvez créer des clients ou des
serveurs COM qui implémentent des objets COM, des serveurs d’automatisation
(dont les objets Active Server), des contrôles ActiveX ou des ActiveForms. COM
sert également de base à d’autres technologies comme l’automatisation, les
contrôles ActiveX, les documents Active et les répertoires Active.
L’utilisation de C++Builder pour créer des applications basées sur COM offre de
nombreuses possibilités, allant de l’amélioration de la conception de logiciel en
utilisant des interfaces de manière interne dans une application, à la création
d’objets qui peuvent interagir avec d’autres objets utilisant l’API COM du
système, comme les extensions du shell Win9x ou la gestion multimedia DirectX.
Les applications peuvent accéder aux interfaces des composants COM se
trouvant sur le même ordinateur que l’application ou sur un autre ordinateur du
réseau, en utilisant un mécanisme nommé DCOM (Distributed COM).
Pour davantage d’informations sur COM et les contrôles ActiveX, voir
chapitre 38, “Présentation des technologies COM”, chapitre 43, “Création d’un
contrôle ActiveX”, et “Distribution d’une application client en tant que contrôle
ActiveX” à la page 29-34.
Pour davantage d’informations sur DCOM, voir “Utilisation de connexions
DCOM” à la page 29-10.

Utilisation de MTS et de COM+


Il est possible d’étendre les applications COM en utilisant des services spéciaux
pour gérer les objets dans un environnement distribué important. Ces services
sont, entre autres, des services de transaction, la sécurité et la gestion des
ressources proposées par Microsoft Transaction Server (MTS) (pour les versions
de Windows antérieures à Windows 2000) ou COM+ (pour Windows 2000 ou
plus).
Pour davantage d’informations sur MTS et COM+, voir chapitre 44, “Création
d’objets MTS ou COM+” et “Utilisation des modules de données transactionnels”
à la page 29-7.

Création d’applications, de composants et de bibliothèques 7-21


Utilisation de modules de données

Utilisation de modules de données


Un module de données ressemble à une fiche spéciale qui ne contient que des
composants non-visuels. Tous les composants d’un module de données peuvent
être placés dans des fiches ordinaires avec des contrôles visuels. Les modules de
données constituent un moyen d’organisation utile quand vous envisagez de
réutiliser des groupes d’objets de bases de données ou système ou si vous
souhaitez isoler les parties d’une application qui gèrent la connexion aux bases
de données ou les règles de fonctionnement.
Il y a plusieurs types de modules de données, dont standard, distant, modules
Web, modules applet et services, selon l’édition de C++Builder que vous avez.
Chaque type de module de données a une fonction spéciale.
• Les modules de données standard sont particulièrement utiles aux applications
de bases de données à un ou à deux niveaux, mais peuvent être utilisés pour
organiser les composants non visuels de n’importe quelle application. Pour
plus d’informations, voir “Création et modification de modules de données
standard” à la page 7-23.
• Les modules de données distants constituent la base d’un serveur
d’application dans une application de base de données multiniveau. Ils ne
sont pas disponibles dans toutes les éditions. En plus de contenir les
composants non visuels du serveur d’application, les modules de données
distants exposent l’interface utilisée par les clients pour communiquer avec le
serveur d’application. Pour plus d’informations sur leur utilisation, voir “Ajout
d’un module de données distant à un projet serveur d’application” à la
page 7-26.
• Les modules Web constituent la base des applications serveur Web. En plus
de contenir les composants qui créent le contenu des messages de réponse
HTTP, ils gèrent la répartition des messages HTTP issus des applications
client. Voir chapitre 32, “Création d’applications serveur Internet”, pour plus
d’informations sur l’utilisation des modules Web.
• Les modules applet constituent la base des applets de panneau de
configuration. En plus de contenir les composants non visuels qui
implémentent le panneau de configuration, ils définissent les propriétés qui
déterminent la façon dont l’icône de l’applet apparaît dans le panneau de
configuration et contiennent les événements qui sont appelés quand les
utilisateurs exécutent l’applet. Pour plus d’informations sur les modules
applet, voir l’aide en ligne.
• Les services encapsulent des services individuels dans une application de
service NT. En plus de contenir les composants non visuels qui implémentent
un service, les services contiennent les événements qui sont appelés quand le
service est démarré ou arrêté. Pour davantage d’informations sur les services,
voir “Applications service” à la page 7-4.

7-22 Guide du développeur


Utilisation de modules de données

Création et modification de modules de données standard


Pour créer un module de données standard pour un projet, choisissez Fichier|
Nouveau|Module de données. C++Builder ouvre un conteneur module de
données sur le bureau, affiche le fichier unité du nouveau module dans l’éditeur
de code et ajoute le module au projet en cours.
En conception, un module de données ressemble à une fiche C++Builder
standard, avec un fond blanc et pas de grille d’alignement. Comme avec les
fiches, vous pouvez placer des composants non visuels de la palette dans un
module et modifier leurs propriétés dans l’inspecteur d’objets. Vous pouvez
redimensionner un module de données pour l’adapter aux composants que vous
lui ajoutez.
Vous pouvez aussi cliquer avec le bouton droit sur un module pour afficher son
menu contextuel. Le tableau suivant résume les options du menu contextuel d’un
module de données :

Tableau 7.4 Options du menu contextuel des modules de données


Elément de menu Utilisation
Edition Affiche un menu contextuel grâce auquel vous pouvez couper,
copier, coller, supprimer et sélectionner les composants du module
de données.
Position Aligne les composants s non visuels sur la grille invisible du module
(Aligner sur la grille) ouselon des critères que vous indiquez dans la
boîte de dialogue Alignement (Aligner).
Ordre de tabulation Vous permet de changer l’ordre dans lequel la focalisation parcourt
les composants quand vous appuyez sur la touche Tab.
Ordre de création Vous permet de modifier l’ordre dans lequel les composants d’accès
aux données sont créés au démarrage.
Revenir à hérité Annule les modifications apportées à un module hérité d’un autre
module dans le référentiel d’objets, et revient au module tel qu’il
était à l’origine lors de l’héritage.
Ajouter au référentiel Stocke un lien vers le module de données dans le référentiel d’objets.
Voir comme texte Affiche la représentation textuelle des propriétés du module de
données.
DFM texte Bascule entre les formats (binaire ou texte) dans lesquels est
enregistrée la fiche.

Pour davantage d’informations sur les modules de données, voir l’aide en ligne.

Nom d’un module de données et de son fichier unité


La barre de titre d’un module de données affiche le nom du module. Le nom
par défaut est “DataModuleN”, où N est un nombre représentant le plus petit
numéro d’unité non utilisé dans le projet. Par exemple, si vous commencez un
nouveau projet et si vous lui ajoutez un module avant de faire quoi que ce soit
d’autre, le nom du module de données est par défaut “DataModule2”. Le fichier
unité correspondant à DataModule2 est par défaut “Unit2”.

Création d’applications, de composants et de bibliothèques 7-23


Utilisation de modules de données

Il vaut mieux renommer les modules de données et les fichiers unités


correspondants, pendant la conception, pour qu’ils soient plus descriptifs. En
particulier, il faut renommer les modules de données que vous ajoutez au
référentiel d’objets pour éviter les conflits de nom avec d’autres modules de
données du référentiel ou des applications qui utilisent vos modules.
Pour renommer un module de données :
1 Sélectionnez le module.
2 Modifiez la propriété Name du module dans l’inspecteur d’objets.
Le nouveau nom du module apparaît dans la barre de titre dès que la propriété
Name n’a plus la focalisation dans l’inspecteur d’objets.
Changer le nom d’un module de données en conception change son nom de
variable dans la section interface du code. Cela change également toute
utilisation du nom dans les déclarations de procédure. Vous devez changer
manuellement toutes les références à ce module de données dans le code que
vous avez écrit.
Pour renommer le fichier unité d’un module de données :
1 Sélectionnez le fichier unité.

Placer et nommer les composants


Vous placez des composants non visuels dans un module de données exactement
comme vous les placeriez sur une fiche. Cliquez sur le composant voulu dans la
page appropriée de la palette de composants, puis cliquez dans le module de
données pour placer le composant. Vous ne pouvez pas placer des contrôles
visuels, comme les grilles, dans un module de données. Si vous essayez de le
faire, vous recevez un message d’erreur.
Pour faciliter leur utilisation, les composants d’un module de données sont
affichés avec leur nom. Quand vous placez un composant pour la première fois,
C++Builder lui attribue un nom générique indiquant le type du composant, suivi
de 1. Par exemple, le composant TDataSource prend le nom DataSource1. Cela
facilite la sélection des composants lorsque vous voulez travailler sur leurs
propriétés et méthodes.
Vous pouvez encore donner à un composant un autre nom qui reflète son type
et sa fonction.
Pour changer le nom d’un composant dans un module de données :
1 Sélectionnez le composant.
2 Modifiez la propriété Name du composant dans l’inspecteur d’objets.
Le nouveau nom du composant apparaît sous son icône dans le module de
données dès que la propriété Name n’a plus la focalisation dans l’inspecteur
d’objets.
Par exemple, supposons que votre application de base de données utilise la table
CUSTOMER. Pour accéder à cette table, vous avez besoin d’au moins deux
composants d’accès aux données : un composant source de données (TDataSource)

7-24 Guide du développeur


Utilisation de modules de données

et un composant table (TClientDataSet). Quand vous placez ces composants dans


votre module de données, C++Builder leur attribue les noms DataSource1 et
ClientDataSet1. Pour refléter le type des composants et la base de données à
laquelle ils accèdent, CUSTOMER, vous pourriez changer leurs noms en
CustomerSource et CustomerTable.

Utilisation des propriétés et événements des composants dans un module


de données
Placer des composants dans un module de données centralise leur comportement
pour l’application toute entière. Par exemple, vous pouvez utiliser les propriétés
des composants ensemble de données, comme TClientDataSet, pour contrôler les
données disponibles dans les composants source de données qui utilisent ces
ensembles de données. Définir la propriété ReadOnly d’un ensemble de données
par true empêche les utilisateurs de modifier les données qu’ils voient dans un
contrôle orienté données se trouvant dans une fiche. Vous pouvez aussi appeler
l’éditeur de champs d’un ensemble de données, en double-cliquant sur
ClientDataSet1, pour limiter les champs d’une table ou d’une requête qui seront
disponibles pour la source de données et donc pour les contrôles orientés
données des fiches. Les propriétés que vous définissez pour les composants d’un
module de données s’appliquent à toutes les fiches de votre application qui
utilisent le module.
Outre les propriétés, vous pouvez écrire des gestionnaires d’événements pour les
composants. Par exemple, un composant TDataSource peut avoir trois
événements : OnDataChange, OnStateChange et OnUpdateData. Un composant
TClientDataSet a plus de 20 événements possibles. Vous pouvez utiliser ces
événements pour créer un ensemble cohérent de règles de gestion qui dictent les
manipulation de données dans toute votre application.

Création de règles de gestion dans un module de données


Parallèlement à l’écriture de gestionnaires d’événements pour les composants
d’un module de données, vous pouvez programmer des méthodes directement
dans le fichier unité du module de données. Ces méthodes peuvent être
appliquées en tant que règles de gestion aux fiches qui utilisent le module de
données. Par exemple, vous pouvez écrire une procédure qui établisse les
comptes mensuels, trimestriels et annuels. Vous pouvez appeler cette procédure
depuis un gestionnaire d’événement d’un composant du module de données.

Accès à un module de données depuis une fiche


Pour associer des contrôles visuels d’une fiche à un module de données, vous
devez tout d’abord ajouter le fichier en-tête du module de données au fichier
cpp de la fiche. Pour ce faire, vous pouvez procéder de plusieurs manières :
• Ouvrez le fichier unité de la fiche dans l’éditeur de code et incluez le fichier
en-tête du du module de données en utilisant la directive #include.

Création d’applications, de composants et de bibliothèques 7-25


Utilisation de modules de données

• Cliquez sur le fichier unité de la fiche, choisissez Fichier|Inclure l’en-tête


d’unité, puis entrez le nom d’un module ou choisissez-le dans la boîte liste de
la boîte de dialogue Utiliser l’unité.
• Pour les composants base de données, cliquez dans le module de données sur
un composant ensemble de données ou requête pour ouvrir l’éditeur de
champs et faire glisser dans la fiche des champs de l’éditeur. C++Builder vous
demande alors de confirmer l’ajout de ce module dans la fiche puis crée des
contrôles (par exemple, des boîtes de saisie) pour chaque champ.
Par exemple, si vous avez ajouté le composant TClientDataSet à votre module de
données, double-cliquez dessus pour ouvrir l’éditeur de champs. Sélectionnez un
champ et faites-le glisser dans la fiche. Une boîte de saisie apparaît.
Comme la source de données n’est pas encore définie, C++Builder ajoute un
nouveau composant source de données, DataSource1, à la fiche et définit la
propriété DataSource de la boîte de saisie par DataSource1. La source de données
définit automatiquement sa propriété DataSet par le composant ensemble de
données, ClientDataSet1, dans le module de données.
Vous pouvez définir la source de données avant de faire glisser un champ sur la
fiche, en ajoutant un composant TDataSource au module de données. Définissez
la propriété DataSet de la source de données par ClientDataSet1. Une fois que
vous avez fait glissé un champ dans la fiche, la boîte de saisie apparaît avec sa
propriété TDataSource déjà définie par DataSource1. Grâce à cette méthode, votre
modèle d’accès aux données est plus propre.

Ajout d’un module de données distant à un projet serveur


d’application
Certaines éditions de C++Builder vous permettent d’ajouter des modules de
données distants à des projets de serveur d’applications. Un module de données
distant dispose d’une interface à laquelle les clients d’une application
multiniveau peuvent accéder au travers d’un réseau.
Pour ajouter un module de données distant à un projet :
1 Choisissez Fichier|Nouveau|Autre.
2 Sélectionnez la page Multi-niveaux dans la boîte de dialogue Nouveaux
éléments.
3 Double-cliquez sur l’icône Module de données distant pour ouvrir l’expert
module de données distant.
Une fois le module de données distant ajouté à un projet, vous pouvez l’utiliser
comme un module de données standard.
Pour davantage d’informations sur les applications de base de données
multiniveaux, voir chapitre 29, “Création d’applications multiniveaux”.

7-26 Guide du développeur


Utilisation du référentiel d’objets

Utilisation du référentiel d’objets


Le référentiel d’objets (Outils|Référentiel) vous permet facilement de partager ou
de copier des fiches, des boîtes de dialogue ou des modules de données. Il
propose également des modèles de projet comme point de départ pour de
nouveaux projets et des experts qui guident l’utilisateur dans la création de
fiches ou de projets. Le référentiel est stocké dans BCB.DRO (placé par défaut
dans le répertoire BIN), c’est un fichier texte qui contient des références aux
éléments apparaissant dans le référentiel et dans la boîte de dialogue Nouveaux
éléments.

Partage d’éléments dans un projet


Il est également facile de partager des éléments à l’intérieur d’un projet sans avoir
à les ajouter au référentiel d’objets. Quand vous ouvrez la boîte de dialogue
Nouveaux éléments (Fichier|Nouveau|Autre), l’onglet d’une des pages porte le
nom de votre projet. Cette page énumère toutes les fiches, boîtes de dialogue et
modules de données de votre projet. Vous pouvez alors dériver un nouvel
élément d’un élément existant et le personnaliser si nécessaire.

Ajout d’éléments au Référentiel d’objets


Vous pouvez ajouter vos propres projets, fiches, cadres et modules de données à
ceux qui existent déjà dans le Référentiel d’objets. Pour ajouter un élément au
Référentiel d’objets,
1 Si l’élément est un projet ou dans un projet, ouvrez le projet.
2 Pour un projet, choisissez Projet|Ajouter au référentiel. Pour une fiche ou un
module de données, cliquez sur l’élément avec le bouton droit de la souris
puis choisissez Ajouter au référentiel.
3 Entrez une description, un titre et un auteur.
4 Décidez dans quelle page cet élément doit apparaître dans la boîte de
dialogue Nouveaux éléments, entrez ou sélectionnez la page dans la boîte à
options Page. Si vous entrez un nom de page inexistant, C++Builder crée une
nouvelle page.
5 Choisissez Parcourir pour sélectionner une icône représentant l’objet dans le
Référentiel d’objets.
6 Choisissez OK.

Partage d’objets par une équipe de développement


Vous pouvez partager des objets dans un groupe de travail ou une équipe de
développement en utilisant un référentiel accessible depuis un réseau. Pour
utiliser un référentiel partagé, tous les membres de l’équipe doivent sélectionner

Création d’applications, de composants et de bibliothèques 7-27


Utilisation du référentiel d’objets

le même répertoire de Référentiel partagé dans la boîte de dialogue Options


d’environnement :
1 Choisissez Outils|Options d’environnement.
2 Dans la page Préférences, repérez le volet Référentiel partagé. Dans le volet
boîte de saisie Répertoire, entrez le nom du répertoire où doit se trouver le
référentiel partagé. Assurez-vous que le répertoire spécifié est bien accessible
pour tous les membres de l’équipe.
Lors de l’ajout du premier élément au référentiel, C++Builder crée, s’il n’existe
pas déjà, un fichier BCB.DRO dans le répertoire spécifié par Référentiel partagé.

Utilisation d’un élément du référentiel d’objets dans un projet


Pour accéder aux éléments du Référentiel d’objets, choisissez Fichier|Nouveau|
Autre. La boîte de dialogue Nouveaux éléments apparaît et affiche tous les
éléments disponibles. Selon le type d’élément que vous souhaitez utiliser, il y a
jusqu’à trois options pour ajouter un élément à votre projet :
• Copier
• Hériter
• Utiliser

Copie d’un élément


Choisissez Copier pour obtenir une réplique exacte de l’élément sélectionné et
ajouter la copie à votre projet. Les modifications ultérieures de l’élément du
Référentiel d’objets ne sont pas répercutées sur votre copie. De même, les
modifications apportées à la copie n’affectent pas l’élément original dans le
Référentiel d’objets.
Copier est la seule option possible pour les modèles de projet.

Héritage d’un élément


Choisissez Hériter pour dériver une nouvelle classe de l’élément sélectionné dans
le Référentiel d’objets et ajouter la nouvelle classe à votre projet. Quand vous
recompilez votre projet, toutes les modifications apportées à l’élément du
Référentiel d’objets sont reportées dans votre classe dérivée. Les modifications
faites dans la classe dérivée n’affectent pas l’élément partagé du Référentiel
d’objets.
Hériter est une option proposée pour les fiches, les boîtes de dialogue et les
modules de données, mais pas pour les modèles de projet. C’est la seule option
utilisable pour réutiliser les éléments du projet en cours.

Utilisation d’un élément


Choisissez Utiliser quand vous voulez que l’objet sélectionné fasse lui-même
partie de votre projet. Les modifications faites à l’élément apparaissent dans tous
les projets dans lesquels l’élément a été ajouté en utilisant l’option Hériter ou
Utiliser. Soyez prudent si vous choisissez cette option.

7-28 Guide du développeur


Utilisation du référentiel d’objets

L’option Utiliser est disponible pour les fiches, les boîtes de dialogue et les
modules de données.

Utilisation de modèles de projet


Les modèles de projet sont des projets préfabriqués que vous pouvez utiliser
comme point de départ pour la création de vos projets. Pour créer un nouveau
projet à partir d’un modèle
1 Choisissez Fichier|Nouveau|Autre pour afficher la boîte de dialogue
Nouveaux éléments.
2 Choisissez l’onglet Projets.
3 Sélectionnez le modèle de projet souhaité et choisissez OK.
4 Dans la boîte de dialogue Sélection du répertoire, spécifiez le répertoire des
fichiers du nouveau projet..
C++Builder copie les fichiers du modèle dans le répertoire spécifié, où vous
pouvez ensuite les modifier. Le modèle de projet initial n’est pas affecté par vos
modifications.

Modification d’éléments partagés


Si vous modifiez un élément du référentiel d’objets, vos modifications affectent
tous les projets qui ultérieurement utilisent l’élément mais également tous les
projets existants qui ont ajouté l’élément en utilisant les options Utiliser ou
Hériter. Pour éviter de propager des modifications à d’autres projets, vous avez
plusieurs solutions :
• Copier l’élément et le modifier uniquement dans le projet en cours.
• Copier l’élément dans le projet en cours, le modifier puis l’ajouter au
référentiel sous un autre nom.
• Créer un composant, une DLL, un modèle de composant ou un cadre à partir
de l’élément. Si vous créez un composant ou une DLL, vous pouvez le
partager avec d’autres développeurs.

Spécification d’un projet par défaut, d’une nouvelle fiche et de la


fiche principale
Par défaut, quand vous choisissez Fichier|Nouveau|Application ou Fichier|
Nouveau|Fiche, C++Builder affiche une fiche vide. Vous pouvez changer ce
comportement en reconfigurant le référentiel :
1 Choisissez Outils|Référentiel.

Création d’applications, de composants et de bibliothèques 7-29


Activation de l’aide dans les applications

2 Si vous voulez spécifier un projet par défaut, sélectionnez la page Projets et


choisissez un élément dans Objets. Sélectionnez ensuite la case à cocher
Nouveau projet.
3 Pour spécifier une fiche par défaut, sélectionnez une page Référentiel (comme
Fiches), puis choisissez une fiche sous Objets. Pour spécifier la nouvelle fiche
par défaut, (Fiche|Nouveau|Fiche), sélectionnez la case à cocher Nouvelle
fiche. Pour spécifier la nouvelle fiche principale par défaut des nouveaux
projets, sélectionnez la case à cocher Fiche principale.
4 Cliquez sur OK.

Activation de l’aide dans les applications


La VCL et la CLX supportent toutes deux l’affichage de l’aide à partir
d’applications utilisant un mécanisme à base d’objets pour transmettre les
demandes d’aide à l’un des multiples visualiseurs d’aide externes. Pour
supporter cela, une application doit contenir une classe qui implémente
l’interface ICustomHelpViewer (et, éventuellement, une des nombreuses interfaces
qui en descendent), puis se recense elle-même dans le gestionnaire d’aide global.
La VCL fournit à toutes les applications une instance de TWinHelpViewer, qui
implémente toutes ces interfaces et fournit un lien entre les applications et
WinHelp. CLX impose que vous fournissiez votre propre implémentation. Dans
Windows, les applications CLX peuvent utiliser l’unité WinHelpViewer fournie
avec la VCL en la liant de manière statique, c’est-à-dire en incluant l’unité
comme faisant partie du paquet au lieu de la lier dans le paquet VCL.
Le gestionnaire d’aide maintient la liste des visualiseurs recensés et leur passe les
requêtes dans un processus en deux phases : d’abord, il demande à chaque
visualiseur s’il est capable de fournir du support sur un mot clé ou un contexte
d’aide particulier ; ensuite, il passe la requête d’aide au visualiseur ayant indiqué
qu’il peut fournir un tel support.
Si plusieurs visualiseurs supportent le mot clé (comme c’est le cas des
applications ayant recensé des visualiseurs pour WinHelp et HyperHelp sous
Windows et pour Man et Info sous Linux), le gestionnaire d’aide peut afficher
une boîte de sélection dans laquelle l’utilisateur de l’application choisit le
visualiseur d’aide à invoquer. Sinon, il affiche le premier système d’aide lui
ayant répondu.

Interfaces avec les systèmes d’aide


Le système d’aide permet la communication entre votre application et les
visualiseurs d’aide via une série d’interfaces. Ces interfaces sont toutes définies
dans HelpIntfs, qui contient également l’implémentation du gestionnaire d’aide.
ICustomHelpViewer prend en charge l’affichage de l’aide selon le mot clé fourni et
l’affichage d’un sommaire listant toute l’aide disponible dans un visualiseur
particulier.

7-30 Guide du développeur


Activation de l’aide dans les applications

IExtendedHelpViewer prend en charge l’affichage de l’aide selon le numéro de


contexte fourni et l’affichage des rubriques ; dans la majorité des systèmes d’aide,
les rubriques fonctionnent comme des mots clés de haut niveau (par exemple,
“IntToStr” pourrait être un mot clé dans le système d’aide, tandis que “Routines
de manipulation de chaînes” pourrait être le nom d’une rubrique).
ISpecialWinHelpViewer prend en charge la réponse aux messages WinHelp
spécialisés qu’une application s’exécutant sous Windows risque de recevoir et
qui ne sont pas facilement généralisables. En principe, seules les applications
opérant dans l’environnement Windows ont besoin d’implémenter cette interface
et, même alors, elle n’est nécessaire qu’aux applications faisant une forte
utilisation des messages WinHelp non standard.
IHelpManager fournit le mécanisme permettant au visualiseur d’aide de
communiquer avec le gestionnaire d’aide de l’application et demande un
supplément d’information. Un IHelpManager est obtenu au moment où le
visualiseur d’aide se recense lui-même.
IHelpSystem fournit le mécanisme permettant à TApplication de transmettre les
requêtes d’aide au système d’aide. TApplication obtient une instance d’un objet
qui implémente à la fois IHelpSystem et IHelpManager au chargement de
l’application et exporte cette instance en tant que propriété ; cela autorise
d’autres parties du code de l’application à traiter les requêtes d’aide directement
lorsque c’est possible.
IHelpSelector fournit le mécanisme permettant au système d’aide d’invoquer
l’interface utilisateur pour demander quel visualiseur d’aide doit être utilisé
lorsque plusieurs visualiseurs sont à même de gérer une requête d’aide et
d’afficher un sommaire. Cette capacité d’affichage n’est pas directement intégrée
au gestionnaire d’aide pour permettre l’utilisation du même code du gestionnaire
d’aide, quel que soit l’ensemble de widgets ou la bibliothèque de classes utilisé.

Implémentation de ICustomHelpViewer
L’interface ICustomHelpViewer contient trois types de méthodes : les méthodes
servant à communiquer au gestionnaire d’aide les informations du niveau
système (par exemple, des informations non liées à une requête d’aide
particulière) ; les méthodes servant à afficher l’aide en fonction du mot clé fourni
par le gestionnaire d’aide ; les méthodes servant à afficher le sommaire.

Communication avec le gestionnaire d’aide


ICustomHelpViewer fournit quatre fonctions servant à communiquer les
informations système au gestionnaire d’aide :
• GetViewerName
• NotifyID
• ShutDown
• SoftShutDown

Création d’applications, de composants et de bibliothèques 7-31


Activation de l’aide dans les applications

Le gestionnaire d’aide appelle ces fonctions dans les circonstances suivantes :


• AnsiString ICustomHelpViewer::GetViewerName() est appelée lorsque le
gestionnaire d’aide veut connaître le nom du visualiseur (par exemple, si
l’application doit afficher la liste des visualiseurs recensés). Cette information
est renvoyée via une chaîne et celle-ci doit être logiquement statique (c’est-à-
dire qu’elle ne peut pas être modifiée pendant que l’application s’exécute). Les
jeux de caractères multi-octets ne sont pas pris en charge.
• void ICustomHelpViewer::NotifyID(const int ViewerID) est appelée
immédiatement après le recensement pour fournir au visualiseur un cookie
qui l’identifie de manière unique. Cette information doit être conservée pour
une utilisation ultérieure ; si le visualiseur s’interrompt de son propre chef (et
non pas en réponse à une notification du gestionnaire d’aide), il doit fournir le
cookie identificateur au gestionnaire d’aide pour que celui-ci libère toutes les
références au visualiseur. (Ne pas réussir à fournir le cookie, ou en fournir un
mauvais, peut amener le gestionnaire d’aide à libérer les références au
mauvais visualiseur.)
• void ICustomHelpViewer::ShutDown() est appelée par le gestionnaire d’aide
pour signaler au visualiseur d’aide que le gestionnaire va s’interrompre et que
toutes les ressources allouées par le visualiseur doivent être libérées. Il est
conseillé de déléguer à cette méthode la libération de toutes les ressources.
• void ICustomHelpViewer::SoftShutDown() est appelée par le gestionnaire d’aide
pour demander au visualiseur d’aide de fermer toutes les manifestations
externes visibles du système d’aide (par exemple, les fenêtres affichant des
informations d’aide) sans décharger le visualiseur.

Demande d’informations au gestionnaire d’aide


Les visualiseurs d’aide communiquent avec le gestionnaire d’aide via l’interface
IHelpManager, une instance de celle-ci leur est renvoyée lorsqu’ils se recensent
auprès du gestionnaire d’aide. IHelpManager permet au visualiseur de
communiquer quatre choses :
• Une requête pour le handle de fenêtre du contrôle actif.
• Une requête pour le nom du fichier d’aide supposé contenir l’aide sur le
contrôle actif.
• Une requête pour le chemin d’accès à ce fichier.
• La notification que le visualiseur d’aide va s’interrompre lui-même en réponse
à autre chose qu’une demande issue du gestionnaire d’aide.
int IHelpManager::GetHandle() est appelée par le visualiseur d’aide s’il veut
connaître le handle du contrôle actif ; le résultat est un handle de fenêtre.
AnsiString IHelpManager::GetHandle() est appelée par le visualiseur d’aide s’il
veut connaître le nom du fichier d’aide supposé contenir l’aide sur le contrôle
actif.

7-32 Guide du développeur


Activation de l’aide dans les applications

void IHelpManager::Release() est appelée pour signaler au gestionnaire d’aide


qu’un visualiseur d’aide va se déconnecter. Elle ne doit jamais être appelée en
réponse à une requête via IHelpManager::ShutDown() ; elle sert à annoncer au
gestionnaire d’aide uniquement les déconnexions inattendues.

Affichage de l’aide basée sur un mot clé


Les requêtes d’aide adressées au visualiseur d’aide sont soit basées sur un mot
clé, auquel cas le visualiseur est chargé de fournir de l’aide en fonction d’une
chaîne particulière, soit basées sur un contexte, auquel cas le visualiseur est
chargé de fournir de l’aide en fonction d’un identificateur numérique particulier.
CLX Les contextes d’aide numériques sont la forme par défaut des requêtes d’aide
des applications s’exécutant sous Windows et utilisant le système WinHelp ; bien
que CLX les supporte, il n’est pas conseillé de les utiliser dans les applications
CLX car la majorité des systèmes d’aide sous Linux ne les comprennent pas.
Les implémentations de ICustomHelpViewer sont nécessaires pour prendre en
charge les requêtes basées sur les mots clés, les implémentations de
IExtendedHelpViewer sont nécessaires pour prendre en charge les requêtes basées
sur des contextes.
ICustomHelpViewer fournit trois méthodes pour traiter l’aide par mot clé :
• UnderstandsKeyword
• GetHelpStrings
• ShowHelp
int__fastcall ICustomHelpViewer::UnderstandsKeyword(const AnsiString HelpString)
est la première des trois méthodes appelées par le gestionnaire d’aide, qui
appellera chacun des visualiseurs d’aide recensés avec la même chaîne pour
demander si le visualiseur peut fournir de l’aide pour cette chaîne ; le visualiseur
est supposé répondre par un entier indiquant le nombre de pages d’aide
différentes qu’il peut afficher en réponse à cette demande. Le visualiseur peut
utiliser la méthode qu’il veut pour le déterminer — dans l’EDI, le visualiseur
HyperHelp maintient son propre index et effectue la recherche. Si le visualiseur
ne dispose pas d’aide sur le mot clé, il doit renvoyer zéro. Les nombres négatifs
sont interprétés comme zéro, mais ce comportement n’est pas garanti dans les
versions futures.
Classes::TStringList*__fastcall ICustomHelpViewer::GetHelpStrings(const AnsiString
HelpString)
est appelée par le gestionnaire d’aide si plusieurs visualiseurs peuvent fournir de
l’aide sur une rubrique. Le visualiseur doit renvoyer une TStringList, qui est
libérée par le gestionnaire d’aide. Les chaînes de la liste renvoyée doivent
correspondre aux pages disponibles pour le mot clé, mais les caractéristiques de
correspondance peuvent être déterminées par le visualiseur. Dans le cas du
visualiseur WinHelp sous Windows et d’HyperHelp sous Linux, la liste de
chaînes contient toujours une seule entrée. HyperHelp propose sa propre
indexation, et la dupliquer ailleurs serait inutile. Dans le cas du visualiseur de

Création d’applications, de composants et de bibliothèques 7-33


Activation de l’aide dans les applications

pages Man (Linux), la liste de chaînes contient plusieurs chaînes, une pour
chaque section du manuel contenant une page pour ce mot clé.
void__fastcall ICustomHelpViewer::ShowHelp(const AnsiString HelpString)
est appelée par le gestionnaire d’aide s’il a besoin que le visualiseur d’aide
affiche de l’aide sur un mot clé particulier. C’est le dernier appel de méthode de
l’opération ; elle n’est jamais appelée sauf si UnderstandsKeyword a été invoquée
au préalable.

Affichage des sommaires


ICustomHelpViewer fournit deux méthodes pour afficher les sommaires :
• CanShowTableOfContents
• ShowTableOfContents
Leur mode opératoire ressemble beaucoup à celui des requêtes d’aide par mot
clé : Le gestionnaire d’aide commence par interroger tous les visualiseurs d’aide
en appelant ICustomHelpViewer::CanShowTableOfContents() puis il invoque un
visualiseur donné en appelant ICustomHelpViewer::ShowTableOfContents().
Il est raisonnable pour un visualiseur de refuser de prendre en charge les
demandes de sommaires. C’est ce que fait, par exemple, le visualiseur de pages
Man car le concept de sommaire est trop éloigné de la façon dont fonctionnent
les pages Man ; le visualiseur HyperHelp, en revanche, supporte les sommaires
en passant la requête d’affichage du sommaire directement à HyperHelp sous
Linux et WinHelp sous Windows. Il n’est pas raisonnable, cependant, pour une
implémentation de ICustomHelpViewer de répondre aux requêtes
CanShowTableOfContents avec une valeur true et d’ignorer ensuite les requêtes
ShowTableOfContents.

Implémentation de IExtendedHelpViewer
ICustomHelpViewer est seule à fournir un support direct de l’aide par mot clé.
Certains systèmes d’aide (spécialement WinHelp) opèrent en associant un
nombre (appelé ID de contexte) aux mots clés, de manière interne au système
d’aide et donc de manière invisible pour l’application. De tels systèmes
nécessitent que l’application supporte l’aide par contexte, où l’application
invoque le système d’aide avec un nombre plutôt qu’une chaîne, et que le
système d’aide effectue la traduction du nombre.
Les applications écrites en CLX ou VCL peuvent communiquer avec les systèmes
utilisant l’aide contextuel, en étendant l’objet qui implémente ICustomHelpViewer
afin qu’il implémente également IExtendedHelpViewer. IExtendedHelpViewer prend
aussi en charge la communication avec les systèmes d’aide vous permettant
d’aller directement aux rubriques de haut niveau au lieu d’utiliser les recherches
par mot clé. Le visualiseur intégré WinHelp le fait automatiquement.
IExtendedHelpViewer expose quatre fonctions. Deux d’entre elles,
UnderstandsContext et DisplayHelpByContext, sont utilisées pour supporter l’aide

7-34 Guide du développeur


Activation de l’aide dans les applications

par contexte ; les deux autres, UnderstandsTopic et DisplayTopic, sont utilisées pour
supporter les rubriques.
Lorsque l’utilisateur d’une application appuie sur F1, le gestionnaire d’aide
appelle
int__fastcall IExtendedHelpViewer::UnderstandsContext(const int ContextID, AnsiString
HelpFileName)
et le contrôle actif prend en charge l’aide par contexte et non l’aide par mot clé.
Comme poure ICustomHelpViewer::UnderstandsKeyword(), le gestionnaire d’aide
interroge successivement tous les visualiseurs d’aide recensés. Mais, au contraire
de ICustomHelpViewer::UnderstandsKeyword(), si plusieurs visualiseurs gèrent un
contexte spécifié, c’est le premier visualiseur recensé et gérant le contexte qui est
invoqué.
Le gestionnaire d’aide appelle
void__fastcall IExtendedHelpViewer::DisplayHelpByContext(const int ContextID, AnsiString
HelpFileName)
après avoir consulté les visualiseurs d’aide recensés.
Les fonctions de support des rubriques se comportent de la même façon :
bool__fastcall IExtendedHelpViewer::UnderstandsTopic(const AnsiString Topic)
est utilisée pour demander aux visualiseurs d’aide s’ils supportent une rubrique ;
void__fastcall IExtendedHelpViewer::DisplayTopic(const AnsiString Topic)
est utilisée pour invoquer le premier visualiseur recensé indiquant qu’il peut
fournir de l’aide sur cette rubrique.

Implémentation de IHelpSelector
IHelpSelector est un compagnon de ICustomHelpViewer. Lorsque plusieurs
visualiseurs recensés peuvent assurer le support du mot clé, du contexte ou de la
rubrique spécifié, ou peuvent fournir un sommaire, le gestionnaire d’aide doit
faire un choix entre eux. Dans le cas des contextes ou des rubriques, le
gestionnaire d’aide sélectionne toujours le premier visualiseur d’aide prétendant
assurer le support. Dans le cas des mots clés ou des sommaires, le gestionnaire
d’aide, par défaut, sélectionne le premier visualiseur d’aide. Ce comportement
peut être redéfini par une application.
Pour supplanter la décision du gestionnaire d’aide, une application doit recenser
une classe fournissant une implémentation de l’interface IHelpSelector.
IHelpSelector exporte deux fonctions : SelectKeyword et TableOfContents. Les deux
acceptent comme argument un TStrings contenant, l’un à la suite de l’autre, soit
les correspondances possibles des mots clés, soit les noms des visualiseurs
pouvant fournir un sommaire. L’implémenteur est nécessaire pour renvoyer
l’indice (dans le TStringList) représentant la chaîne sélectionnée, puis le
TStringList est libéré par le gestionnaire d’aide
Remarque Le gestionnaire d’aide risque de se tromper si les chaînes sont réarrangées ; il est
conseillé que les implémenteurs de IHelpSelector ne le fassent pas. Le système

Création d’applications, de composants et de bibliothèques 7-35


Activation de l’aide dans les applications

d’aide ne supporte qu’un seul HelpSelector ; lorsque de nouveaux sélecteurs sont


recensés, tout sélecteur existant préalablement est déconnecté.

Recensement des objets du système d’aide


Pour que le gestionnaire d’aide communique avec eux, les objets implémentant
ICustomHelpViewer, IExtendedHelpViewer, ISpecialWinHelpViewer et IHelpSelector
doivent se recenser auprès du gestionnaire d’aide.
Pour recenser les objets du système d’aide auprès du gestionnaire d’aide, il
vous faut :
• Recenser le visualiseur d’aide.
• Recenser le sélecteur d’aide.

Recensement des visualiseurs d’aide


L’unité contenant l’implémentation de l’objet doit utiliser HelpIntfs. Une instance
de l’objet doit être déclarée dans le fichier en-tête de l’unité d’implémentation.
L’unité d’implémentation doit contenir une directive pragma startup qui appelle
une méthode affectant la variable d’instance et la transmet à la fonction
RegisterViewer. RegisterViewer est une fonction simple, exportée par HelpIntfs.pas,
qui prend un ICustomHelpViewer en argument et renvoie un IHelpManager. Le
IHelpManager doit être enregistré pour une utilisation ultérieure.
Le fichier .cpp correspondant contient le code qui recense l’interface. Pour
l’interface décrite ci-dessus, le code de recensement à la forme suivante :
void InitServices()
{
THelpImplementor GlobalClass;
Global = dynamic_cast<ICustomHelpViewer*>(GlobalClass);
Global->AddRef;
HelpIntfs::RegisterViewer(Global, GlobalClass->Manager);
}
#pragma startup InitServices
Remarque Le gestionnaire d’aide doit être libéré dans le destructeur de l’objet GlobalClass
s’il n’a pas déjà été libéré.

Recensement des sélecteurs d’aide


L’unité contenant l’implémentation de l’objet doit utiliser Forms dans la VCL ou
QForms dans la CLX. Une instance de l’objet doit être déclarée dans le fichier
.cpp de l’unité d’implémentation.
L’unité d’implémentation doit recenser le sélecteur d’aide via la propriété
HelpSystem de l’objet global Application :
Application->HelpSystem->AssignHelpSelector(myHelpSelectorInstance)
Cette procédure ne renvoie pas de valeur.

7-36 Guide du développeur


Utilisation de l’aide dans une application VCL

Utilisation de l’aide dans une application VCL


Les sections suivantes expliquent comment utiliser l’aide dans une application
VCL.
• Comment TApplication traite-il l’aide VCL
• Comment les contrôles VCL traitent-ils l’aide
• Appel direct à un système d’aide
• Utilisation de IHelpSystem

Comment TApplication traite-il l’aide VCL


TApplication dans la VCL fournit quatre méthodes accessibles depuis le code de
l’application :

Tableau 7.5 Méthodes d’aide de TApplication


Méthode Description
HelpCommand Transmet HELP_COMMAND, de style aide Windows, à WinHelp. Les
demandes d’aide transmises par le biais de ce mécanisme sont passées
uniquement aux implémentations de IspecialWinHelpViewer.
HelpContext Invoque le système d’aide en utilisant une requête par contexte.
HelpKeyword Invoque le système d’aide en utilisant une requête par mot clé.
HelpJump Demande l’affichage d’une rubrique particulière.

Les quatre fonctions prennent les données qui leurs sont transmises et les font
suivre via une donnée membre de TApplication qui représente le système d’aide.
Cette donnée membre est directement accessible via la propriété HelpSystem.

Comment les contrôles VCL traitent-ils l’aide


Tous les contrôles VCL dérivant de TControl exposent plusieurs propriétés qui
sont utilisées par le système d’aide : HelpType, HelpContext et HelpKeyword.
La propriété HelpType contient une instance d’un type énuméré qui détermine si
le concepteur du contrôle a prévu de fournir l’aide par mot clé ou par contexte.
Si HelpType est définie par htKeyword, le système d’aide s’attend à ce que le
contrôle utilise l’aide par mot clé et il examine uniquement le contenu de la
propriété HelpKeyword. En revanche, si HelpType est définie par htContext, le
système d’aide s’attend à ce que le contrôle utilise l’aide par contexte et il
examine uniquement le contenu de la propriété HelpContext.
En plus des propriétés, les contrôles exposent une seule méthode, InvokeHelp, qui
peut être appelée pour transmettre une requête au système d’aide. Elle ne prend
pas de paramètre et appelle dans l’objet global Application les méthodes qui
correspondent au type d’aide supporté par le contrôle.
Les messages d’aide sont automatiquement invoqués lors de l’appui sur la
touche F1 car la méthode KeyDown de TWinControl appelle InvokeHelp.

Création d’applications, de composants et de bibliothèques 7-37


Utilisation de l’aide dans une application CLX

Utilisation de l’aide dans une application CLX


Les sections suivantes expliquent comment utiliser l’aide dans une application
CLX.
• Comment TApplication traite-il l’aide CLX
• Comment les contrôles CLX traitent-ils l’aide
• Appel direct à un système d’aide
• Utilisation de IHelpSystem

Comment TApplication traite-il l’aide CLX


TApplication dans CLX fournit deux méthodes accessibles depuis le code de
l’application :
• ContextHelp, qui invoque le système d’aide en utilisant une requête par
contexte
• KeywordHelp, qui invoque le système d’aide en utilisant une requête par
mot clé
Les deux fonctions prennent en argument le contexte ou le mot clé, et fait suivre
la requête à une donnée membre de TApplication, qui représente le système
d’aide. Cette donnée membre est directement accessible via la propriété en
lecture seule HelpSystem.

Comment les contrôles CLX traitent-ils l’aide


Tous les contrôles dérivant de TControl exposent quatre propriétés qui sont
utilisées par le système d’aide : HelpType, HelpFile, HelpContext et HelpKeyword.
HelpFile est censée contenir le nom du fichier où se trouve l’aide du contrôle ; si
l’aide se trouve dans un système d’aide externe ne reconnaissant pas les noms
de fichiers (par exemple, le système des pages Man), la propriété doit être laissée
vierge.
La propriété HelpType contient une instance d’un type énuméré qui détermine si
le concepteur du contrôle a prévu de fournir l’aide par mot clé ou par contexte ;
les deux autres propriétés lui sont liées. Si HelpType est définie par htKeyword, le
système d’aide s’attend à ce que le contrôle utilise l’aide par mot clé et il
examine uniquement le contenu de la propriété HelpKeyword. En revanche, si
HelpType est définie par htContext, le système d’aide s’attend à ce que le contrôle
utilise l’aide par contexte et il examine uniquement le contenu de la propriété
HelpContext.
En plus des propriétés, les contrôles exposent une seule méthode, InvokeHelp, qui
peut être appelée pour transmettre une requête au système d’aide. Elle ne prend
pas de paramètre et appelle dans l’objet global Application les méthodes qui
correspondent au type d’aide supporté par le contrôle.

7-38 Guide du développeur


Appel direct à un système d’aide

Les messages d’aide sont automatiquement invoqués lors de l’appui sur la


touche F1 car la méthode KeyDown de TWidgetControl appelle InvokeHelp.

Appel direct à un système d’aide


Pour les fonctionnalités des systèmes d’aide non fournis par la VCL ou par CLX,
TApplication fournit une propriété, accessible en lecture seulement, qui donne un
accès direct au système d’aide. Cette propriété est une instance d’une
implémentation de l’interface IHelpSystem. IHelpSystem et IHelpManager sont
implémentées par le même objet, mais une interface est utilisée pour permettre à
l’application de communiquer avec le gestionnaire d’aide, et l’autre est utilisée
pour permettre aux visualiseurs d’aide de communiquer avec le gestionnaire
d’aide.

Utilisation de IHelpSystem
IHelpSystem permet à l’application VCL ou CLX de réaliser trois choses :
• Fournit au gestionnaire d’aide les informations de chemin d’accès.
• Fournit un nouveau sélecteur d’aide.
• Demande au gestionnaire d’aide d’afficher l’aide.
Assigner un sélecteur d’aide permet au gestionnaire d’aide de déléguer la prise
de décision au cas où plusieurs systèmes d’aide externes peuvent apporter l’aide
pour le même mot clé. Pour plus d’informations, voir la section “Implémentation
de IHelpSelector” à la page 7-35.
IHelpSystem exporte quatre procédure et une fonction utilisées pour demander au
gestionnaire d’aide d’afficher l’aide :
• ShowHelp
• ShowContextHelp
• ShowTopicHelp
• ShowTableOfContents
• Hook
Hook est entièrement destinée à la compatibilité WinHelp et ne doit pas être
utilisée dans une application CLX ; elle permet le traitement des messages
WM_HELP qui ne peuvent pas être directement traduits en requêtes d’aide basée
sur un mot clé, un contexte ou une rubrique. Les autres méthodes prennent
chacune deux arguments : le mot clé, l’ID de contexte ou la rubrique pour lequel
l’aide est demandée, et le fichier d’aide dans lequel on s’attend à la trouver.
En général, sauf si vous demandez une aide par rubrique, il est aussi efficace et
plus clair de transmettre les requêtes au gestionnaire d’aide via la méthode
InvokeHelp de votre contrôle.

Création d’applications, de composants et de bibliothèques 7-39


Personnalisation du système d’aide de l’EDI

Personnalisation du système d’aide de l’EDI


L’EDI de C++Builder supporte les visualiseurs d’aide multiples exactement
comme le fait une application VCL ou CLX : il délègue les demandes d’aide au
gestionnaire d’aide, qui les fait suivre aux visualiseurs d’aide recensés. L’EDI
utilise le même visualiseur d’aide WinHelpViewer que VCL.
Pour installer un nouveau visualiseur d’aide dans l’EDI, faites exactement ce que
vous feriez dans une application VLC ou CLX à une différence près. Vous
écrivez un objet qui implémente ICustomHelpViewer (et, éventuellement,
IExtendedHelpViewer) pour faire suivre les requêtes d’aide au visualiseur externe
de votre choix, et vous recensez le ICustomHelpViewer avec l’EDI.
Pour recenser un visualiseur d’aide personnalisé avec l’EDI
1 Assurez-vous que l’unité implémentant le visualiseur d’aide contient
HelpIntfs.cpp.
2 Construisez l’unité dans un paquet de conception recensé avec l’EDI, et
construisez le paquet en activant l’option Paquets d’exécution. (C’est
nécessaire pour garantir que l’instance du gestionnaire d’aide utilisée par
l’unité est la même que celle utilisée par l’EDI.)
3 Assurez-vous que le visualiseur d’aide existe comme instance globale à
l’intérieur de l’unité.
4 Dans la fonction d’initialisation bloquée par #pragma startup, assurez-vous
que l’instance est transmise à la fonction RegisterHelpViewer.

7-40 Guide du développeur


Chapitre

Conception de l’interface utilisateur


Chapitre 8
8
des applications
Lorsque vous ouvrez C++Builder ou créez un nouveau projet, une fiche vierge
s’affiche à l’écran. Vous concevez l’interface utilisateur de l’application en plaçant
et disposant des composants visuels de la palette des composants (fenêtres,
menus ou boîtes de dialogues) sur la fiche.
Une fois un composant visuel dans la fiche, vous pouvez modifier sa position, sa
taille et d’autres propriétés de conception et coder ses gestionnaires
d’événements. C++Builder prend en charge les détails sous-jacents de la
programmation.
Les sections suivantes décrivent les principales opérations de conception de
l’interface utilisateur : la manipulation des fiches, la création de modèles de
composants, l’ajout de boîtes de dialogue et l’organisation d’actions pour les
menus et les barres d’outils.

Contrôle du comportement de l’application


TApplication, TScreen et TForm sont les classes qui constituent la base de toutes
les applications C++Builder en contrôlant le comportement de votre projet. La
classe TApplication sert de fondation à une application en fournissant les
propriétés et les méthodes qui encapsulent le comportement d’un programme
standard. La classe TScreen est utilisée à l’exécution pour gérer les fiches et les
modules de données chargés, ainsi que pour maintenir des informations
spécifiques au système comme la résolution écran ou les fontes utilisables à
l’affichage. Des instances de la classe TForm servent à construire l’interface
utilisateur de votre application. Les fenêtres et les boîtes de dialogue d’une
application sont basées sur TForm.

Conception de l’interface utilisateur des applications 8-1


Paramétrage des fiches

Manipulation de l’application
La variable globale Application de type TApplication se trouve dans chaque
application utilisant la VCL ou la CLX. Application encapsule l’application et
propose de nombreux services fonctionnant en arrière-plan du programme. Ainsi,
Application gère la manière d’appeler un fichier d’aide depuis les menus de votre
programme. La compréhension du fonctionnement de TApplication est plus
importante pour le concepteur de composants que pour le développeur
d’applications autonomes, mais vous devez définir les options gérées par
Application dans la page Application de la boîte de dialogue Options de projet
(Projet|Options) quand vous créez un projet.
De plus, Application reçoit de nombreux événements qui s’appliquent à
l’application dans son ensemble. Par exemple, l’événement OnActivate vous
permet de réaliser des actions au démarrage de l’application, l’événement OnIdle
vous permet d’exécuter des traitements en arrière-plan lorsque l’application n’est
pas occupée, l’événement OnMessage vous permet d’intercepter les messages
Windows (sous Windows uniquement), l’événement OnEvent vous permet
d’intercepter des événements, etc. Bien que vous ne puissiez pas utiliser l’EDI
pour examiner les propriétés et les événements de la variable globale Application,
un autre composant, TApplicationEvents, intercepte les événements et vous permet
de fournir les gestionnaires d’événements à l’aide de l’EDI.

Gestion de l’écran
Une variable globale de type TScreen, appelée Screen, est créée lors de la création
d’un projet. Screen encapsule l’état de l’écran dans lequel l’application s’exécute.
Parmi les fonctions imparties à Screen, il y a
• La gestion de l’aspect du curseur.
• La taille de la fenêtre dans laquelle s’exécute l’application.
• La liste des fontes disponibles pour le périphérique écran.
• Divers aspects de l’écran (Windows uniquement).
Si votre application Windows s’exécute sur plusieurs moniteurs, Screen gère une
liste des moniteurs et leurs dimensions afin que vous puissiez effectivement
gérer la disposition de l’interface utilisateur.
Lors de l’utilisation de la CLX pour la programmation multiplate-forme, le
comportement par défaut est le suivant : les applications créent un composant
écran en fonction des informations concernant le périphérique d’écran en cours
et l’assigne à Screen.

Paramétrage des fiches


TForm est la classe essentielle dans la création d’applications disposant d’une
interface utilisateur graphique. Lorsque vous ouvrez C++Builder, ce qui affiche
un projet par défaut, ou lorsque vous créez un nouveau projet, une fiche est
affichée pour vous permettre de démarrer la conception de votre interface
utilisateur.

8-2 Guide du développeur


Paramétrage des fiches

Utilisation de la fiche principale


La première fiche créée et enregistrée dans un projet devient, par défaut, la fiche
principale du projet : c’est la première fiche créée à l’exécution. Quand vous
ajoutez d’autres fiches dans vos projets, vous pouvez en choisir une autre pour
servir de fiche principale à votre application. Par ailleurs, faire d’une fiche la
fiche principale est le moyen le plus simple de la tester à l’exécution : à moins de
changer explicitement l’ordre de création, la fiche principale est la première fiche
affichée lors de l’exécution d’une application.
Pour changer la fiche principale d’un projet :
1 Choisissez Projet|Options et sélectionnez la page Fiche.
2 Dans la boîte liste Fiche principale, sélectionnez la fiche à utiliser comme fiche
principale du projet et choisissez OK.
Désormais, si vous exécutez votre application, la fiche choisie comme fiche
principale s’affiche.

Cacher la fiche principale


Vous pouvez empêcher l’affichage de la fiche principale lors du démarrage de
l’application. Pour ce faire, vous devez utiliser la variable globale Application
(décrite à la section “Manipulation de l’application” à la page 8-2).
Pour masquer la fiche principale au démarrage :
1 Choisissez Projet|Voir le source pour afficher le fichier du projet principal.
2 Ajoutez la ligne suivante après l’appel de Application->CreateForm() et avant
l’appel de Application->Run().
Application->ShowMainForm = false;
3 En utilisant l’inspecteur d’objets, définissez la propriété Visible de votre fiche
principale par false.

Ajout de fiches
Pour ajouter une fiche à votre projet, sélectionnez Fichier|Nouveau|Fiche.
Toutes les fiches d’un projet ainsi que les unités correspondantes sont affichées
dans le gestionnaire de projet (Voir|Gestionnaire de projet) et vous pouvez
afficher la liste des fiches en choisissant Voir|Fiches.

Liaison de fiches
L’ajout d’une fiche au projet ajoute au fichier projet une référence à cette fiche
mais pas aux autres unités du projet. Avant d’écrire du code faisant référence à
la nouvelle fiche, vous devez ajouter une référence à cette fiche dans les fichiers
unité des fiches y faisant référence. Cela s’appelle la liaison de fiche.

Conception de l’interface utilisateur des applications 8-3


Paramétrage des fiches

La liaison de fiche est fréquemment utilisée pour donner accès aux composants
contenus dans une autre fiche. Par exemple, la liaison de fiche est souvent
employée pour permettre à une fiche contenant des composants orientés données
de se connecter aux composants d’accès aux données d’un module de données.
Pour lier une fiche à une autre fiche :
1 Sélectionnez la fiche qui fait référence à une autre.
2 Choisissez Fichier|Inclure l’en-tête d’unité.
3 Sélectionnez le nom de l’unité de la fiche qui doit être référencée.
4 Choisissez OK.
La liaison d’une fiche à une autre se traduit simplement par le fait qu’une fiche
contient l’en-tête de l’unité de l’autre fiche. Par conséquent, la fiche liée et ses
composants se trouvent maintenant dans la portée de l’autre fiche.

Gestion de la disposition
A son niveau le plus élémentaire, vous contrôlez l’organisation de votre interface
utilisateur par la manière de disposer les contrôles dans les fiches. Le choix des
emplacements est reflété par les propriétés Top, Left, Width et Height des
contrôles. Vous pouvez modifier ces valeurs à l’exécution afin de modifier la
position ou la taille des contrôles dans les fiches.
Les contrôles disposent de nombreuses autres propriétés qui leur permettent de
s’adapter automatiquement à leur contenu ou à leur conteneur. Cela vous permet
d’organiser les fiches de telle manière que les différents éléments forment un
tout unifié.
Deux propriétés contrôlent la position et la taille d’un contrôle relativement à
celle de son parent. La propriété Align vous permet d’obliger un contrôle à
s’adapter exactement à un côté spécifié de son parent ou à occuper toute la place
disponible de la zone client du parent une fois les autres contrôles alignés.
Quand le parent est redimensionné, les contrôles alignés sont automatiquement
redimensionnés et restent positionnés le long d’un côté donné du parent.
Si vous voulez qu’un contrôle reste positionné relativement à un côté particulier
de son parent sans toucher ce bord ou être redimensionné pour occuper la
totalité du côté, vous pouvez utiliser la propriété Anchors.
Pour vous assurer qu’un contrôle ne devient ni trop grand ni trop petit, vous
pouvez utiliser la propriété Constraints. Constraints vous permet de spécifier la
hauteur maximum, la hauteur minimum, la largeur maximum et la largeur
minimum du contrôle. Initialisez ces valeurs afin de limiter la taille (en pixels)
de la hauteur et de la largeur du contrôle. Ainsi, en initialisant les contraintes
MinWidth et MinHeight d’un objet conteneur, vous êtes certain que ses objets
enfant sont toujours visibles.
La valeur de Constraints se propage le long de la hiérarchie parent/enfant de
telle manière que la taille d’un objet peut être restreinte car il contient des
enfants alignés qui ont des contraintes de taille. Constraints peut également
empêcher un contrôle d’être mis à l’échelle dans une dimension particulière lors
de l’appel de sa méthode ChangeScale.

8-4 Guide du développeur


Utilisation des fiches

TControl introduit un événement protégé, OnConstrainedResize, de type


TConstrainedResizeEvent :
void __fastcall (__closure *TConstrainedResizeEvent)(System::TObject* Sender, int
&MinWidth, int &MinHeight, int &MaxWidth, int &MaxHeight);
Cet événement vous permet de surcharger les contraintes de taille lors d’une
tentative de redimensionnement du contrôle. Les valeurs des contraintes sont
transmises comme paramètres var, elles peuvent donc être modifiées dans le
gestionnaire d’événement. OnConstrainedResize est publié pour les objets
conteneur (TForm, TScrollBox, TControlBar et TPanel). De plus, les concepteurs de
composants peuvent utiliser ou publier cet événement dans tout descendant de
TControl.
Les contrôles dont le contenu peut changer de taille ont une propriété AutoSize
qui force le contrôle à adapter sa taille à l’objet ou à la fonte qu’il contient.

Utilisation des fiches


Quand vous créez une fiche C++Builder dans l’EDI, C++Builder crée
automatiquement la fiche en mémoire en ajoutant du code au point d’entrée
principal de votre application. C’est généralement le comportement souhaité et
vous n’avez donc rien à y changer. Ainsi, la fiche principale existe pour toute la
durée du programme, il est donc peu probable que vous changiez le
comportement par défaut de C++Builder quand vous créez la fiche de votre
fenêtre principale.
Néanmoins, il n’est pas toujours nécessaire de conserver en mémoire toutes les
fiches de votre application pour toute la durée de l’exécution du programme. Si
vous ne souhaitez pas avoir tout le temps en mémoire toutes les boîtes de
dialogue de votre application, vous pouvez les créer dynamiquement quand vous
voulez les voir apparaître.
Une fiche peut être modale ou non modale. Les fiches modales sont des fiches
avec lesquelles l’utilisateur doit interagir avant de pouvoir passer à une autre
fiche (par exemple une boîte de dialogue impose une saisie de l’utilisateur). Les
fiches non modales sont des fenêtres visibles tant qu’elles ne sont pas masquées
par une autre fenêtre, fermées ou réduites par l’utilisateur.

Contrôle du stockage en mémoire des fiches


Par défaut, C++Builder crée automatiquement en mémoire la fiche principale de
l’application en ajoutant le code suivant au point d’entrée principal de
l’application :
Application ->CreateForm(__classid(TForm1), &Form1);
Cette fonction crée une variable globale portant le même nom que la fiche. Ainsi,
chaque fiche d’une application a une variable globale associée. Cette variable est
un pointeur sur une instance de la classe de la fiche et sert à désigner la fiche
durant l’exécution de l’application. Tout fichier code source (.cpp) qui inclut le

Conception de l’interface utilisateur des applications 8-5


Utilisation des fiches

fichier en-tête (.h) de la fiche peut accéder à la fiche par l’intermédiaire de cette
variable.
Comme la fiche est ajoutée au point d’entrée principal de l’application, elle
apparaît lorsque le programme est exécuté et existe en mémoire pour la durée de
l’application.

Affichage d’une fiche créée automatiquement


Il est possible de créer une fiche au démarrage, mais de ne l’afficher que plus
tard dans l’exécution du programme. Les gestionnaires d’événements de la fiche
utilisent la méthode ShowModal pour afficher une fiche déjà chargée en mémoire :
void __fastcall TMainMForm::FirstButtonClick(TObject *Sender)
{
ResultsForm->ShowModal();
}
Dans ce cas, comme la fiche est déjà en mémoire, il n’est pas nécessaire de créer
une autre instance ou de détruire cette instance.

Création dynamique de fiche


Toutes les fiches de votre application n’ont pas besoin d’être en mémoire
simultanément. Pour réduire la quantité de mémoire nécessaire au chargement
de l’application, vous pouvez créer certaines fiches uniquement quand vous en
avez besoin. Ainsi, une boîte de dialogue n’a besoin d’être en mémoire que
pendant le temps où l’utilisateur interagit avec elle.
Pour spécifier dans l’EDI que la fiche doit être créée à un autre moment pendant
l’exécution, procédez de la manière suivante :
1 Sélectionnez Fichier|Nouveau|Fiche dans le menu principal afin d’afficher la
nouvelle fiche.
2 Retirez la fiche de la liste Fiches créées automatiquement dans la page Fiches
de Projet|Options.
Cela supprime l’appel de la fiche. Vous pouvez également retirer
manuellement la ligne suivante au point d’entrée principal du programme :
Application->CreateForm(__classid(TResultsForm), &ResultsForm);
3 Appelez la fiche au moment souhaité en utilisant la méthode Show de la fiche
si la fiche est non modale ou la méthode ShowModal si la fiche est modale.
Un gestionnaire d’événement de la fiche principale doit créer et détruire une
instance de la fiche résultat. Une manière d’appeler cette fiche consiste à utiliser
la variable globale comme dans le code suivant. Remarquez que ResultsForm
étant une fiche modale, le gestionnaire utilise la méthode ShowModal :
void __fastcall TMainMForm::FirstButtonClick(TObject *Sender)
{
ResultsForm = new TResultsForm(this);
ResultsForm->ShowModal();
delete ResultsForm;
}

8-6 Guide du développeur


Utilisation des fiches

Dans cet exemple, le gestionnaire d’événement supprime la fiche après sa


fermeture, la fiche doit donc être recréée en utilisant new si vous avez besoin de
ResultsForm ailleurs dans l’application. Si la fiche était affichée en utilisant Show,
vous ne pourriez la supprimer dans le gestionnaire d’événement car, après
l’appel de Show, l’exécution du code du gestionnaire se poursuit alors que la
fiche est toujours ouverte.
Remarque Si vous créez une fiche en utilisant l’opérateur new, assurez-vous que la fiche
n’apparaît pas dans la liste Fiches créées automatiquement de la page Fiches de
la boîte de dialogue Options de projet. En effet, si vous créez une nouvelle fiche
sans avoir détruit la fiche de même nom dans la liste, C++Builder crée la fiche
au démarrage et le gestionnaire d’événement crée une nouvelle instance de la
fiche, ce qui remplace la référence à l’instance auto-créée. L’instance auto-créée
existe toujours mais l’application n’y a plus accès. A la fin du gestionnaire
d’événement, la variable globale ne pointe plus sur une fiche valide. Toute
tentative de déréférencer la variable globale entraînera probablement le blocage
de l’application.

Création de fiches non modales comme fenêtres


Vous devez vous assurer que les variables désignant des fiches non modales
existent tant que la fiche est utilisée. Cela signifie que ces variables doivent avoir
une portée globale. Le plus souvent, vous utiliserez la variable globale
référençant la fiche qui a été créée quand vous avez ajouté la fiche (le nom de
variable qui correspond à la valeur de la propriété Name de la fiche). Si votre
application a besoin d’autres instances de la fiche, déclarez des variables globales
distinctes (de type pointeur sur la classe fiche) pour chaque instance.

Création d’une instance de fiche en utilisant une variable locale


Un moyen fiable de créer une seule instance d’une fiche modale consiste à utiliser
une variable locale du gestionnaire d’événement comme référence à la nouvelle
instance. Si une variable locale est employée, il importe peu que ResultsForm soit
ou non auto-créée. Le code du gestionnaire d’événement ne fait pas référence à
la variable fiche globale. Par exemple :
void __fastcall TMainMForm::FirstButtonClick(TObject *Sender)
{
TResultsForm *rf = new TResultsForm(this);// rf est l’instance locale de la fiche
rf->ShowModal();
delete rf; // fiche détruite de manière fiable
}
Remarquez que l’instance globale de la fiche n’est jamais utilisée dans cette
version du gestionnaire d’événement.
Habituellement, les applications utilisent les instances globales des fiches.
Cependant, si vous avez besoin d’une nouvelle instance d’une fiche modale alors
que vous utilisez cette fiche dans une portion réduite de votre application (par
exemple dans une seule fonction), une instance locale est normalement le moyen
le plus rapide et le plus fiable de manipuler la fiche.

Conception de l’interface utilisateur des applications 8-7


Utilisation des fiches

Bien entendu, vous ne pouvez pas utiliser de variables locales pour les fiches
non modales dans les gestionnaires d’événements car elles doivent avoir une
portée globale pour garantir que la fiche existe aussi longtemps qu’elle est
utilisée. Show rend la main dès que la fiche est ouverte, donc si vous utilisez une
variable locale, la variable locale sort de portée immédiatement.

Transfert de paramètres supplémentaires aux fiches


Généralement, vous créez les fiches de votre application en utilisant l’EDI.
Quand elle est créée ainsi, la fiche a un constructeur qui prend un argument,
Owner, qui est un pointeur sur le propriétaire de la fiche créée. (Le propriétaire
est l’objet application ou l’objet fiche appelant.) Owner peut avoir la valeur
NULL.
Pour transmettre d’autres arguments à la fiche, créez un constructeur différent et
instanciez la fiche en utilisant l’opérateur new. La classe fiche exemple suivante
utilise un constructeur supplémentaire proposant le paramètre supplémentaire
whichButton. Il faut ajouter manuellement ce nouveau constructeur à la fiche.
class TResultsForm : public TForm
{
__published: // Composants gérés par l’EDI
TLabel *ResultsLabel;
TButton *OKButton;
void __fastcall OKButtonClick(TObject *Sender);
private: // Déclarations de l’utilisateur
public: // Déclarations de l’utilisateur
virtual __fastcall TResultsForm(TComponent* Owner);
virtual __fastcall TResultsForm(int whichButton, TComponent* Owner);
};
Voici le code, créé manuellement, de ce constructeur qui passe le paramètre
supplémentaire whichButton. Ce constructeur utilise le paramètre whichButton
pour initialiser la propriété Caption d’un contrôle Label de la fiche.
void__fastcall TResultsForm::TResultsForm(int whichButton, TComponent* Owner)
: TForm(Owner)
{
switch (whichButton) {
case 1:
ResultsLabel->Caption = "Vous avez choisi le premier bouton!";
break;
case 2:
ResultsLabel->Caption = "Vous avez choisi le second bouton!";
break;
case 3:
ResultsLabel->Caption = "Vous avez choisi le troisième bouton!";
}
}
Quand vous créez une instance d’une fiche disposant de plusieurs constructeurs,
vous pouvez sélectionner le constructeur le mieux adapté à vos besoins.

8-8 Guide du développeur


Utilisation des fiches

Par exemple, le gestionnaire OnClick suivant d’un bouton de la fiche crée une
instance de TResultsForm en utilisant le paramètre supplémentaire :
void __fastcall TMainMForm::SecondButtonClick(TObject *Sender)
{
TResultsForm *rf = new TResultsForm(2, this);
rf->ShowModal();
delete rf;
}

Récupération des données des fiches


La plupart des applications réelles utilisent plusieurs fiches. Bien souvent, il est
nécessaire de transmettre des informations entre ces différentes fiches. Il est
possible de transmettre des informations à une fiche sous la forme des
paramètres du constructeur de la fiche destination ou en affectant des valeurs
aux propriétés de la fiche. La méthode à utiliser pour obtenir des informations
d’une fiche change selon que la fiche est ou non modale.

Récupération de données dans les fiches non modales


Il est facile d’extraire des informations de fiches non modales en appelant des
fonctions membre publiques de la fiche ou en interrogeant ses propriétés. Soit,
par exemple, une application contenant une fiche non modale appelée ColorForm
qui contient une boîte liste appelée ColorListBox contenant une liste de couleurs
(“Rouge”, “Vert”, “Bleu”, etc.). Le nom de couleur sélectionné dans ColorListBox
est automatiquement stocké dans une propriété appelée CurrentColor à chaque
fois que l’utilisateur sélectionne une nouvelle couleur. La déclaration de classe
pour la fiche est la suivante :
class TColorForm : public TForm
{
__published: // Composants gérés par l’EDI
TListBox *ColorListBox;
void __fastcall ColorListBoxClick(TObject *Sender);
private: // Déclarations de l’utilisateur
String getColor();
void setColor(String);
String curColor;
public: // Déclarations de l’utilisateur
virtual __fastcall TColorForm(TComponent* Owner);
__property String CurrentColor = {read=getColor, write=setColor};
};
Le gestionnaire d’événement OnClick de la boîte liste, ColorListBoxClick, initialise
la valeur de la propriété CurrentColor à chaque fois qu’un nouvel élément est
sélectionné. Le gestionnaire d’événement obtient la chaîne dans la boîte liste qui
contient le nom de couleur et l’affecte à CurrentColor. La propriété CurrentColor
utilise la fonction d’affectation, setColor, pour stocker la valeur réelle de la
propriété dans la donnée membre privée curColor :
void __fastcall TColorForm::ColorListBoxClick(TObject *Sender)
{

Conception de l’interface utilisateur des applications 8-9


Utilisation des fiches

int index = ColorListBox->ItemIndex;


if (index >= 0) {// vérifier qu’une couleur est sélectionnée
CurrentColor = ColorListBox->Items->Strings[index];
}
else // Pas de couleur sélectionnée
CurrentColor = "";
}
//---------------------------------------------------------------------
void TColorForm::setColor(String s)
{
curColor = s;
}
Supposons maintenant qu’une autre fiche de l’application, appelée ResultsForm, a
besoin de connaître la couleur actuellement sélectionnée dans ColorForm à chaque
fois qu’un bouton (nommé UpdateButton) de ResultsForm est choisi. Le
gestionnaire d’événement OnClick de UpdateButton doit avoir la forme suivante :
void __fastcall TResultsForm::UpdateButtonClick(TObject *Sender)
{
if (ColorForm) { // Vérifier l’existence de ColorForm
String s = ColorForm->CurrentColor;
// faire quelque chose avec la chaîne nom de la couleur
}
}
Le gestionnaire d’événement commence par vérifier que ColorForm existe en
vérifiant si leur pointeur est NULL. Ensuite, il obtient la valeur de la propriété
CurrentColor de ColorForm. La lecture de la propriété CurrentColor appelle sa
fonction de lecture getColor qui contient le code suivant :
String TColorForm::getColor()
{
return curColor;
}
En procédant autrement, si la fonction getColor de ColorForm est publique, une
autre fiche peut obtenir la couleur en cours sans utiliser la propriété CurrentColor
(par exemple, String s = ColorForm->getColor();). En fait, rien n’empêche l’autre
fiche d’obtenir la couleur sélectionnée dans ColorForm en examinant directement
la valeur sélectionnée dans la boîte liste :
String s = ColorListBox->Items->Strings[ColorListBox->ItemIndex];
Néanmoins, l’utilisation d’une propriété rend l’interface avec ColorForm très claire
et simple. Tout ce qu’une fiche a besoin de savoir sur ColorForm, c’est comment
récupérer la valeur de CurrentColor.

Récupération de données dans les fiches modales


Tout comme les fiches non modales, les fiches modales contiennent souvent des
informations nécessaires à d’autres fiches. Dans le cas de figure la plus classique,
une fiche A lance la fiche modale B. Lors de la fermeture de B, la fiche A a
besoin de savoir ce que l’utilisateur a fait dans la fiche B pour décider comment
poursuivre les traitements de la fiche A. Si la fiche B est toujours en mémoire,

8-10 Guide du développeur


Utilisation des fiches

il est possible de l’interroger via ses propriétés et ses fonctions membres tout
comme les fiches non modales de l’exemple précédent. Mais comment faire si la
fiche B est retirée de la mémoire une fois fermée ? Comme une fiche ne renvoie
pas explicitement de valeur, il est nécessaire de préserver les informations
importantes de la fiche avant de la détruire.
Pour illustrer cette manière de procéder, considérez une version modifiée de la
fiche ColorForm conçue comme une fiche modale. Sa classe est déclarée de la
manière suivante :
class TColorForm : public TForm
{
__published: // Composants gérés par l’EDI
TListBox *ColorListBox;
TButton *SelectButton;
TButton *CancelButton;
void __fastcall CancelButtonClick(TObject *Sender);
void __fastcall SelectButtonClick(TObject *Sender);
private: // Déclarations de l’utilisateur
String* curColor;
public: // Déclarations de l’utilisateur
virtual __fastcall TColorForm(TComponent* Owner);
virtual __fastcall TColorForm(String* s, TComponent* Owner);
};
La fiche contient une boîte liste nommée ColorListBox contenant une liste de
noms de couleur. Quand il est choisi, le bouton nommé SelectButton mémorise le
nom de la couleur sélectionnée dans ColorListBox puis ferme la fiche.
CancelButton est un bouton qui ferme simplement la fiche.
Remarquez l’ajout à la déclaration de la classe d’un constructeur défini par
l’utilisateur qui attend un argument String*. Normalement, ce paramètre String*
pointe sur une chaîne gérée par la fiche qui déclenche ColorForm. Ce constructeur
a l’implémentation suivante :
void__fastcall TColorForm::TColorForm(String* s, TComponent* Owner)
: TForm(Owner)
{
curColor = s;
*curColor = "";
}
Le constructeur enregistre le pointeur dans une donnée membre privée curColor
et initialise la chaîne avec une chaîne vide.
Remarque Pour utiliser ce constructeur défini par l’utilisateur, la fiche doit être créée
explicitement. Ce ne peut pas être une fiche auto-créée au démarrage de
l’application. Pour davantage d’informations, voir “Contrôle du stockage en
mémoire des fiches” à la page 8-5.
Dans l’application, l’utilisateur sélectionne une couleur dans la boîte liste puis
clique sur le bouton SelectButton pour enregistrer son choix et fermer la fiche.

Conception de l’interface utilisateur des applications 8-11


Utilisation des fiches

Le gestionnaire d’événement OnClick du bouton SelectButton doit avoir la forme


suivante :
void __fastcall TColorForm::SelectButtonClick(TObject *Sender)
{
int index = ColorListBox->ItemIndex;
if (index >= 0)
*curColor = ColorListBox->Items->Strings[index];
Close();
}
Remarquez comment le gestionnaire d’événement stocke le nom de couleur
sélectionné dans l’adresse de chaîne qui a été transmise au constructeur.
Pratiquement, pour utiliser ColorForm, la fiche appelante doit transmettre au
constructeur un pointeur sur une chaîne existante. Supposons par exemple que
ColorForm est instanciée par une fiche appelée ResultsForm en réponse au choix
d’un bouton de ResultsForm nommé UpdateButton. Le gestionnaire d’événement
de ce bouton doit avoir la forme suivante :
void __fastcall TResultsForm::UpdateButtonClick(TObject *Sender)
{
String s;
GetColor(&s);
if (s != "") {
// faire quelque chose avec la chaîne nom de la couleur
}
else {
// faire autre chose car il n’y a pas de couleur sélectionnée
}
}
//---------------------------------------------------------------------
void TResultsForm::GetColor(String *s)
{
ColorForm = new TColorForm(s, this);
ColorForm->ShowModal();
delete ColorForm;
ColorForm = 0; // Mettre le pointeur à NULL
}
UpdateButtonClick crée une chaîne nommée s. L’adresse de s est transmise à la
fonction GetColor qui crée ColorForm en transmettant comme argument au
constructeur un pointeur sur s. Dès que ColorForm est fermée, elle est détruite
mais le nom de la couleur sélectionnée, s’il y en a une, est préservé dans s.
Sinon, s contient une chaîne vide, ce qui indique clairement que l’utilisateur est
sorti de ColorForm sans sélectionner une couleur.
Cet exemple utilise une variable chaîne pour stocker des informations provenant
de la fiche modale. Il est possible d’utiliser des objets plus complexes en fonction
de vos besoins. N’oubliez jamais qu’il faut laisser à la fiche appelante un moyen
de savoir que la fiche modale a été fermée sans modification, ni sélection (dans
l’exemple précédent en attribuant par défaut à s une chaîne vide).

8-12 Guide du développeur


Réutilisation des composants et des groupes de composants

Réutilisation des composants et des groupes de composants


C++Builder offre différentes possibilités d’enregistrer et de réutiliser le travail
réalisé avec les composants :
• Les modèles de composants procurent une façon simple et rapide de configurer et
d’enregistrer des groupes de composants. Voir “Création et utilisation des
modèles de composants” à la page 8-13.
• Vous pouvez enregistrer les fiches, les modules de données et les projets dans
le Référentiel. Vous disposez ainsi d’une base de données centrale composée
d’éléments réutilisables et vous pouvez utiliser l’héritage de fiche pour
diffuser les modifications.
• Vous pouvez enregistrer des cadres sur la palette des composants ou dans le
référentiel. Les cadres utilisent l’héritage de fiche et peuvent être incorporés
dans des fiches ou dans d’autres cadres. Voir “Manipulation des cadres” à la
page 8-14.
• Créer un composant personnalisé est la manière la plus complexe de réutiliser
du code, mais c’est celle qui procure le plus de souplesse. Voir chapitre 45,
“Présentation générale de la création d’un composant”.

Création et utilisation des modèles de composants


Vous pouvez créer des modèles composés d’un ou de plusieurs composants.
Après avoir organisé les composants sur une fiche, défini leurs propriétés et écrit
du code pour eux, enregistrez-les sous la forme d’un modèle de composant. Par la
suite, en sélectionnant le modèle dans la palette des composants, vous pouvez
placer les composants préconfigurés sur une fiche en une seule étape ; toutes les
propriétés et tout le code de gestion d’événement associés sont simultanément
ajoutés à votre projet.
Une fois que vous avez placé un modèle sur une fiche, vous pouvez
repositionner les composants indépendamment les uns des autres, redéfinir leurs
propriétés et créer ou modifier Les gestionnaires d’événements qui leur sont
associés comme si vous placiez chaque composant un par un.
Pour créer un modèle de composant,
1 Placez et arrangez des composants sur une fiche. Dans l’inspecteur d’objets,
définissez leurs propriétés et événements.
2 Sélectionnez les composants. La manière la plus simple de sélectionner
plusieurs composants consiste à faire glisser le pointeur de la souris au-dessus
d’eux. Des poignées grises apparaissent dans les coins de chaque composant
sélectionné.
3 Choisissez Composant|Créer un modèle de composant.
4 Spécifiez un nom pour le modèle dans la zone de saisie Information modèle
de composant. Le nom proposé par défaut est le type du premier composant
sélectionné à l’étape 2 suivi du mot “Template”. Par exemple, si vous
sélectionnez un libellé puis une boîte texte, le nom proposé est

Conception de l’interface utilisateur des applications 8-13


Manipulation des cadres

“TLabelTemplate”. Vous pouvez modifier ce nom, en veillant à ne pas utiliser


un nom de composant existant.
5 Dans la boîte de saisie Page de palette, spécifiez la page de la palette des
composants dans laquelle vous souhaitez placer le modèle. Si vous spécifiez
une page qui n’existe pas, une nouvelle page est créée lorsque vous
enregistrez le modèle.
6 A côté de Icône de palette, sélectionnez un bitmap pour représenter le modèle
sur la palette. L’image bitmap proposée par défaut est celle utilisée par le type
du premier composant sélectionné à l’étape 2. Pour rechercher d’autres images
bitmap, cliquez sur Changer. Les dimensions du bitmap que vous choisissez
ne doivent pas dépasser 24 pixels sur 24 pixels.
7 Cliquez sur OK.
Pour supprimer des modèles de la palette des composants, choisissez
Composant|Configurer la palette.

Manipulation des cadres


Un cadre (TFrame), comme une fiche, est un conteneur pour d’autres
composants. Il utilise le même mécanisme de possession que les fiches lorsque
les composants y sont instanciés et détruits automatiquement, et la même
relation parent-enfant pour la synchronisation des propriétés de composants.
A divers égards, un cadre s’apparente davantage à un composant personnalisé
qu’à une fiche. Les cadres peuvent être enregistrés sur la palette des composants
pour en faciliter la réutilisation et imbriqués dans des fiches, dans d’autres
cadres ou autres objets conteneur. Une fois qu’un cadre a été créé et enregistré, il
continue de fonctionner comme une unité et d’hériter des modifications des
composants qu’il contient (y compris d’autres cadres). Lorsqu’un cadre est
incorporé dans un autre cadre ou dans une fiche, il continue d’hériter des
modifications apportées au cadre dont il dérive.
Les cadres servent à organiser les groupes de contrôles utilisés en plusieurs
endroits de votre application. Par exemple, si vous avez un bitmap utilisé par
plusieurs fiches, vous pouvez le placer dans un cadre afin qu’une seule copie de
ce bitmap soit incluse dans les ressources de votre application. Vous pouvez
également décrire un ensemble de champs de saisie servant à modifier une table
avec un cadre et l’utiliser chaque fois que vous souhaitez entrer les données de
la table.

Création de cadres
Pour créer un cadre vide, choisissez Fichier|Nouveau|Cadre, ou Fichier|
Nouveau|Autre et double-cliquez sur Cadre. Vous pouvez alors déposer des
composants (y compris d’autres cadres) sur le nouveau cadre.

8-14 Guide du développeur


Manipulation des cadres

Il est généralement préférable, bien que non nécessaire, d’enregistrer les cadres
en tant que partie d’un projet. Si vous souhaitez créer un projet ne contenant
que des cadres et aucune fiche, choisissez Fichier|Nouveau|Application, fermez
la nouvelle fiche et la nouvelle unité sans les enregistrer, puis choisissez Fichier|
Nouveau|Cadre et enregistrez le projet.
Remarque Lorsque vous enregistrez des cadres, évitez d’utiliser les noms par défaut Unit1,
Project1 etc., car ils peuvent être à la source de conflits au moment de
l’utilisation ultérieure des cadres.
A la conception, vous pouvez afficher n’importe quel cadre contenu dans le
projet en cours en choisissant Voir|Fiches et en sélectionnant le cadre. Comme
dans le cas des fiches et des modules de données, vous pouvez passer du
concepteur de fiche au fichier fiche du cadre en cliquant avec le bouton droit et
en choisissant Voir comme fiche ou Voir comme texte.

Ajout de cadres à la palette des composants


Les cadres sont ajoutés à la palette des composants comme des modèles de
composants. Pour ajouter un cadre à la palette des composants, ouvrez le cadre
dans le concepteur de fiche (vous ne pouvez pas utiliser un cadre incorporé dans
un autre composant), cliquez avec le bouton droit sur le cadre et choisissez
Ajouter à la palette. Lorsque la boîte de dialogue Information modèle de
composant s’ouvre, sélectionnez un nom, une page de palette et une icône pour
le nouveau modèle.

Utilisation et modification des cadres


Pour utiliser un cadre dans une application, vous devez le placer, directement ou
indirectement, sur une fiche. Vous pouvez ajouter des cadres directement sur des
fiches, sur d’autres cadres ou sur d’autres objets conteneur, comme des volets et
des boîtes de défilement.
Le concepteur de fiche permet d’ajouter un cadre à une application de deux
manières :
• Sélectionnez un cadre à partir de la palette des composants et déposez-le sur
une fiche, un autre cadre ou un autre objet conteneur. Si nécessaire, le
concepteur de fiche demande s’il est possible d’inclure le fichier unité du
cadre dans votre projet.
• Sélectionnez Cadres à partir de la page Standard de la palette des composants
et cliquez sur une fiche ou un autre cadre. Une boîte de dialogue s’ouvre sur
une liste de cadres figurant déjà dans votre projet ; sélectionnez-en un et
cliquez sur OK.
Lorsque vous déposez un cadre sur une fiche ou un autre conteneur, C++Builder
déclare une nouvelle classe qui dérive du cadre que vous avez sélectionné. De
même, lorsque vous ajoutez une nouvelle fiche à un projet, C++Builder déclare
une nouvelle classe qui dérive de TForm. Cela signifie que les modifications
apportées ultérieurement au cadre d’origine (ancêtre) sont répercutées sur le

Conception de l’interface utilisateur des applications 8-15


Manipulation des cadres

cadre incorporé, mais que les modifications apportées au cadre incorporé ne sont
pas répercutées sur le cadre ancêtre.
Supposons que vous souhaitiez regrouper des composants d’accès aux données
et des contrôles orientés données en vue d’une utilisation fréquente,
éventuellement dans plusieurs applications. Pour ce faire, vous pourriez
rassembler les composants dans un modèle de composant ; mais si vous
commencez à utiliser le modèle et changez d’avis ultérieurement sur
l’organisation des contrôles, vous devez faire marche arrière et modifier
manuellement dans chaque projet la partie sur laquelle le modèle a été placé.
Par contre, si vous placez vos composants base de données dans un cadre, les
modifications ultérieures ne doivent être apportées que dans un seul endroit ; les
modifications apportées à un cadre d’origine sont automatiquement répercutées
sur ses descendants incorporés lors de la recompilation des projets.
Parallèlement, vous pouvez modifier n’importe quel cadre incorporé sans affecter
le cadre d’origine ni aucun de ses descendants incorporés. La seule restriction à
la modification des cadres incorporés est que vous ne pouvez pas leur ajouter
des composants.
Figure 8.1 Cadre avec des contrôles orientés données et un composant source de données

Outre une simplification de gestion, les cadres procurent une efficacité


supplémentaire dans l’utilisation des ressources. Par exemple, pour utiliser une
image bitmap ou un autre graphique dans une application, vous pouvez charger
le graphique dans la propriété Picture d’un contrôle TImage. Toutefois, si vous
utilisez fréquemment le même graphique dans une application, chaque objet
Image que vous placez sur une fiche génère une autre copie du graphique ajouté
au fichier ressource de la fiche. Cela est également vrai si vous définissez
TImage::Picture une fois et enregistrez le contrôle Image en tant que modèle de
composant. Une meilleure solution consiste à déposer l’objet Image sur un cadre,
à y charger le graphique puis à utiliser le cadre là où vous souhaitez que le
graphique apparaisse. Cela génère des fichiers fiche moins volumineux et
présente en outre la possibilité de modifier le graphique partout où il figure en
modifiant l’objet Image sur le cadre d’origine.

Partage des cadres


Vous pouvez partager un cadre avec les autres développeurs de deux manières :
• Ajouter le cadre au référentiel d’objet.
• Distribuer l’unité du cadre (.cpp et .h) et les fichiers fiche (.dfm ou .xfm).

8-16 Guide du développeur


Développement de boîtes de dialogue

Pour ajouter un cadre au référentiel, ouvrez n’importe quel projet contenant le


cadre, cliquez avec le bouton droit dans le concepteur de fiche et choisissez
Ajouter au référentiel. Pour davantage d’informations, voir “Utilisation du
référentiel d’objets” à la page 7-27.
Si vous envoyez une unité de cadre et les fichiers fiche à d’autres développeurs,
ils peuvent les ouvrir et les ajouter à la palette des composants. Si le cadre
contient d’autres cadres, ils devront l’ouvrir en tant que partie d’un projet.

Développement de boîtes de dialogue


Les composants boîte de dialogue de la page Dialogues de la palette des
composants permettent d’utiliser dans vos applications diverses boîtes de
dialogue. Ces boîtes de dialogue donnent à vos applications une interface
familière et cohérente dans laquelle l’utilisateur effectue certaines opérations
communes sur les fichiers, comme l’ouverture, l’enregistrement ou l’impression.
Ces boîtes de dialogue affichent et/ou obtiennent des données.
Chaque boîte de dialogue s’ouvre lorsque sa méthode Execute est appelée.
Execute renvoie une valeur booléenne : si l’utilisateur choisit OK pour accepter
les modifications apportées dans la boîte de dialogue, Execute renvoie true ; s’il
choisit Annuler pour quitter la boîte de dialogue sans rien modifier, Execute
renvoie false.
CLX Si vous écrivez une application multiplate-forme, vous pouvez utiliser les boîtes
de dialogue proposés par CLX dans l’unité QDialogs. Pour les systèmes
d’exploitation disposant d’un type de boîte de dialogue natif pour les opérations
courantes, comme l’ouverture ou l’enregistrement d’un fichier ou la modification
de fonte ou de couleur, vous pouvez utiliser la propriété UseNativeDialog.
Attribuez la valeur true à UseNativeDialog si vous savez que votre application
sera exécutée dans un environnement qui possède ces boîtes de dialogue natives,
et si vous préférez les utiliser au lieu des boîtes de dialogue Qt.

Utilisation des boîtes de dialogue d’ouverture


TOpenDialog est le composant boîte de dialogue le plus couramment utilisé. Il est
généralement employé par une option de menu Nouveau ou Ouvrir dans le
menu Fichier de la barre de menus principale d’une fiche. La boîte de dialogue
contient des contrôles qui vous permettent de sélectionner des groupes de
fichiers en utilisant un caractère joker et de naviguer dans les répertoires.
Le composant TOpenDialog permet d’utiliser une boîte de dialogue Ouvrir dans
votre application. La fonction de cette boîte de dialogue est de permettre à
l’utilisateur de spécifier un fichier à ouvrir. Utilisez la méthode Execute pour
afficher la boîte de dialogue.
Quand l’utilisateur choisit OK dans la boîte de dialogue, le nom du fichier
sélectionné par l’utilisateur est stocké dans la propriété FileName de TOpenDialog.
Vous pouvez ensuite utiliser cette valeur à votre guise.

Conception de l’interface utilisateur des applications 8-17


Organisation des actions pour les barres d’outils et les menus

L’exemple de code suivant peut être placé dans une Action et lié à la propriété
Action du sous-élément d’un menu TMainMenu ou placé dans l’événement
OnClick du sous-élément :
if(OpenDialog1->Execute()){
filename = OpenDialog1->FileName;
};
Ce code affiche la boîte de dialogue et si l’utilisateur choisit le bouton OK, le
nom du fichier sélectionné est copié dans la variable filename de type AnsiString
préalablement déclarée.

Organisation des actions pour les barres d’outils et les menus


C++Builder offre plusieurs fonctionnalités qui simplifieront votre travail de
création, de personnalisation et de maintenance des menus et des barres d’outils.
Ces fonctionnalités vous permettent d’organiser les listes des actions que les
utilisateurs de votre application peuvent déclencher en appuyant sur un bouton
dans une barre d’outils, en choisissant une commande dans un menu ou en
cliquant sur une icône.
Très souvent, un même ensemble d’actions est utilisé pour plusieurs éléments de
l’interface utilisateur. Par exemple, les commandes Couper, Copier et Coller
apparaissent fréquemment à la fois dans un menu Edition et dans une barre
d’outils. Il vous suffit d’ajouter l’action une fois pour l’utiliser dans plusieurs
éléments de l’interface utilisateur de votre application.
Sur la plate-forme Windows, il existe des outils pour vous aider à définir et à
grouper les actions, à créer diverses dispositions et à personnaliser les menus
lors de la conception ou de l’exécution. Ces outils sont appelés outils
ActionBand, les menus et les barres d’outils que vous créez en les utilisant sont
appelés bandes d’actions. En général, vous pouvez créer une interface utilisateur
ActionBand comme suit :
• Construisez une liste d’actions afin de créer un ensemble d’actions disponibles
pour votre application (utilisez le gestionnaire d’actions, TActionManager)
• Ajoutez les éléments de l’interface utilisateur à l’application (utilisez des
composants ActionBand comme TActionMainMenuBar et TActionToolBar)
• “Glissez-déplacez” des actions du gestionnaire d’actions sur les éléments de
l’interface utilisateur

8-18 Guide du développeur


Organisation des actions pour les barres d’outils et les menus

Le tableau suivant définit la terminologie qui s’applique à la définition des


menus et des barres d’outils :

Tableau 8.1 Terminologie de la définition des actions


Terme Définition
Action Une réponse à ce que fait l’utilisateur, comme cliquer sur un élément
de menu. De nombreuses actions standard fréquement nécessaires sont
fournies ; vous pouvez les utiliser telles quelles dans vos applications.
Par exemple, sont incluses les opérations sur les fichiers, comme
ouvrir, enregistrer sous, exécuter et quitter, ainsi que de nombreuses
autres pour l’édition, le formatage, la recherche, les dialogues ou les
actions sur les fenêtres. Vous pouvez également programmer des
actions personnalisées et utiliser les listes et le gestrionnaire d’actions
pour y accéder.
Bande d’action Un conteneur pour un ensemble d’actions associé à un menu ou à une
barre d’outils personnalisés. Les composants ActionBand pour les
menus principaux et les barres d’outils (TActionMainMenuBar et
TActionToolBar) sont des exemples de bandes d’actions.
Catégorie d’action Vous permet de grouper des actions et de les introduire en tant que
groupe dans un menu ou une barre d’outils. Par exemple, une des
catégories d’actions standard, Search, inclut les actions Find, FindFirst,
FindNext et Replace et les ajoute toutes en même temps.
Classes d’actions Les classes qui réalisent les actions utilisées dans votre application.
Toutes les actions standard sont définies dans des classes d’actions
comme TEditCopy, TEditCut et TEditUndo. Vous pouvez utiliser ces
classes en les faisant glisser de la boîte de dialogue Personnalisation à
une bande d’action.
Client d’action Représente la plupart du temps l’élément de menu ou le bouton qui
reçoit une notification pour déclencher une action. Quand le client
reçoit une commande utilisateur (par exemple, un clic de souris), il
initie une action associée.
Liste d’actions Maintiennent la liste des actions par lesquelles votre application
répond à ce que fait l’utilisateur.
Gestionnaire Groupe et organise des ensembles logiques d’actions pouvant être ré-
d’actions utilisés dans les composants ActionBand. Voir TActionManager.
Menu Présente la liste des commandes que l’utilisateur de l’application peut
exécuter en cliquant dessus. Vous pouvez créer des menus en utilisant
la classe menu ActionBand TActionMainMenuBar, ou en utilisant des
composants multiplates-formes comme TMainMenu ou TPopupMenu.
Cible Représente l’élément auquel s’applique l’action. La cible est
généralement un contrôle, par exemple un mémo ou un contrôle de
données. Certaines actions n’ont pas de cible. Ainsi, les actions
standard d’aide ne tiennent pas compte de la cible mais démarrent
simplement le système d’aide.
Barre d’outils Affiche une ligne visible d’icônes de boutons qui, lorsque l’utilisateur
clique dessus, font accomplir au programme une action, comme
imprimer le document en cours. Vous pouvez créer des barres d’outils
en utilisant le composant barre d’outils ActionBand TActionToolBar, ou
en utilisant le composant multiplate-forme TToolBar.

Si vous développez pour plusieurs plates-formes, voir “Utilisation des listes


d’actions” à la page 8-26.

Conception de l’interface utilisateur des applications 8-19


Organisation des actions pour les barres d’outils et les menus

Qu’est-ce qu’une action ?


Pendant que vous développez votre application, vous pouvez créer un ensemble
d’actions utilisables dans divers éléments de l’interface utilisateur. Vous pouvez
les organiser en catégories et les insérer dans un menu en tant qu’ensemble (par
exemple, Couper, Copier et Coller) ou un seul à la fois (par exemple, Outils|
Personnaliser).
Une action correspond à un ou plusieurs éléments de l’interface utilisateur,
comme les commandes de menu ou les boutons des barres d’outils. Les actions
ont deux utilités : (1) elles représentent des propriétés communes à des éléments
de l’interface utilisateur, par exemple l’état d’un contrôle activé ou coché, et (2)
elles répondent lorsqu’un contrôle est déclenché, comme lorsque l’utilisateur de
l’application clique sur un bouton ou choisit un élément de menu. Vous pouvez
créer un catalogue d’actions disponibles dans votre application via des menus,
des boutons, des barres d’outils, des menus contextuels, etc.
Les actions sont associées à d’autres composants :
• Clients :Un ou plusieurs clients utilisent l’action. Le client souvent représente
un élément de menu ou un bouton (par exemple, TToolButton, TSpeedButton,
TMenuItem, TButton, TCheckBox, TRadioButton, etc.). Des actions se trouvent
également dans les composants ActionBand comme TActionMainMenuBar et
TActionToolBar. Quand le client reçoit une commande de l’utilisateur (par
exemple, un clic de souris), il initie une action associée. Généralement,
l’événement OnClick d’un client est associé à l’événement OnExecute de son
action.
• Cible :L’action agit sur la cible. La cible est généralement un contrôle, par
exemple un mémo ou un contrôle de données. Les développeurs de
composants peuvent créer des actions spécifiques aux besoins des contrôles
qu’ils conçoivent et utilisent, puis empaqueter ces unités pour créer des
applications plus modulaires. Certaines actions n’ont pas de cible. Ainsi, les
actions standard d’aide ne tiennent pas compte de la cible mais démarrent
simplement le système d’aide.
Une cible peut également être un composant. Par exemple, les contrôles de
données changent la cible par un ensemble de données associé.
Le client influence l’action — l’action répond lorsqu’un client déclenche l’action.
L’action influence également le client — les propriétés des actions mettent à jour
dynamiquement les propriétés des clients. Par exemple, si, à l’exécution, une
action est désactivée (en initialisant sa propriété Enabled à false), chaque client de
cette action est désactivé et apparaît estompé.
Vous pouvez ajouter, supprimer et réorganiser des actions en utilisant le
gestionnaire d’actions ou l’éditeur de liste d’actions (qui s’affiche lorsque vous
double-cliquez sur un objet liste d’actions, TActionList). Ces actions sont ensuite
connectées aux contrôles client.

8-20 Guide du développeur


Organisation des actions pour les barres d’outils et les menus

Définition des bandes d’actions


Les actions ne conservant aucune information de “disposition” (ni apparence ni
position), C++Builder propose les bandes d’actions capables de stocker ces
données. Les bandes d’actions fournissent un mécanisme permettant de spécifier
des informations de disposition et un jeu de contrôles. Vous pouvez afficher les
actions comme des éléments de l’interface utilisateur tels que barres d’outils ou
menus.
Vous organisez des ensembles d’actions en utilisant le gestionnaire d’actions
(TActionManager). Vous pouvez soit utiliser des actions standard soit créer les
vôtres.
Créez ensuite les bandes d’actions :
• Utilisez TActionMainMenuBar pour créer un menu principal.
• Utilisez TActionToolBar pour créer une barre d’outils.
Les bandes d’actions agissent comme conteneurs qui contiennent et affichent les
ensembles d’actions. Pendant la conception, vous pouvez “glisser-déplacer” des
éléments de l’éditeur du gestionnaire d’actions à la bande d’action. A l’exécution,
les utilisateurs peuvent également personnaliser les menus ou les barres d’outils
de l’application en utilisant une boîte de dialogue semblable à l’éditeur du
gestionnaire d’actions.

Création des barres d’outils et des menus


Remarque Cette section décrit la méthode recommandée pour créer des menus et des barres
d’outils dans les applications Windows. Pour le développement multiplate-forme,
vous devez utiliser TToolBar et les composants menu, comme TMainMenu, et les
organiser en utilisant les listes d’actions (TActionList). Voir “Définition des listes
d’actions” à la page 8-26.
Vous utilisez le gestionnaire d’actions pour générer automatiquement des barres
d’outils et des menus principaux en fonction des actions contenues dans votre
application. Le gestionnaire d’actions gère les actions standard ainsi que les
actions personnalisées que vous aurez éventuellement écrites. Créez ensuite les
éléments de l’interface utilisateur basés sur ces actions et utilisez les bandes
d’actions pour afficher ces éléments d’action en tant qu’éléments dans un menu
ou en tant que boutons dans une barre d’outils.
La procédure générale de création des menus, barres d’outils et autres bandes
d’actions comporte les étapes suivantes :
• Placer un gestionnaire d’actions sur une fiche.
• Ajouter des actions au gestionnaire d’actions, qui les organise en listes
d’actions adaptées.
• Créer les bandes d’actions (c’est-à-dire, le menu ou la barre d’outils) pour
l’interface utilisateur.
• Placer les actions dans l’interface de l’application par glisser-déplacer.

Conception de l’interface utilisateur des applications 8-21


Organisation des actions pour les barres d’outils et les menus

La procédure suivante décrit ces étapes en détail :


Pour créer des menus et des barres d’outils en utilisant les bandes d’actions :
1 Depuis la page Supplément de la palette des composants, placez un
composant gestionnaire d’actions (TActionManager) sur la fiche dans laquelle
vous voulez créer la barre d’outils ou le menu.
2 Si vous voulez qu’il y ait des images sur le menu ou la barre d’outils, placez
sur la fiche un composant liste d’images (ImageList) en le prenant dans la
page Win32 de la palette des composants. (Vous devez ajouter les images que
vous souhaitez utiliser à cette liste d’images ou utilisez les images fournies.)
3 Depuis la page Supplément de la palette des composants, placez sur la fiche
un ou plusieurs des bandes d’actions suivantes :
• TActionMainMenuBar (pour concevoir des menus principaux)
• TActionToolBar (pour concevoir des barres d’outils)
4 Connectez la liste d’images au gestionnaire d’actions : la focalisation étant sur
le gestionnaire d’actions, sélectionnez dans l’inspecteur d’objets le nom de la
liste d’images dans la propriété Images.
5 Ajoutez des actions au volet action de l’éditeur du gestionnaire d’actions :
• Double-cliquez sur le gestionnaire d’actions afin d’afficher l’éditeur du
gestionnaire d’actions.
• Cliquez sur la flèche déroulante située à côté du bouton Nouvelle action (le
bouton le plus à gauche dans le coin supérieur droit de la page Actions,
comme illustré par la figure 8.2) et sélectionnez Nouvelle action ou
Nouvelle action standard. Une vue arborescente s’affiche. Ajoutez une ou
plusieurs actions, ou catégories d’actions, au volet actions du gestionnaire
d’actions. Le gestionnaire d’actions ajoute les actions à ses listes d’actions.
Figure 8.2 Editeur du gestionnaire d’actions

Bouton Nouvelle action et


bouton déroulant

6 “Glissez-déplacez” des actions indépendantes, ou des catégories d’actions, de


l’éditeur du gestionnaire d’actions au menu ou à la barre d’outils que vous
concevez.

8-22 Guide du développeur


Organisation des actions pour les barres d’outils et les menus

Pour ajouter des actions définies par l’utilisateur, créez une nouvelle TAction en
cliquant sur le bouton Nouvelle action et en écrivant le gestionnaire d’événement
qui définit la réponse qu’elle donnera à son déclenchement. Voir “Que se passe-
t-il lors du déclenchement d’une action ?” à la page 8-27 pour plus de détails.
Lorsque vous avez défini les actions, vous pouvez les placer dans les menus ou
les barres d’outils par glisser-déplacer comme les actions standard.

Ajout de couleurs, de motifs ou d’images aux menus, boutons et barres


d’outils
Vous pouvez utiliser les propriétés Background et BackgroundLayout pour spécifier
la couleur, le motif ou le bitmap à utiliser sur un élément de menu ou un
bouton. Ces propriétés vous permettent également de définir une bannière qui se
place à gauche ou à droite d’un menu.
Assignez des fonds et des dispositions aux sous-éléments à partir de leurs objets
client action. Si vous voulez définir le fond des éléments d’un menu, cliquez
dans le concepteur de fiches sur l’élément de menu qui contient ces éléments.
Par exemple, sélectionner Fichier vous permet de changer le fond des éléments
apparaissant dans le menu Fichier. Vous pouvez attribuer une couleur, un motif,
ou un bitmap à la propriéte Background dans l’inspecteur d’objets.
Utilisez la propriété BackgroundLayout pour décrire comment placer le fond sur
l’élément. Les couleurs ou les images peuvent être placées derrière le libellé
normalement, étirées pour remplir à la zone, ou en mosaïque de petits carrés
recouvrant toute la zone.
Les éléments dont le fond est normal (blNormal), étiré (blStretch), ou en
mosaïque (blTile) sont affichés avec un fond transparent. Si vous créez une
bannière, l’image complète est placée à gauche (blLeftBanner) ou à droite
(blRightBanner) de l’élément. Vous devez vous assurer que la taille convient car
elle ne’st ni réduite ni agrandie.
Pour modifier le fond d’une bande d’action (c’est-à-dire, dans un menu principal
ou une barre d’outils) sélectionnez la bande d’action et choisissez la
TActionClientBar via l’éditeur de collection de bandes d’actions. Vous pouvez
définir les propriétés Background et BackgroundLayout pour spécifier la couleur, le
motif ou le bitmap à utiliser sur toute la barre d’outils ou tout le menu.

Ajout d’icônes aux menus et aux barres d’outils


Vous pouvez ajouter des icônes à côté des éléments de menu ou remplacer les
libellés figurant dans les barres d’outils par des icônes. Vous organiserez les
bitmaps ou les icônes au moyen d’un composant ImageList.
1 A partir de la page Win32 de la palette des composants, placez sur la fiche un
composant ImageList.
2 Ajoutez à la liste d’images les images que vous voulez utiliser. Double-cliquez
sur l’icône ImageList. Cliquez sur Ajouter et naviguez jusqu’aux images que
vous voulez utiliser ; cliquez sur OK lorsque vous en avez terminé. Vous
trouverez des exemples d’images dans Program Files\Common Files\Borland
Shared\Images. (Les images des boutons comprennent deux vues pour les
états actif et inactif des boutons.)

Conception de l’interface utilisateur des applications 8-23


Organisation des actions pour les barres d’outils et les menus

3 Depuis la page Supplément de la palette des composants, placez sur la fiche


une ou plusieurs des bandes d’actions suivantes :
• TActionMainMenuBar (pour concevoir des menus principaux)
• TActionToolBar (pour concevoir des barres d’outils)
4 Connectez la liste d’images au gestionnaire d’actions. Donnez d’abord la
focalisation au gestionnaire d’actions. Ensuite, sélectionnez dans l’inspecteur
d’objets le nom de la liste d’images dans la propriété Images, par exemple
ImageList1.
5 Utilisez l’éditeur du gestionnaire d’actions pour ajouter des actions au
gestionnaire d’actions. Vous pouvez associer une image à une action en
définissant sa propriété ImageIndex par le numéro d’ordre de l’image dans la
liste d’images.
6 “Glissez-déplacez” des actions indépendantes ou des catégories d’actions de
l’éditeur du gestionnaire d’actions au menu ou à la barre d’outils.
7 Pour les barres d’outils, où vous voulez uniquement afficher l’icône et pas le
libellé : sélectionnez la bande d’action Barre d’outils et double-cliquez sur sa
propriété Items. Dans l’éditeur de collections, vous pouvez sélectionner un ou
plusieurs éléments et définir leurs propriétés Caption.
8 Les images apparaissent automatiquement dans le menu ou la barre d’outils.

Création de barres d’outils et de menus personnalisables par l’utilisateur


Vous pouvez utiliser les bandes d’actions avec le gestionnaire d’actions pour
créer des menus et des barres d’outils personnalisables. A l’exécution, les
utilisateurs peuvent personnaliser les barres d’outils et les menus (bandes
d’actions) de l’interface utilisateur de l’application en utilisant une boîte de
dialogue semblable à l’éditeur du gestionnaire d’actions.
Pour permettre aux utilisateurs de personnaliser une bande d’action de
l’application qu’ils exécutent :
1 Placez un composant gestionnaire d’actions sur une fiche.
2 Placez vos composants bande d’action (TActionMainMenuBar, TActionToolBar).
3 Double-cliquez sur le gestionnaire d’actions afin d’afficher l’éditeur du
gestionnaire d’actions.
• Sélectionnez les actions que vous voulez utiliser dans votre application.
Ajoutez également l’action Customize, qui apparaît à la fin de la liste des
actions standard.
• Placez sur la fiche un composant TCustomizeDlg depuis l’onglet Supplément,
connectez-le au gestionnaire d’actions en utilisant sa propriété
ActionManager. Spécifiez un nom de fichier pour enregistrer dans un flux
les personnalisations effectuées par les utilisateurs.
• Placez les actions dans les composants bande d’action par glisser-déplacer.
(Vérifiez que vous avez ajouté l’action Customize à la barre d’outils ou au
menu.)

8-24 Guide du développeur


Organisation des actions pour les barres d’outils et les menus

4 Terminez l’application.
Lorsque vous compilez et exécutez l’application, les utilisateurs ont accès à une
commande Personnaliser qui affiche une boîte de dialogue de personnalisation
semblable à l’éditeur du gestionnaire d’actions. Ils peuvent “glisser-déplacer” des
éléments de menu et créer des barres d’outils en utilisant les actions que vous
avez fournies dans le gestionnaire d’actions.

Cacher les éléments et les catégories inutilisés dans les bandes d’actions
Un des avantages de l’utilisation des ActionBands est que les éléments et les
catégories inutilisés peuvent être cachés à l’utilisateur. Avec le temps, les bandes
d’actions s’adaptent aux utilisateurs de l’application en montrant les éléments
qu’ils utilisent et en cachant les autres. Les éléments cachés peuvent redevenir
visibles : il suffit que l’utilisateur appuie sur un bouton déroulant. De plus,
l’utilisateur peut restaurer la visibilité de tous les éléments d’une bande d’action
en réinitialisant les statistiques d’usage dans la boîte de dialogue de
personnalisation. Le masquage des éléments fait partie du comportement par
défaut des bandes d’actions, mais ce comportement peut être modifié afin
d’inhiber le masquage d’éléments particuliers, de tous les éléments d’une
collection particulière (par exemple, le menu Fichier), ou de tous les éléments
d’une bande d’action particulière.
Le gestionnaire d’actions mémorise le nombre de fois qu’une action a été
invoquée par l’utilisateur en l’enregistrant dans le champ UsageCount du
TActionClientItem correspondant. Le gestionnaire d’actions enregistre également le
nombre de fois que l’application a été exécutée (ce qui correspond au numéro de
la dernière session), ainsi que le numéro de la session où une action a été utilisée
pour la dernière fois. La valeur de UsageCount sert à rechercher le nombre
maximal de sessions pendant lesquelles un élément est inutilisé avant d’être
masqué, il ensuite est comparé avec la différence entre le numéro de session
actuel et le numéro de session de la dernière utilisation de l’élément. Si cette
différence est supérieure au nombre défini dans PrioritySchedule, l’élément est
caché. Les valeurs par défaut de PrioritySchedule sont indiquées dans le tableau
suivant :

Tableau 8.2 Valeurs par défaut de la propriété PrioritySchedule du gestionnaire d’actions


Nombre de sessions dans
lesquelles un élément d’une Nombre de sessions pendant lesquelles un élément
bande d’action a été utilisé restera visible après sa dernière utilisation
0, 1 3
2 6
3 9
4, 5 12
6-8 17
9-13 23
14-24 29
25 ou plus 31

Conception de l’interface utilisateur des applications 8-25


Utilisation des listes d’actions

Il est possible de désactiver le masquage d’un élément au moment de la


conception. Pour empêcher le masquage d’une action particulière (et de toutes
les collections qui la contiennent), recherchez son objet TActionClientItem et
définissez sa propriété UsageCount par -1. Pour empêcher le masquage d’une
collection entière d’éléments, comme le menu Fichier ou même la barre de
menus principale, recherchez l’objet TActionClients qui lui est associé et définissez
sa propriété HideUnused par false.

Utilisation des listes d’actions


Remarque Cette section concerne la définition des barres d’outils et des menus dans le
développement multiplates-formes. Vous pouvez utiliser les méthodes décrites ici
pour le développement Windows. Mais, l’utilisation des bandes d’actions est plus
simple et offre plus d’options. Les listes d’actions seront gérées automatiquement
par le gestionnaire d’actions. Voir “Organisation des actions pour les barres
d’outils et les menus” à la page 8-18 pour davantage d’informations sur
l’utilisation des bandes d’actions et du gestionnaire d’actions.
Les listes d’actions maintiennent la liste des actions par lesquelles votre
application répond à ce que fait l’utilisateur. En utilisant les objets action, vous
centralisez les fonctions accomplies par votre application à partir de l’interface
utilisateur. Cela vous permet de partager le code réalisant les actions (par
exemple, lorsqu’un bouton de barre d’outils et un élément de menu effectuent la
même tâche), et procure un lieu unique et centralisé d’activer et de désactiver
des actions selon l’état de l’application.

Définition des listes d’actions


La définition des listes d’actions est très simple une fois comprises les étapes
qu’elle implique :
• Créer la liste d’actions.
• Ajouter des actions à la liste d’actions.
• Définir des propriétés pour les actions.
• Attacher des clients à l’action.
Voici le détail de ces étapes :
1 Placez un objet TActionList dans votre fiche ou votre module de données.
ActionList appartient à la page Standard de la palette des composants.
2 Double-cliquez sur l’objet TActionList pour afficher l’éditeur de liste d’actions.
1 Utilisez une des actions prédéfinies énumérées dans l’éditeur : cliquez avec
le bouton droit et choisissez Nouvelle action standard.
2 Les actions prédéfinies sont groupées en catégories (ensemble de données,
édition, aide et fenêtre) dans la boîte de dialogue Classes d’actions
standard. Sélectionnez toutes les actions standard que vous voulez ajouter à
votre liste d’actions et cliquez sur OK.

8-26 Guide du développeur


Utilisation des listes d’actions

ou
3 Créez une nouvelle action qui vous sera propre : cliquez avec le bouton
droit et choisissez Nouvelle action.
3 Définissez les propriétés de chaque action dans l’inspecteur d’objets. Les
propriétés que vous définissez affectent chaque client de l’action.
La propriété Name identifie l’action, les autres propriétés et événements
(Caption, Checked, Enabled, HelpContext, Hint, ImageIndex, ShortCut, Visible et
Execute) correspondent aux propriétés et événements de ses contrôles client.
Elles portent généralement, mais pas obligatoirement, le même nom que la
propriété du client. Par exemple, la propriété Enabled d’une action correspond
à la propriété Enabled d’un TToolButton. Mais, la propriété Checked d’une action
correspond à la propriété Down d’un TToolButton.
4 Si vous utilisez les actions prédéfinies, l’action inclut une réponse standard qui
intervient automatiquement. Si vous créez votre propre action, vous devez
écrire un gestionnaire d’événement définissant comment l’action répond
lorsqu’elle est déclenchée. Voir “Que se passe-t-il lors du déclenchement d’une
action ?” à la page 8-27 pour plus de détails.
5 Attachez les actions de la liste d’actions aux clients qui le nécessitent :
• Cliquez sur le contrôle (par exemple, le bouton ou l’élément de menu) dans
la fiche ou le module de données. Dans l’inspecteur d’objets, la propriété
Action est la liste des actions disponibles.
• Sélectionnez celle que vous souhaitez.
Les actions standard, comme TEditDelete ou TDataSetPost, accomplissent l’action
attendue. L’aide en ligne de référence peut vous donner tous les détails sur le
fonctionnement de chacune des actions standard. Si vous écrivez vos propres
actions, vous aurez besoin de mieux comprendre ce qui se passe lorsqu’une
action est déclenchée.

Que se passe-t-il lors du déclenchement d’une action ?


Lorsqu’un événement est déclenché, il se produit la série d’événements qui
s’applique d’abord aux actions génériques. Ensuite, si l’événement ne gère pas
l’action, une autre séquence d’événements intervient.

Réponse par les événements


Quand un composant ou un contrôle client est cliqué ou subit un autre type
d’opération, se produit une série d’événements auxquels vous pouvez répondre.
Par exemple, le code suivant est le gestionnaire d’événement pour une action qui
inverse la visibilité d’une barre d’outils quand une action est exécutée :
void __fastcall TForm1::Action1Execute(TObject *Sender)
{
// Inverse la visibilité de Toolbar1
ToolBar1->Visible = !ToolBar1->Visible;
}

Conception de l’interface utilisateur des applications 8-27


Utilisation des listes d’actions

Vous pouvez fournir un gestionnaire d’événement qui réponde à l’un des trois
différents niveaux : action, liste d’actions ou application. Cela ne vous concerne
que si vous utilisez une nouvelle action générique et non une action standard
prédéfinie. En effet, les actions standard ont un comportement intégré qui
s’exécute automatiquement lorsque ces événements se produisent.
L’ordre dans lequel les gestionnaires d’événements répondront aux événements
est le suivant :
• Liste d’actions
• Application
• Action
Lorsque l’utilisateur clique sur un contrôle client, C++Builder appelle la méthode
Execute de l’action qui s’adresse d’abord à la liste d’actions, puis à l’objet
Application, enfin à l’action elle-même lorsque ni la liste d’actions ni
l’application ne la gère. C++Builder suit cette séquence de répartition lors de la
recherche d’une façon de répondre à l’action de l’utilisateur :
1 Si vous fournissez un gestionnaire d’événement OnExecute pour la liste
d’actions et qu’il gère l’action, l’application se poursuit.
Le gestionnaire d’événement de la liste d’actions dispose d’un paramètre
Handled qui renvoie false par défaut. Si le gestionnaire est défini et gère
l’événement, il renvoie true et la séquence de traitement s’arrête là. Par
exemple :
void __fastcall TForm1::ActionList1ExecuteAction(TBasicAction *Action, bool &Handled)
{
Handled = true;
}
Si vous ne définissez pas Handled par true dans le gestionnaire d’événement
de la liste d’actions, le traitement se poursuit.
2 Si vous n’avez pas écrit de gestionnaire d’événement OnExecute pour la liste
d’actions ou si le gestionnaire ne gère pas l’action, le gestionnaire d’événement
OnActionExecute de l’application est déclenché. S’il gère l’action, l’application
continue.
L’objet Application global reçoit un événement OnActionExecute si l’une des
listes d’actions de l’application échoue en gérant un événement. Comme le
gestionnaire d’événement OnExecute de la liste d’actions, le gestionnaire
OnActionExecute dispose d’un paramètre Handled qui renvoie false par défaut.
Si un gestionnaire d’événement est défini et gère l’événement, il renvoie true
et la séquence de traitement s’arrête ici. Par exemple :
void __fastcall TForm1::ApplicationExecuteAction(TBasicAction *Action, bool &Handled)
{
// Empêche l’exécution de toutes les actions de Application
Handled = true;
}
3 Si le gestionnaire d’événement OnExecute de l’application ne gère pas l’action,
le gestionnaire d’événement OnExecute de l’action est déclenché.

8-28 Guide du développeur


Utilisation des listes d’actions

Vous pouvez utiliser des actions intégrées ou créer vos propres classes d’actions
qui savent comment opérer sur des classes cibles spécifiques (telles que les
contrôles de saisie). Quand aucun gestionnaire d’événement n’est trouvé à
n’importe quel niveau, l’application essaie ensuite de trouver une cible sur
laquelle exécuter l’action. Quand l’application trouve une cible pour laquelle
l’action sait quoi faire, elle déclenche l’action. Voir la section suivante pour
davantage d’informations sur la manière dont l’application trouve une cible
pouvant correspondre à une classe d’actions prédéfinie.

Comment les actions trouvent leurs cibles


“Que se passe-t-il lors du déclenchement d’une action ?” à la page 8-27 décrit le
cycle d’exécution se produisant lorsqu’un utilisateur déclenche une action. S’il
n’y a pas de gestionnaire d’événement défini pour répondre à l’action, que ce
soit au niveau de la liste d’actions, de l’application ou de l’action, l’application
essaie d’identifier un objet cible auquel l’action peut s’appliquer.
L’application recherche un objet cible selon la séquence suivante :
1 Contrôle actif : l’application recherche d’abord un contrôle actif comme cible
potentielle.
2 Fiche active : si l’application ne trouve pas de contrôle actif ou si le contrôle
actif ne peut servir de cible, elle recherche la fiche active à l’écran
(ActiveForm).
3 Contrôles de la fiche : si la fiche active n’est pas une cible appropriée,
l’application recherche une cible dans les autres contrôles de la fiche active.
Si aucune cible n’est trouvée, rien ne se passe lorsque l’événement est déclenché.
Certains contrôles peuvent étendre la recherche afin de déférer la cible à un
composant qui leur est associé ; par exemple, les contrôles orientés données
défèrent la cible au composant ensemble de données qui leur est associé. D’autre
part, certaines actions prédéfinies n’utilisent pas de cible, par exemple, le
dialogue d’ouverture de fichiers.

Actualisation des actions


Quand l’application est inactive, l’événement OnUpdate se produit pour chaque
action liée à un contrôle ou un élément de menu affiché. Ceci permet aux
applications d’exécuter un code centralisé pour l’activation et la désactivation, la
sélection et la désélection, et ainsi de suite. Par exemple, le code suivant illustre
le gestionnaire d’événement OnUpdate pour une action qui est “cochée” quand la
barre d’outils est visible.
void __fastcall TForm1::Action1Update(TObject *Sender)
{
// Indique si ToolBar1 est actuellement visible
((TAction *)Sender)->Checked = ToolBar1->Visible;
}

Conception de l’interface utilisateur des applications 8-29


Utilisation des listes d’actions

Attention Ne placez pas de code nécessitant une exécution longue dans le gestionnaire
d’événement OnUpdate. En effet, il est exécuté à chaque fois que l’application est
inactive. Si l’exécution de ce gestionnaire d’événement est trop longue, les
performances de toute l’application s’en trouvent affectées.

Classes d’actions prédéfinies


Vous pouvez ajouter des actions prédéfinies à votre application en cliquant avec
le bouton droit sur le gestionnaire d’actions et en choisissant Nouvelle action
standard. La boîte de dialogue Classes d’actions standard s’affiche et présente la
liste des classes d’actions prédéfinies avec les actions standard qui leur sont
associées. Ce sont des actions qui sont incluses dans C++Builder et il existe des
objets qui accomplissent ces actions automatiquement. Les actions prédéfinies
sont organisées dans les classes suivantes :

Tableau 8.3 Classes d’actions


Classe Description
Edition Actions d’édition standard : Utilisées avec une cible contrôle de saisie.
TEditAction est la classe de base de descendants qui redéfinissent la
méthode ExecuteTarget afin d’implémenter les opérations copier,
couper et coller en utilisant le presse-papiers.
Formatage Actions de formatage standard : Utilisées avec le texte formaté pour
appliquer des options de formatage du texte telles que gras, italique,
souligné, barré, etc. TRichEditActionest la classe de base de
descendants qui redéfinissent les méthodes ExecuteTarget et
UpdateTarget afin d’implémenter le formatage de la cible.
Aide Actions d’aide standard : Utilisées avec toute cible. THelpAction est la
classe de base de descendants qui redéfinissent la méthode
ExecuteTarget pour transmettre les commandes à un système d’aide.
Fenêtre Actions de fenêtre standard : Utilisées avec les fiches d’une
application MDI comme cible. TWindowAction est la classe de base de
descendants qui redéfinissent la méthode ExecuteTarget pour
implémenter la réorganisation, la cascade, la fermeture, la mosaïque
et la réduction de fenêtres enfant MDI.
Fichier Actions de fichiers : Utilisées avec les opérations sur les fichiers
comme ouvrir, exécuter ou quitter.
Recherche Actions de recherche : Utilisées avec les options de recherche.
TSearchAction implémente le comportement commun des actions
affichant un dialogue non modal où l’utilisateur peut entrer une
chaîne pour rechercher un contrôle de saisie.
Onglet Actions des contrôles onglet : Utilisées pour le déplacement entre les
onglets dans un contrôle à onglets, comme les boutons Précédent et
Suivant d’un expert.
Liste Actions des contrôles liste : Utilisées pour gérer les éléments d’une
vue liste.
Dialogue Actions de dialogue : Utilisées avec les composants dialogue.
TDialogAction implémente le comportement commun des actions
affichant un dialogue lors de leur exécution. Chaque classe dérivée
représente un dialogue spécifique.

8-30 Guide du développeur


Utilisation des listes d’actions

Tableau 8.3 Classes d’actions (suite)


Classe Description
Internet Actions Internet : Utilisées pour des fonctions comme la navigation, le
téléchargement et l’envoie de mail sur Internet.
Ensemble de données Actions d’ensembles de données : Utilisées avec un composant
ensemble de données comme cible. TDataSetAction est la classe de
base de descendants qui redéfinissent les méthodes ExecuteTarget et
UpdateTarget afin d’implémenter les déplacements et les éditions de la
cible.
TDataSetAction introduit une propriété DataSource qui garantit que les
actions sont effectuées sur l’ensemble de données. Si DataSource vaut
NULL, le contrôle orienté données détenant la focalisation est utilisé.
Outils Outils : Des outils supplémentaires comme TCustomizeActionBars qui
affiche automatiquement la boîte de dialogue permettant de
personnaliser les bandes d’actions.

Tous les objets action sont décrits sous leur nom dans l’aide en ligne de
référence. Reportez-vous à l’aide pour avoir des détails sur leur fonctionnement.

Conception de composants action


Vous pouvez également créer vos propres classes d’actions prédéfinies. Quand
vous écrivez vos propres classes d’actions, vous pouvez leur attribuer la capacité
à s’exécuter sur certaines classes d’objet cible. Vous pouvez ensuite utiliser vos
actions personnalisées de la même façon que les classes d’actions prédéfinies.
Ainsi, si l’action détermine qu’elle peut s’appliquer à une classe cible, il suffit
d’affecter l’action au contrôle client et il agit sur la cible sans avoir besoin
d’écrire un gestionnaire d’événement.
Les concepteurs de composants peuvent utiliser comme exemple les classes
définies dans les unités StdActns et DBActns afin de dériver leurs propres classes
d’actions qui implémentent des comportements spécifiques à leurs contrôles et
leurs composants. Les classes de base de ces actions spécialisées (TEditAction,
TWindowAction) redéfinissent généralement HandlesTarget, UpdateTarget et d’autres
méthodes afin de limiter la cible de l’action à une classe spécifique d’objets.
Les classes dérivées surchargent habituellement ExecuteTarget pour réaliser une
tâche spécifique.
Voici ces méthodes :

Méthode Description
HandlesTarget Automatiquement appelée lorsque l’utilisateur invoque un objet (comme
un bouton de barre d’outils ou un élément de menu) lié à l’action. La
méthode HandlesTarget laisse l’objet action indiquer s’il convient de
l’exécuter à ce moment avec comme “cible” l’objet spécifié par le
paramètre Target. Voir “Comment les actions trouvent leurs cibles” à la
page 8-29 pour plus de détails.

Conception de l’interface utilisateur des applications 8-31


Création et gestion de menus

Méthode Description
UpdateTarget Automatiquement appelée lorsque l’application est inactive pour que les
actions puissent se mettre à jour elles-mêmes en fonction des conditions
en cours. Utilisez à la place de OnUpdateAction. Voir “Actualisation des
actions” à la page 8-29 pour plus de détails.
ExecuteTarget Automatiquement appelée lorsque l’action est déclenchée en réponse à
une action de l’utilisateur à la place de OnExecute (par exemple, quand
l’utilisateur sélectionne un élément de menu ou appuie sur un bouton de
barre d’outils qui est lié à cette action). Voir “Que se passe-t-il lors du
déclenchement d’une action ?” à la page 8-27 pour plus de détails.

Recensement d’actions
Si vous écrivez vos propres actions, il est possible de les recenser pour les faire
apparaître dans l’éditeur de liste d’actions. Vous les recensez ou vous en annulez
le recensement en utilisant les routines globales de l’unité ActnList :
extern PACKAGE void __fastcall RegisterActions(const AnsiString CategoryName, TMetaClass*
const * AClasses, const int AClasses_Size, TMetaClass* Resource);
extern PACKAGE void __fastcall UnRegisterActions(TMetaClass* const * AClasses, const int
AClasses_Size);
Quand vous appelez RegisterActions, les actions recensées apparaissent dans
l’éditeur de liste d’actions afin d’être utilisées dans vos applications. Vous
pouvez spécifier un nom de catégorie afin d’organiser vos actions, ainsi qu’un
paramètre Resource permettant de fournir des valeurs de propriété par défaut.
Par exemple, le code suivant recense dans l’EDI les actions de l’unité MyAction :
namespace MyAction
{
void __fastcall PACKAGE Register()
{
// du code vient ici pour recenser des composants et des éditeurs
TMetaClass classes[2] = {__classid(TMyAction1), __classid(TMyAction2)};
RegisterActions("MySpecialActions", classes, 1, NULL);
}
}
Quand vous appelez UnRegisterActions, les actions n’apparaissent plus dans
l’éditeur de liste d’actions.

Création et gestion de menus


Les menus constituent pour les utilisateurs un moyen commode d’exécuter des
commandes regroupées logiquement. Le concepteur de menus vous permet
d’ajouter facilement à une fiche un menu prédéfini ou personnalisé. Ajoutez un
composant menu à la fiche, ouvrez le concepteur de menus et saisissez
directement les éléments de menu dans la fenêtre du concepteur de menus.

8-32 Guide du développeur


Création et gestion de menus

Vous pouvez ajouter ou supprimer des éléments de menu et utiliser le glisser-


déplacer pour réorganiser les éléments à la conception.
Vous n’avez même pas besoin d’exécuter votre programme pour voir le résultat :
ce que vous concevez est immédiatement visible dans la fiche et apparaît
exactement comme à l’exécution. En utilisant du code, vous pouvez également
modifier les menus à l’exécution afin de proposer à l’utilisateur davantage
d’informations ou d’options.
Ce chapitre décrit la manière d’utiliser le concepteur de menus pour concevoir
des barres de menus et des menus surgissants (locaux). Les sujets suivants,
concernant la manipulation des menus à la conception et à l’exécution, sont
abordés :
• Ouverture du concepteur de menus.
• Construction des menus.
• Edition des éléments de menu dans l’inspecteur d’objets.
• Utilisation du menu contextuel du concepteur de menus.
• Utilisation des modèles de menu.
• Enregistrement d’un menu comme modèle.
• Ajout d’images à des éléments de menu.
Figure 8.3 Terminologie des menus
Eléments de menu de la barre de menu
Touche
accélératrice Eléments de menu d’une liste de menus

Ligne de
séparation Raccourci clavier

Ouverture du concepteur de menus


Vous concevez les menus de votre application à l’aide du concepteur de menus.
Avant de commencer à utiliser le concepteur de menus, ajoutez à votre fiche un
composant MainMenu ou PopupMenu. Ces deux composants menu se trouvent
dans la page Standard de la palette des composants.
Figure 8.4 Composants menu principal et menu surgissant
Composant MainMenu
Composant PopupMenu

Un composant menu principal (MainMenu) crée un menu attaché à la barre de


titre de la fiche. Un composant menu surgissant (PopupMenu) crée un menu qui
apparaît quand l’utilisateur clique avec le bouton droit de la souris dans la fiche.
Les menus surgissants n’ont pas de barre de menu.
Pour ouvrir le concepteur de menus, sélectionnez un composant menu sur la fiche,
puis :
• Double-cliquez sur le composant menu.

Conception de l’interface utilisateur des applications 8-33


Création et gestion de menus

ou
• Dans la page Propriétés de l’inspecteur d’objets, sélectionnez la propriété Items
puis double-cliquez sur [Menu] dans la colonne des valeurs ou cliquez sur le
bouton points de suspension (...).
Le concepteur de menus apparaît, le premier élément de menu (vide) est
sélectionné dans le concepteur et la propriété Caption est sélectionnée dans
l’inspecteur d’objets.
Figure 8.5 Concepteur pour un menu surgissant

Emplacement pour le
premier élément de menu

Construction des menus


Vous devez ajouter un composant menu à vos fiches pour chaque menu devant
apparaître dans l’application. Vous pouvez créer chaque structure de menu à
partir de zéro ou partir de l’un des modèles de menu prédéfinis.
Cette section décrit les principes de base de la création de menus à la
conception. Pour davantage d’informations sur les modèles de menu, voir
“Utilisation des modèles de menu” à la page 8-42.

Nom des menus


Comme pour tous les composants, C++Builder donne un nom par défaut au
composant menu que vous ajoutez à une fiche, par exemple MainMenu1. Vous
pouvez donner au menu un nom plus significatif.
C++Builder ajoute le nom du menu à la déclaration de type de la fiche et le nom
du menu apparaît dans la liste des composants.

Nom des éléments de menu


A la différence des composants menu, vous devez donner vous-même
explicitement un nom aux éléments de menu quand vous les ajoutez à la fiche.
Vous pouvez le faire de deux manières :
• En saisissant directement la valeur de la propriété Name.
• En saisissant d’abord la valeur de la propriété Caption, puis en laissant
C++Builder en dériver une valeur pour la propriété Name.

8-34 Guide du développeur


Création et gestion de menus

Si, par exemple, vous spécifiez Fichier comme valeur de la propriété Caption,
C++Builder affecte la valeur Fichier1 à la propriété Name de l’élément de
menu. Si vous renseignez d’abord la propriété Name avant de renseigner la
propriété Caption, C++Builder laisse la propriété Caption vide jusqu’à ce que
vous saisissiez une valeur.
Remarque Si vous saisissez dans la propriété Caption des caractères qui ne sont pas
autorisés dans un identificateur C++, C++Builder modifie la propriété Name en
conséquence. Si par exemple, l’intitulé commence par un chiffre, C++Builder
fait précéder le chiffre d’un caractère pour en dériver la valeur de la propriété
Name.
Le tableau suivant donne des exemples de ce processus en supposant que tous
ces éléments sont placés dans la même barre de menu.

Tableau 8.4 Exemples d’intitulés et des noms dérivés


Intitulé du composant Nom dérivé Explication
&Fichier Fichier1 Retire le &
&Fichier (une Fichier2 Numérote les éléments répétés
deuxième fois)
1234 N12341 Ajoute une lettre au début et numérote en fin
1234 (une deuxième N12342 Ajoute un nombre pour que le nom dérivé ne
fois) soit plus ambigu.
$@@@# N1 Supprime tous les caractères non standard,
ajoute une lettre au début et un numéro d’ordre
- (signe moins) N2 Numérote cette deuxième occurrence d’un
intitulé sans aucun caractère standard

Comme pour le composant menu, C++Builder ajoute le nom des éléments de


menu à la déclaration de type de la fiche et leur nom apparaît dans la liste des
composants.

Ajout, insertion et suppression d’éléments de menu


Les procédures suivantes décrivent la manière d’effectuer les opérations de base
intervenant dans la conception d’une structure de menu. Chaque procédure
suppose que la fenêtre du concepteur de menus est déjà ouverte.
Pour ajouter des éléments de menu à la conception :
1 Sélectionnez la position à laquelle vous voulez créer l’