Documente Academic
Documente Profesional
Documente Cultură
Borland® ™
Delphi 4
pour Windows 95 et Windows NT
Reportez-vous au fichier DEPLOY.TXT situé dans le répertoire racine de votre produit Delphi 4 pour obtenir la
liste complète des fichiers que vous pouvez distribuer en accord avec les termes du contrat de licence.
Les applications mentionnées dans ce manuel sont brevetées ou en attente de brevet. Ce document ne donne
aucun droit sur ces brevets.
COPYRIGHT © 1983–1998 Inprise Corporation. Tous droits réservés. Tous les produits Inprise et Borland sont des
marques ou des marques déposées de Inprise Corporation. Tous les autres noms de produits sont des marques
déposées de leurs fabricants respectifs.
Imprimé en Irlande
HDA1340WW21001 2E1R698
9899000102-9 8 7 6 5 4 3 2 1
D4
Table des matières
Chapitre 1 Affichage graphique. . . . . . . . . . . . 2-38
Boîtes de dialogue standard Windows . 2-39
Introduction 1-1 Initialisation des propriétés d’un
Contenu de ce manuel . . . . . . . . . . . . . . 1-1
composant . . . . . . . . . . . . . . . . . . 2-40
Conventions typographiques. . . . . . . . . . . 1-3
Affichage des propriétés dans
Support technique Inprise . . . . . . . . . . . . 1-3
l’inspecteurd’objets . . . . . . . . . . . 2-40
Commande de documentation imprimée . . . 1-3
Déplacements dans l’inspecteur
Partie I d’objets . . . . . . . . . . . . . . . . . . 2-41
Affichage et initialisation de propriétés
Programmation avec Delphi partagées . . . . . . . . . . . . . . . . . 2-41
Utilisation des éditeurs de propriété . . 2-41
Chapitre 2 Initialisation des propriétés à
Utilisation du Pascal Objet l’exécution . . . . . . . . . . . . . . . . 2-42
avec la VCL 2-1 Appel de méthodes . . . . . . . . . . . . . . 2-43
Différences entre le Pascal Objet et la VCL . . 2-1 Manipulation des gestionnaires
Utilisation du modèle objet . . . . . . . . . . . 2-2 d’événements . . . . . . . . . . . . . . . . 2-43
Qu’est-ce qu’un objet ? . . . . . . . . . . . . 2-2 Génération du gestionnaire de
Examen d’un objet Delphi. . . . . . . . . 2-3 l’événement par défaut . . . . . . . . . 2-43
Héritage des données et du code d’un Génération d’un nouveau gestionnaire
objet . . . . . . . . . . . . . . . . . . . . . . 2-6 d’événement . . . . . . . . . . . . . . . 2-44
Objets, composants et contrôles . . . . . 2-8 Recherche de gestionnaires
Portée d’un objet . . . . . . . . . . . . . . . . 2-9 d’événements . . . . . . . . . . . . . . . 2-45
Accès aux composants d’une autre Association d’un événement à un
fiche. . . . . . . . . . . . . . . . . . . . . 2-10 gestionnaire d’événement existant. . . 2-45
Portée et descendants d’un objet . . . . . 2-10 Association d’événements de menu à
Accès aux champs et aux méthodes du code . . . . . . . . . . . . . . . . . . 2-48
d’un objet . . . . . . . . . . . . . . . . . 2-12 Emploi d’objets utilitaires . . . . . . . . . . . . 2-49
Affectation de valeurs à des variables Utilisation des listes de chaînes . . . . . . . 2-50
objet . . . . . . . . . . . . . . . . . . . . . . 2-14 Manipulation des chaînes d’une liste . . 2-50
Création d’objets non visuels . . . . . . . . . 2-16 Chargement et enregistrement de listes
Création d’une instance d’un objet. . . . 2-16 de chaînes. . . . . . . . . . . . . . . . . 2-53
Destruction d’objets . . . . . . . . . . . . 2-17 Création d’une nouvelle liste de
Utilisation de composants . . . . . . . . . . . . 2-17 chaînes . . . . . . . . . . . . . . . . . . 2-54
Organisation de la VCL . . . . . . . . . . . . 2-18 Ajout d’objets à une liste de chaînes . . 2-56
Composants standard de Delphi . . . . . 2-18 Opérations sur les objets d’une liste de
Comment choisir le composant chaînes . . . . . . . . . . . . . . . . . . 2-57
approprié ? . . . . . . . . . . . . . . . . . . 2-19 Le registre et les fichiers INI Windows . . 2-58
Propriétés communes à tous les Utilisation des flux . . . . . . . . . . . . . . 2-58
composants . . . . . . . . . . . . . . . . 2-20 Utilisation de modules de données et de
Contrôles texte . . . . . . . . . . . . . . . 2-22 modules de données distants . . . . . . . . . 2-58
Contrôles de saisies spécialisées . . . . . 2-24 Création d’un nouveau module de
Contrôles bouton et similaires . . . . . . 2-26 données . . . . . . . . . . . . . . . . . . . . 2-59
Gestion de listes . . . . . . . . . . . . . . 2-29 Nom d’un module de données et de
Regroupement de composants . . . . . . 2-32 son fichier unité . . . . . . . . . . . . . 2-59
Rétroaction visuelle . . . . . . . . . . . . 2-34 Ajout et nom de composants . . . . . . 2-60
Affichage tabulaire . . . . . . . . . . . . . 2-36
i
Utilisation des propriétés et méthodes Conception d’applications distribuées . . . . . . 3-9
des composants dans un module de Distribution d’applications en utilisant
données . . . . . . . . . . . . . . . . . . 2-61 TCP/IP . . . . . . . . . . . . . . . . . . . . 3-10
Création de règles de gestion dans un Utilisation de sockets dans les
module de données. . . . . . . . . . . . 2-61 applications . . . . . . . . . . . . . . . . 3-10
Ajout d’un module de données distant Création d’applications serveur Web . . 3-11
à un projet serveur d’application . . . . . 2-62 Distribution d’applications en utilisant
Accès à un module de données depuis COM et DCOM . . . . . . . . . . . . . . . 3-11
une fiche . . . . . . . . . . . . . . . . . . . . 2-62 COM et ActiveX . . . . . . . . . . . . . . 3-11
Utilisation du référentiel d’objets . . . . . . . . 2-63 MTS . . . . . . . . . . . . . . . . . . . . . 3-12
Partage de fiches, de boîtes de dialogue, Distribution d’applications en utilisant
de modules de données ou de fiches . . . 2-63 CORBA . . . . . . . . . . . . . . . . . . . . 3-12
Ajout d’éléments au référentiel d’objets . . 2-64 Distribution d’applications de base de
Partage d’objets par une équipe de données . . . . . . . . . . . . . . . . . . . . 3-12
développement . . . . . . . . . . . . . . . . 2-64
Utilisation d’un élément du référentiel Chapitre 4
d’objets dans un projet . . . . . . . . . . . 2-65 Sujets de programmation généraux 4-1
Copie d’un élément . . . . . . . . . . . . 2-65 Gestion des exceptions . . . . . . . . . . . . . . . 4-1
Héritage d’un élément . . . . . . . . . . . 2-65 Protection des blocs de code. . . . . . . . . . 4-2
Utilisation d’un élément . . . . . . . . . . 2-65 Réponse aux exceptions . . . . . . . . . . 4-2
Utilisation de modèles de projet . . . . . . . 2-66 Exceptions et contrôle d’exécution . . . . 4-3
Modification d’une fiche partagée . . . . . . 2-66 Réponses à des exceptions imbriquées . . 4-3
Spécification d’un projet par défaut, Protection de l’allocation de ressources . . . 4-4
d’une nouvelle fiche et de la fiche Quelles ressources doivent être
principale . . . . . . . . . . . . . . . . . . . 2-67 protégées ? . . . . . . . . . . . . . . . . . 4-4
Ajout de composants personnalisés à l’EDI . . 2-67 Création d’un bloc de protection de
Différences entre installation de ressource . . . . . . . . . . . . . . . . . . 4-5
composant et installation de paquet . . . . 2-67 Gestion des exceptions RTL . . . . . . . . . . 4-6
Installer composant. . . . . . . . . . . . . 2-67 Qu’est-ce qu’une exception RTL ? . . . . . 4-6
Installer paquet . . . . . . . . . . . . . . . 2-68 Création d’un gestionnaire d’exception . 4-7
Installation de composants . . . . . . . . . . 2-68 Instructions de gestion des exceptions . . 4-8
Utilisation de l’instance d’exception . . . 4-9
Chapitre 3 Portée des gestionnaires d’exceptions . . 4-9
Création d’applications, de Spécification du gestionnaire
composants et de bibliothèques 3-1 d’exception par défaut . . . . . . . . . 4-10
Création d’applications . . . . . . . . . . . . . . 3-1 Gestion des classes d’exceptions . . . . 4-10
Exécutables Windows 95/NT. . . . . . . . . 3-2 Redéclenchement de l’exception. . . . . 4-11
Modèles d’interfaces utilisateur . . . . . 3-2 Gestion des exceptions des composants . . 4-12
Initialisation des options de l’EDI, du Utilisation de
projet et de la compilation. . . . . . . . 3-3 TApplication.HandleException . . . . . . 4-12
Applications console. . . . . . . . . . . . . . 3-3 Exceptions silencieuses . . . . . . . . . . . . 4-13
Applications service . . . . . . . . . . . . . . 3-4 Définition d’exceptions personnalisées. . . 4-14
Threads de service . . . . . . . . . . . . . 3-6 Déclaration d’un type objet exception . 4-14
Propriétés de nom d’un service. . . . . . 3-7 Déclenchement d’une exception . . . . . 4-14
Création de paquets et de DLL . . . . . . . . . 3-8 Utilisation des interfaces. . . . . . . . . . . . . 4-15
Utilisation des paquets et des DLL . . . . . 3-9 Création d’interfaces . . . . . . . . . . . . . 4-15
Modèles de programmation . . . . . . . . . 3-9 Partage d’interfaces entre des classes . . 4-16
Utilisation d’interfaces avec des
procédures . . . . . . . . . . . . . . . . 4-17
ii
Implémentation de IUnknown . . . . . . . . 4-18 Types fichier et E/S de fichier. . . . . . . . 4-40
TInterfacedObject . . . . . . . . . . . . . . . 4-18 Utilisation des flux fichier . . . . . . . . . . 4-41
Utilisation de l’opérateur as . . . . . . . . . 4-19 Création et ouverture de fichiers . . . . 4-42
Réutilisation de code et délégation . . . . . 4-20 Utilisation du handle de fichier . . . . . 4-42
Utilisation de implements pour la Lecture et écriture de fichiers . . . . . . 4-43
délégation . . . . . . . . . . . . . . . . . 4-20 Lecture et écriture de chaînes . . . . . . 4-43
Agrégation. . . . . . . . . . . . . . . . . . 4-21 Déplacements dans un fichier . . . . . . 4-44
Gestion mémoire des objets interface . . . . 4-22 Position et taille de fichier . . . . . . . . 4-44
Utilisation du comptage de références. . 4-22 Copie . . . . . . . . . . . . . . . . . . . . 4-45
Situations où il ne faut pas utiliser le
comptage de références . . . . . . . . . 4-23 Chapitre 5
Utilisation d’interfaces dans des Conception de l’interface utilisateur
applications distribuées . . . . . . . . . . . 4-24
Utilisation des chaînes . . . . . . . . . . . . . . 4-25
des applications 5-1
TApplication, TScreen et TForm . . . . . . . . . 5-1
Types caractère . . . . . . . . . . . . . . . . . 4-25
Utilisation de la fiche principale . . . . . . . 5-1
Types chaîne . . . . . . . . . . . . . . . . . . 4-26
Ajout de fiches supplémentaires . . . . . . . 5-2
Chaînes courtes . . . . . . . . . . . . . . . 4-26
Liaison de fiches . . . . . . . . . . . . . . . 5-2
Chaînes longues . . . . . . . . . . . . . . 4-27
Manipulation de l’application . . . . . . . . . 5-3
Chaînes étendues . . . . . . . . . . . . . . 4-28
Gestion de l’écran . . . . . . . . . . . . . . . . 5-3
Types PChar . . . . . . . . . . . . . . . . . 4-28
Gestion de la disposition. . . . . . . . . . . . 5-3
Chaînes ouvertes . . . . . . . . . . . . . . 4-28
Utilisation des messages . . . . . . . . . . . . . . 5-4
Routines de la bibliothèque d’exécution
Informations supplémentaires sur les fiches . . 5-5
manipulant des chaînes . . . . . . . . . . . 4-29
Contrôle du stockage en mémoire des
Routines manipulant les caractères
fiches . . . . . . . . . . . . . . . . . . . . . . 5-5
étendus . . . . . . . . . . . . . . . . . . . 4-29
Affichage d’une fiche créée
Routines usuelles de manipulation des
automatiquement . . . . . . . . . . . . . 5-5
chaînes longues . . . . . . . . . . . . . . 4-30
Création dynamique de fiche . . . . . . . 5-6
Déclaration et initialisation de chaînes . . . 4-32
Création de fiches non modales comme
Mélange et conversion de types chaîne . . . 4-33
fenêtres . . . . . . . . . . . . . . . . . . . 5-7
Conversions de chaînes en PChar . . . . . . 4-33
Utilisation d’une variable locale pour
Dépendances de chaîne . . . . . . . . . . 4-33
créer une instance de fiche . . . . . . . . 5-7
Renvoi d’une variable locale PChar . . . 4-34
Transfert de paramètres supplémentaires
Transfert d’une variable locale comme
aux fiches . . . . . . . . . . . . . . . . . . . . 5-7
PChar . . . . . . . . . . . . . . . . . . . . 4-34
Récupération de données des fiches . . . . . 5-8
Directives de compilation portant sur les
Récupération de données dans des
chaînes . . . . . . . . . . . . . . . . . . . . . 4-35
fiches non modales . . . . . . . . . . . . 5-9
Sujets apparentés . . . . . . . . . . . . . . . . 4-36
Récupération de données dans des
Jeux de caractères internationaux . . . . 4-36
fiches modales . . . . . . . . . . . . . . 5-10
Tableaux de caractères . . . . . . . . . . . 4-36
Création et gestion de menus . . . . . . . . . . 5-12
Chaînes de caractères . . . . . . . . . . . 4-36
Ouverture du concepteur de menus . . . . 5-13
Pointeurs de caractère . . . . . . . . . . . 4-36
Conception de menus . . . . . . . . . . . . 5-14
Opérateurs de chaîne . . . . . . . . . . . 4-36
Nom des menus . . . . . . . . . . . . . . 5-15
Utilisation des fichiers . . . . . . . . . . . . . . 4-36
Nom des éléments de menu . . . . . . . 5-15
Manipulation de fichiers . . . . . . . . . . . 4-37
Ajout, insertion et suppression
Suppression d’un fichier. . . . . . . . . . 4-37
d’éléments de menu . . . . . . . . . . . 5-16
Recherche d’un fichier . . . . . . . . . . . 4-37
Création de sous-menus . . . . . . . . . 5-17
Modifications des attributs d’un fichier . 4-39
Affichage du menu . . . . . . . . . . . . 5-20
Modification d’un nom de fichier . . . . 4-39
Edition des éléments de menu dans
Routines date-heure de fichier . . . . . . 4-40
l’inspecteur d’objets . . . . . . . . . . . . . 5-20
Copie d’un fichier . . . . . . . . . . . . . 4-40
iii
Utilisation du menu contextuel du Utilisation des listes d’actions. . . . . . . . . . 5-35
concepteur de menus . . . . . . . . . . . . 5-21 Objets action . . . . . . . . . . . . . . . . . . 5-35
Commandes du menu contextuel . . . . 5-21 Utilisation des actions . . . . . . . . . . . . 5-37
Changement de menu à la conception. . 5-21 Centralisation du code . . . . . . . . . . 5-37
Utilisation des modèles de menu . . . . . . 5-22 Liaison de propriétés . . . . . . . . . . . 5-37
Enregistrement d’un menu comme Exécution d’actions . . . . . . . . . . . . 5-38
modèle . . . . . . . . . . . . . . . . . . . . . 5-23 Actualisation des actions . . . . . . . . . 5-39
Conventions de nom pour les éléments Classes d’actions prédéfinies . . . . . . . . 5-40
et les gestionnaires d’événements des Actions standard d’édition . . . . . . . . 5-40
modèles de menu . . . . . . . . . . . . . 5-24 Actions standard de fenêtre . . . . . . . 5-40
Manipulation d’éléments de menu à Actions des ensembles de données . . . 5-41
l’exécution . . . . . . . . . . . . . . . . . . . 5-25 Conception de composants utilisant des
Fusion de menus . . . . . . . . . . . . . . . . 5-25 actions. . . . . . . . . . . . . . . . . . . . . 5-41
Spécification du menu actif : propriété Comment les actions trouvent leurs
Menu . . . . . . . . . . . . . . . . . . . . 5-25 cibles. . . . . . . . . . . . . . . . . . . . 5-42
Ordre des éléments de menu Recensement d’actions . . . . . . . . . . 5-43
fusionnés : propriété GroupIndex . . . 5-26 Ecriture d’éditeurs de listes d’actions. . 5-43
Importation de fichiers ressource . . . . . . 5-26 Programmes exemple. . . . . . . . . . . . . 5-44
Conception de barres d’outils et de barres
multiples . . . . . . . . . . . . . . . . . . . . . 5-27 Chapitre 6
Ajout d’une barre d’outils en utilisant un Manipulation des contrôles 6-1
composant volet . . . . . . . . . . . . . . . 5-28 Implémentation du glisser-déplacer dans les
Ajout d’un turbobouton à un volet . . . 5-28 contrôles . . . . . . . . . . . . . . . . . . . . . . 6-1
Spécification du glyphe d’un Début de l’opération glisser-déplacer . . . . 6-1
turbobouton . . . . . . . . . . . . . . . . 5-29 Acceptation des éléments à déplacer . . . . . 6-2
Définition de l’état initial d’un Déplacement des éléments. . . . . . . . . . . 6-3
turbobouton . . . . . . . . . . . . . . . . 5-29 Fin de l’opération glisser-déplacer . . . . . . 6-4
Création d’un groupe de turboboutons . 5-29 Personnalisation du glisser-déplacer avec
Utilisation de boutons bascule . . . . . . 5-30 l’objet TDrag . . . . . . . . . . . . . . . . . . 6-4
Ajout d’une barre d’outils en utilisant le Changement du pointeur de la souris . . . . 6-5
composant barre d’outils . . . . . . . . . . 5-30 Implémentation du glisser-empiler dans les
Ajout d’un bouton outil . . . . . . . . . . 5-31 contrôles . . . . . . . . . . . . . . . . . . . . . . 6-5
Affectation d’images à des boutons Transformation d’un contrôle fenêtré en
outils . . . . . . . . . . . . . . . . . . . . 5-31 un site d’empilement . . . . . . . . . . . . . 6-5
Définition de l’aspect et de l’état initial Transformation d'un contrôle en un
d’un bouton outil . . . . . . . . . . . . . 5-31 contrôle enfant empilable . . . . . . . . . . 6-6
Création de groupes de boutons outils . 5-32 Contrôle de l'empilement des contrôles
Utilisation de boutons outils bascule . . 5-32 enfants dans un site. . . . . . . . . . . . . . 6-6
Ajout d’un composant barre multiple . . . . 5-32 Contrôle du désempilement des contrôles
Initialisation de l’aspect de la barre enfants dans un site d'empilement . . . . . 6-7
multiple . . . . . . . . . . . . . . . . . . 5-33 Contrôle de la réponse des contrôles
Réponse aux clics . . . . . . . . . . . . . . . 5-33 enfants aux opérations glisser-empiler . . . 6-8
Ecriture du gestionnaire de l’événement Utilisation du texte dans les contrôles . . . . . . 6-8
clic d’un bouton. . . . . . . . . . . . . . 5-34 Définition de l’alignement du texte. . . . . . 6-8
Affectation d’un menu à un bouton Ajout de barres de défilement en mode
outil. . . . . . . . . . . . . . . . . . . . . 5-34 exécution . . . . . . . . . . . . . . . . . . . . 6-9
Ajout de barres d’outils masquées. . . . . . 5-34 Ajout de l’objet Clipboard . . . . . . . . . . 6-10
Affichage d’une barre d’outils . . . . . . . . 5-35 Sélection de texte . . . . . . . . . . . . . . . 6-10
iv
Sélection de la totalité d’un texte . . . . . . 6-11 Dessin de rectangles à coins arrondis. . 7-12
Couper, copier et coller du texte . . . . . . . 6-11 Dessin de polygones . . . . . . . . . . . 7-12
Effacement du texte sélectionné . . . . . . . 6-12 Gestion de plusieurs objets de dessin dans
Désactivation des éléments de menu . . . . 6-12 votre application . . . . . . . . . . . . . . . . 7-12
Ajout d’un menu surgissant . . . . . . . . . 6-13 Faire le suivi de l’outil de dessin à
Gestion de l’événement OnPopup . . . . . . 6-14 utiliser. . . . . . . . . . . . . . . . . . . . . 7-13
Ajout de graphiques à des contrôles . . . . . . 6-14 Changement d’outil en utilisant un
Choix du style dessiné par le propriétaire . 6-15 TurboBouton . . . . . . . . . . . . . . . . 7-14
Ajout d’objets graphiques à une liste de Utilisation des outils de dessin . . . . . . . 7-14
chaînes . . . . . . . . . . . . . . . . . . . . . 6-15 Dessiner des formes . . . . . . . . . . . . 7-15
Ajout d’images à une application . . . . 6-16 Partage de code entre plusieurs
Ajout d’images à une liste de chaînes . . 6-16 gestionnaires d’événements . . . . . . 7-16
Dessiner des éléments dessinés par le Dessiner sur un graphique . . . . . . . . . . . 7-17
propriétaire . . . . . . . . . . . . . . . . 6-17 Création de graphiques défilables . . . . . 7-18
Dimensionnement des éléments dessinés Ajout d’un contrôle image . . . . . . . . . . 7-18
par le propriétaire . . . . . . . . . . . . . . 6-17 Positionnement du contrôle . . . . . . . 7-18
Dessin de chaque élément dessiné par le Définition de la taille initiale du
propriétaire . . . . . . . . . . . . . . . . . . 6-18 bitmap . . . . . . . . . . . . . . . . . . . 7-18
Dessiner sur un bitmap . . . . . . . . . . 7-19
Chapitre 7 Chargement et enregistrement de fichiers
Utilisation de graphiques 7-1 graphiques . . . . . . . . . . . . . . . . . . . . 7-20
Présentation de la programmation relative Chargement d’une image depuis un
aux graphiques . . . . . . . . . . . . . . . . . . 7-1 fichier . . . . . . . . . . . . . . . . . . . . . 7-20
Propriétés et méthodes communes du Enregistrement d’une image dans un
canevas . . . . . . . . . . . . . . . . . . . . 7-2 fichier . . . . . . . . . . . . . . . . . . . . . 7-21
Rafraîchissement de l’écran . . . . . . . . . . 7-4 Remplacement de l’image . . . . . . . . . . 7-21
Affichage d’images graphiques dans une Utilisation du Presse-papiers avec les
application. . . . . . . . . . . . . . . . . . . 7-4 graphiques . . . . . . . . . . . . . . . . . . . . 7-23
Types des objets graphiques . . . . . . . . . 7-4 Copier des graphiques dans le
Utilisation des propriétés de l’objet canevas . 7-5 Presse-papiers . . . . . . . . . . . . . . . . 7-23
Utilisation des crayons . . . . . . . . . . . . 7-5 Couper des graphiques dans le
Changement de la couleur du crayon . . 7-6 Presse-papiers . . . . . . . . . . . . . . . . 7-23
Changement de l’épaisseur du crayon. . 7-6 Coller des graphiques depuis le
Changement du style du crayon . . . . . 7-7 Presse-papiers . . . . . . . . . . . . . . . . 7-24
Changement du mode du crayon . . . . 7-7 Techniques de dessin dans une application . . 7-24
Renvoi de la position du crayon . . . . . 7-8 Répondre à la souris . . . . . . . . . . . . . 7-25
Utilisation des pinceaux. . . . . . . . . . . . 7-8 Qu’y a-t’il dans un événement de
Changement de la couleur du pinceau . 7-8 souris ? . . . . . . . . . . . . . . . . . . 7-25
Changement du style du pinceau . . . . 7-9 Réponse à l’action bouton de souris
Définition de la propriété Bitmap du enfoncé . . . . . . . . . . . . . . . . . . 7-25
pinceau . . . . . . . . . . . . . . . . . . . 7-9 Réponse à l’action bouton de souris
Lecture et définition de pixels . . . . . . . . 7-10 relâché . . . . . . . . . . . . . . . . . . . 7-26
Utilisation des méthodes du canevas pour Réponse au déplacement de la souris . 7-27
dessiner des objets graphiques. . . . . . . . . 7-10 Ajout d’un champ à un objet fiche . . . . . 7-27
Dessin de lignes et de polylignes . . . . . . 7-10 Amélioration du dessin des lignes . . . . . 7-29
Dessin de lignes . . . . . . . . . . . . . . 7-10 Suivi du point d’origine . . . . . . . . . 7-29
Dessin de polylignes . . . . . . . . . . . . 7-11 Suivi des déplacements . . . . . . . . . . 7-29
Dessin de formes . . . . . . . . . . . . . . . . 7-11
Dessin de rectangles et d’ellipses. . . . . 7-11
v
Chapitre 8 Chapitre 10
Utilisation du multimédia 8-1 Utilisation des paquets
Ajout de séquences vidéo silencieuses à une et des composants 10-1
application . . . . . . . . . . . . . . . . . . . . 8-1 Pourquoi utiliser des paquets? . . . . . . . . . 10-2
Exemple d’ajout de séquences vidéo Les paquets et les DLL standard . . . . . . 10-2
silencieuses . . . . . . . . . . . . . . . . . . 8-2 Paquets d’exécution . . . . . . . . . . . . . . . 10-3
Ajout de séquences audio et/ou vidéo à une Utilisation des paquets dans une
application . . . . . . . . . . . . . . . . . . . . 8-3 application . . . . . . . . . . . . . . . . . . 10-3
Exemple d’ajout de séquences audio et/ou Paquets chargés dynamiquement . . . . . . 10-4
vidéo . . . . . . . . . . . . . . . . . . . . . . 8-5 Choix des paquets d'exécution à utiliser. . 10-4
Paquets personnalisés . . . . . . . . . . . . 10-5
Chapitre 9 Paquets de conception . . . . . . . . . . . . . . 10-6
Ecriture d’applications multithreads 9-1 Installation de paquets de composants. . . 10-6
Définition d’objets thread. . . . . . . . . . . . . 9-2 Création et modification de paquets . . . . . . 10-8
Initialisation du thread . . . . . . . . . . . . 9-3 Création d’un paquet . . . . . . . . . . . . . 10-8
Affectation d’une priorité par défaut . . 9-3 Modification d’un paquet existant . . . . . 10-9
Libération des threads . . . . . . . . . . . 9-3 Modification de fichiers source de paquets
Ecriture de la fonction thread . . . . . . . . 9-4 manuellement . . . . . . . . . . . . . . . . 10-9
Utilisation du thread principal VCL . . . 9-4 Présentation de la structure d’un
Utilisation de variables locales aux paquet. . . . . . . . . . . . . . . . . . . . 10-10
threads . . . . . . . . . . . . . . . . . . . 9-5 Nom de paquets . . . . . . . . . . . . . 10-10
Vérification de l’arrêt par d’autres La clause Requires. . . . . . . . . . . . 10-10
threads . . . . . . . . . . . . . . . . . . . 9-6 La clause Contains . . . . . . . . . . . 10-10
Ecriture du code de nettoyage . . . . . . . . 9-6 Compilation de paquets . . . . . . . . . . .10-11
Coordination de threads . . . . . . . . . . . . . 9-7 Directives de compilation propres aux
Eviter les accès simultanés . . . . . . . . . . 9-7 paquets . . . . . . . . . . . . . . . . . .10-11
Verrouillage d’objets . . . . . . . . . . . . 9-7 Utilisation du compilateur et du lieur
Utilisation de sections critiques. . . . . . 9-7 en ligne de commande . . . . . . . . 10-13
Utilisation du synchronisateur à écriture Fichiers paquets créés lors d’une
exclusive et lecture multiple. . . . . . . 9-8 compilation réussie . . . . . . . . . . 10-13
Autres techniques de partage de la Déploiement de paquets . . . . . . . . . . . . 10-14
mémoire . . . . . . . . . . . . . . . . . . 9-9 Déploiement d’applications utilisant des
Attente des autres threads . . . . . . . . . . 9-9 paquets . . . . . . . . . . . . . . . . . . . 10-14
Attente de la fin d’exécution d’un Distribution de paquets à d’autres
thread. . . . . . . . . . . . . . . . . . . . 9-9 développeurs. . . . . . . . . . . . . . . . 10-14
Attente de l’achèvement d’une tâche . . 9-10 Fichiers de collection de paquet. . . . . . 10-14
Exécution d’objets thread . . . . . . . . . . . . . 9-11
Redéfinition de la priorité par défaut . . . . 9-11 Chapitre 11
Démarrage et arrêt des threads . . . . . . . 9-12 Création d’applications
Cache des threads . . . . . . . . . . . . . . . 9-12
Utilisation des threads dans les applications
internationales 11-1
Internationalisation et localisation . . . . . . . 11-1
distribuées . . . . . . . . . . . . . . . . . . . . 9-13
Internationalisation . . . . . . . . . . . . . . 11-1
Utilisation des threads dans les serveurs
Localisation . . . . . . . . . . . . . . . . . . 11-1
de messagerie . . . . . . . . . . . . . . . . . 9-13
Internationalisation des applications . . . . . . 11-2
Utilisation des threads avec les objets
Codage de l’application . . . . . . . . . . . 11-2
distribués . . . . . . . . . . . . . . . . . . . 9-14
Jeux de caractères . . . . . . . . . . . . . 11-2
Ecriture d'applications ( fichiers .EXE) . 9-14
Jeux de caractères OEM et ANSI . . . . 11-2
Ecriture de bibliothèques . . . . . . . . . 9-15
Jeux de caractères sur deux octets. . . . 11-2
Débogage d’applications multithreads . . . . . 9-15
vi
Caractères larges . . . . . . . . . . . . . . 11-3 Fontes . . . . . . . . . . . . . . . . . . . . . .12-11
Inclure des fonctionnalités bi-direction- Versions de Windows. . . . . . . . . . . . .12-11
nelles dans les applications . . . . . . . 11-4 Termes du contrat de licence logicielle . . . 12-12
Propriété BiDiMode . . . . . . . . . . . . 11-5 DEPLOY.TXT . . . . . . . . . . . . . . . . 12-13
Fonctionnalités spécifiques aux cibles README.TXT . . . . . . . . . . . . . . . . 12-13
locales . . . . . . . . . . . . . . . . . . . 11-8 Contrat de licence . . . . . . . . . . . . . . 12-13
Conception de l’interface utilisateur. . . . . 11-8 Documentation de produits vendus par
Texte . . . . . . . . . . . . . . . . . . . . . 11-8 un tiers . . . . . . . . . . . . . . . . . . . 12-13
Images graphiques . . . . . . . . . . . . . 11-9
Formats et ordre de tri . . . . . . . . . . . 11-9 Partie II
Correspondances entre claviers . . . . . . 11-9 Développement d’applications
Isolement des ressources . . . . . . . . . . 11-10
Création de DLL de ressources. . . . . . . 11-10 de base de données
Utilisation des DLL de ressource . . . . . 11-11
Basculement dynamique de DLL de Chapitre 13
ressource. . . . . . . . . . . . . . . . . . . 11-12 Conception d’applications de
Localisation des applications. . . . . . . . . . 11-13 bases de données 13-1
Localisation des ressources . . . . . . . . . 11-13 Utilisation des bases de données . . . . . . . . 13-1
Types de bases de données . . . . . . . . . 13-2
Chapitre 12 Bases de données locales . . . . . . . . . 13-2
Déploiement des applications 12-1 Serveurs de bases de données
Déploiement d’applications généralistes . . . . 12-1 distants . . . . . . . . . . . . . . . . . . 13-3
Utilisation des programmes d’installation . 12-2 Sécurité des bases de données. . . . . . . . 13-3
Identification des fichiers de l’application . 12-2 Transactions . . . . . . . . . . . . . . . . . . 13-4
Les fichiers de l’application, par Dictionnaire de données . . . . . . . . . . . 13-5
extension de fichier . . . . . . . . . . . . 12-3 Intégrité référentielle, procédures stockées
Fichiers paquet . . . . . . . . . . . . . . . 12-3 et déclencheurs . . . . . . . . . . . . . . . 13-6
Contrôles ActiveX . . . . . . . . . . . . . 12-3 Architecture des bases de données . . . . . . . 13-7
Applications complémentaires . . . . . . 12-4 Anticipation de l’évolutivité . . . . . . . . . 13-8
Emplacement des DLL. . . . . . . . . . . 12-4 Applications de base de données à niveau
Déploiement d’applications de base de unique. . . . . . . . . . . . . . . . . . . . . 13-9
données . . . . . . . . . . . . . . . . . . . . . . 12-4 Applications de base de données à niveau
L’accès au moteur de bases de données. . . 12-4 double. . . . . . . . . . . . . . . . . . . . 13-10
Le moteur de bases de données Applications de base de données
Borland . . . . . . . . . . . . . . . . . . . 12-5 multiniveaux . . . . . . . . . . . . . . . . .13-11
Autres moteurs de bases de données . . 12-5 Conception de l’interface utilisateur . . . . . 13-12
SQL Links . . . . . . . . . . . . . . . . . . 12-5 Affichage d’un seul enregistrement. . . . 13-13
MIDAS, services d’application distribuée Affichage de plusieurs enregistrements . 13-13
multiniveau . . . . . . . . . . . . . . . . . . 12-6 Analyse des données . . . . . . . . . . . . 13-14
Déploiement d’applications Web . . . . . . . . 12-7 Sélection des données à afficher . . . . . 13-14
Programmer pour des environnements hôtes Ecriture de rapports . . . . . . . . . . . . 13-16
hétérogènes . . . . . . . . . . . . . . . . . . . . 12-8
Résolution d’écran et profondeurs de Chapitre 14
couleur . . . . . . . . . . . . . . . . . . . . . 12-8 Construction d’applications à
Si vous n’utilisez pas de redimension-
nement dynamique . . . . . . . . . . . . 12-9
niveau unique et à niveau double 14-1
Si vous redimensionnez dynamique- Applications basées sur le BDE. . . . . . . . . 14-2
ment les fiches et les contrôles . . . . . 12-9 Architecture basée sur le BDE . . . . . . . . 14-2
Présentation des bases de données et
Adaptation à des profondeurs de
couleur variables . . . . . . . . . . . . 12-10 des ensembles de données . . . . . . . 14-3
vii
Utilisation des sessions . . . . . . . . . . 14-4 Création du serveur d’applications . . . . . .15-11
Connexion aux bases de données . . . . . . 14-5 Configuration du module de données
Utilisation des transactions . . . . . . . . . . 14-5 distant. . . . . . . . . . . . . . . . . . . . 15-13
Contrôle explicite des transactions . . . . 14-6 Configuration de
Utilisation d’un composant base de TRemoteDataModule . . . . . . . . . 15-13
données pour les transactions. . . . . . 14-7 Configuration de TMTSDataModule . 15-14
Utilisation de la propriété Configuration de TCorbaDataModule 15-16
TransIsolation . . . . . . . . . . . . . . . 14-8 Création d’un fournisseur de données
Utilisation du SQL direct . . . . . . . . . 14-9 pour le serveur d’applications. . . . . . 15-17
Utilisation des transactions locales . . . 14-10 Contrôle des informations contenues
Mise en mémoire cache des mises à dans les paquets de données . . . . . 15-18
jour . . . . . . . . . . . . . . . . . . . . . . 14-11 Réponse aux requêtes de données du
Création et restructuration des tables de client . . . . . . . . . . . . . . . . . . . 15-20
base de données . . . . . . . . . . . . . . 14-12 Réponse aux requêtes de mise à jour
Applications de base de données linéaires . . 14-12 du client. . . . . . . . . . . . . . . . . 15-21
Création des ensembles de données . . . . 14-13 Modification des paquets delta avant
Création d’un nouvel ensemble de la mise à jour de la base de
données à l’aide de champs données . . . . . . . . . . . . . . . . . 15-22
persistants . . . . . . . . . . . . . . . . 14-13 Impact sur l’application des mises à
Création d’un ensemble de données à jour. . . . . . . . . . . . . . . . . . . . 15-23
l’aide de définitions de champ et Filtrage des mises à jour . . . . . . . . 15-24
d’index . . . . . . . . . . . . . . . . . . 14-14 Résolution des erreurs de mise à jour
Création d’un ensemble de données à sur le fournisseur . . . . . . . . . . . 15-24
partir d’une table existante . . . . . . 14-15 Réponse aux événements générés par
Chargement et enregistrement des le client . . . . . . . . . . . . . . . . . 15-25
données . . . . . . . . . . . . . . . . . . . 14-16 Gestion des contraintes serveur . . . . 15-25
Utilisation du modèle “briefcase” . . . . . 14-17 Création de l’application client . . . . . . . . 15-26
Passage à une application à niveau triple . . 14-18 Connexion au serveur d’application . . . 15-27
Spécification d’une connexion à l’aide
Chapitre 15 de DCOM . . . . . . . . . . . . . . . . 15-28
Création d’applications Spécification d’une connexion à l’aide
de sockets . . . . . . . . . . . . . . . . 15-29
multiniveaux 15-1 Spécification d’une connexion à l’aide
Avantages du modèle de base de données
de OLEnterprise . . . . . . . . . . . . 15-30
multiniveau . . . . . . . . . . . . . . . . . . . . 15-2
Spécification d’une connexion à l’aide
Présentation de la technologie MIDAS . . . . . 15-3
de CORBA . . . . . . . . . . . . . . . 15-30
Présentation d’une application
Courtage de connexions . . . . . . . . 15-31
multiniveau basée sur MIDAS . . . . . . . 15-3
Gestion des connexions serveur. . . . . . 15-31
Structure de l’application client . . . . . . . 15-4
Connexion au serveur. . . . . . . . . . 15-31
Structure du serveur d’applications . . . . . 15-5
Fermeture ou changement de
Utilisation de MTS . . . . . . . . . . . . . 15-6
connexion serveur . . . . . . . . . . . 15-32
Utilisation de l’interface IDataBroker . . 15-8
Appel des interfaces serveur . . . . . . . 15-32
Utilisation de l’interface IProvider . . . . 15-8
Gestion des contraintes. . . . . . . . . . . 15-34
Sélection d’un protocole de connexion . . . 15-9
Mise à jour des enregistrements. . . . . . 15-35
Utilisation de connexions DCOM . . . . 15-9
Application des mises à jour. . . . . . 15-36
Utilisation de connexions Socket . . . . . 15-9
Régularisation des erreurs de mise à
Utilisation de OLEnterprise . . . . . . . 15-10
jour. . . . . . . . . . . . . . . . . . . . 15-36
Utilisation de connexions CORBA . . . 15-10
Rafraîchissement des enregistrements . . 15-37
Construction d’une application
Obtention de paramètres du serveur
multiniveau . . . . . . . . . . . . . . . . . . . 15-10
d’applications . . . . . . . . . . . . . . . 15-38
viii
Personnalisation des serveurs Déplacement parmi les composants
d’applications. . . . . . . . . . . . . . . . . . 15-39 base de données d’une session . . . . . 16-13
Extension de l’interface du serveur Spécification de l’emplacement des
d’applications . . . . . . . . . . . . . . . . 15-39 répertoires Paradox . . . . . . . . . . . . 16-14
Fourniture et résolution dans un Spécification de l’emplacement du
ensemble de données . . . . . . . . . . . 15-40 fichier de contrôle . . . . . . . . . . . 16-14
Gestion des transactions dans les Spécification de l’emplacement des
applications multiniveaux . . . . . . . . . . 15-41 fichiers temporaires . . . . . . . . . . 16-15
Gestion des relations maître/détail . . . . . . 15-42 Manipulation de tables Paradox et dBase
Gestion des modules de données distants protégées par mot de passe . . . . . . . 16-15
sans état . . . . . . . . . . . . . . . . . . . . . 15-43 Utilisation de la méthode
Distribution d’une application client en tant AddPassword . . . . . . . . . . . . . 16-15
que contrôle ActiveX . . . . . . . . . . . . . 15-44 Utilisation des méthodes
Création d’une fiche active pour RemovePassword
l’application client . . . . . . . . . . . . . 15-45 RemoveAllPasswords . . . . . . . . . 16-16
Utilisation de la méthode GetPassword
Chapitre 16 et de l’événement OnPassword . . . 16-16
Gestion de sessions de bases Gestion de plusieurs sessions . . . . . . . . . 16-18
Utilisation d’un composant session dans
de données 16-1 des modules de données. . . . . . . . . . . 16-19
Manipulation d’un composant session . . . . . 16-2
Utilisation de la session par défaut . . . . . 16-2
Création de sessions supplémentaires. . . . 16-3
Chapitre 17
Dénomination d’une session . . . . . . . . . 16-4 Connexion aux bases de données 17-1
Activation d’une session . . . . . . . . . . . 16-5 Présentation des composants base de
Personnalisation du démarrage d’une données persistants et temporaires . . . . . . 17-1
session . . . . . . . . . . . . . . . . . . . . . 16-6 Utilisation des composants base de
Spécification du comportement par défaut données temporaires . . . . . . . . . . . . 17-2
de connexion aux bases de données . . . . 16-6 Création de composants base de données
Création, ouverture et fermeture des en mode conception. . . . . . . . . . . . . 17-3
connexions de bases de données . . . . . . 16-7 Création de composants base de données
Fermeture d’une connexion de base de à l’exécution . . . . . . . . . . . . . . . . . 17-3
données . . . . . . . . . . . . . . . . . . 16-8 Contrôle des connexions. . . . . . . . . . . . . 17-4
Fermeture de toutes les connexions de Association d’un composant base de
base de données. . . . . . . . . . . . . . 16-8 données à une session . . . . . . . . . . . 17-4
Abandon des connexions aux bases de Spécification d’un alias BDE. . . . . . . . . 17-5
données temporaires . . . . . . . . . . . . . 16-9 Définition des paramètres des alias BDE . 17-6
Recherche de la connexion d’une base de Contrôle de la connexion au serveur . . . . 17-7
données . . . . . . . . . . . . . . . . . . . . 16-9 Connexion à un serveur de bases de
Extraction d’informations sur une données . . . . . . . . . . . . . . . . . . . . 17-7
session . . . . . . . . . . . . . . . . . . . . 16-10 Considérations relatives à la connexion à
Manipulation des alias BDE . . . . . . . . 16-11 un serveur distant . . . . . . . . . . . . . . 17-8
Spécification de la visibilité des alias . 16-11 Utilisation des protocoles réseau . . . . 17-8
Comment rendre des alias visibles Utilisation de ODBC . . . . . . . . . . . 17-9
aux autres sessions et applications . . 16-11 Déconnexion d’un serveur de base de
Comment déterminer les alias, les données . . . . . . . . . . . . . . . . . . . . 17-9
pilotes et les paramètres connus . . . 16-11 Fermeture d’ensembles de données sans
Création, modification et suppression déconnexion du serveur . . . . . . . . . 17-10
des alias . . . . . . . . . . . . . . . . . 16-12
ix
Déplacement parmi les ensembles de Navigation parmi les enregistrements
données d’un composant base de d’un ensemble de données filtré . . . . 18-23
données . . . . . . . . . . . . . . . . . . . 17-10 Modification des données . . . . . . . . . . . 18-24
Interactions entre les composants base de Modification d’enregistrements . . . . . . 18-24
données et les composants session . . . . . 17-10 Ajout de nouveaux enregistrements . . . 18-25
Utilisation de composants base de données Insertion d’enregistrements . . . . . . 18-26
dans des modules de données . . . . . . . . 17-11 Ajout d’enregistrements . . . . . . . . 18-26
Suppression d’enregistrements . . . . . . 18-27
Chapitre 18 Validation des modifications. . . . . . . . 18-27
Présentation des ensembles de Annulation des modifications . . . . . . . 18-27
Modification d’enregistrements entiers. . 18-28
données 18-1 Utilisation des événements des ensembles de
Présentation de l’objet TDataSet . . . . . . . . 18-2
données. . . . . . . . . . . . . . . . . . . . . 18-29
Types d’ensembles de données . . . . . . . . . 18-2
Interruption d’une méthode . . . . . . . . 18-30
Ouverture et fermeture des ensembles de
Utilisation de l’événement OnCalcFields 18-30
données . . . . . . . . . . . . . . . . . . . . . . 18-3
Utilisation des ensembles de données
Détermination et définition des états d’un
orientés BDE . . . . . . . . . . . . . . . . . . 18-31
ensemble de données . . . . . . . . . . . . . . 18-3
Présentation de l’orientation BDE. . . . . 18-32
Désactivation d’un ensemble de données. . 18-5
Gestion des connexions de base de
Visualisation d’un ensemble de données . . 18-6
données et de session . . . . . . . . . . . 18-32
Activation de l’édition d’un ensemble de
Utilisation des propriétés
données . . . . . . . . . . . . . . . . . . . . 18-7
DatabaseName et SessionName . . . 18-33
Activation de l’insertion de nouveaux
Utilisation des propriétés de handle
enregistrements . . . . . . . . . . . . . . . . 18-8
BDE . . . . . . . . . . . . . . . . . . . 18-33
Activation de recherches indexées et
Utilisation d’un composant fournisseur . 18-34
définition de portées . . . . . . . . . . . . . 18-9
Utilisation des mises à jour en mémoire
Champs calculés . . . . . . . . . . . . . . . . 18-9
cache . . . . . . . . . . . . . . . . . . . . 18-34
Filtrage d’enregistrements . . . . . . . . . 18-10
Mise en mémoire cache des BLOB . . . . 18-35
Mise à jour d’enregistrements . . . . . . . 18-10
Navigation dans les ensembles de données . 18-10
Utilisation des méthodes First et Last . . . 18-11
Chapitre 19
Utilisation des méthodes Next et Prior . . 18-12 Manipulation des composants
Utilisation de la méthode MoveBy . . . . 18-12 champ 19-1
Utilisation des propriétés Eof et Bof. . . . 18-13 Présentation des composants champ. . . . . . 19-2
Eof . . . . . . . . . . . . . . . . . . . . . 18-13 Champs dynamiques . . . . . . . . . . . . . 19-3
Bof . . . . . . . . . . . . . . . . . . . . . 18-14 Champs persistants . . . . . . . . . . . . . . 19-4
Marquage d’enregistrements . . . . . . . . 18-15 Création de champs persistants. . . . . . . . . 19-6
Recherche dans les ensembles de données . . 18-16 Modification de l’ordre des champs
Utilisation de la méthode Locate. . . . . . 18-17 persistants . . . . . . . . . . . . . . . . . . . . 19-7
Utilisation de la méthode Lookup . . . . . 18-18 Définition de nouveaux champs persistants . 19-7
Affichage et édition d’ensembles de Définition d’un champ de données . . . . . 19-9
données en utilisant des filtres. . . . . . . . 18-19 Définition d’un champ calculé . . . . . . 19-10
Activation et désactivation des filtres . . . 18-19 Programmation d’un champ calculé . . . 19-10
Création de filtres . . . . . . . . . . . . . . 18-19 Définition d’un champ de référence . . . .19-11
Définition de la propriété Filter . . . . . . 18-20 Définition d’un champ agrégat . . . . . . 19-13
Ecriture d’un gestionnaire d’événement Suppression de champs persistants. . . . 19-14
OnFilterRecord . . . . . . . . . . . . . . . 18-21 Définition des événements et des propriétés
Permutation entre les gestionnaires des champs persistants. . . . . . . . . . . . 19-14
d’événement filtre à l’exécution. . . . 18-22 Définition des propriétés d’affichage et
Définition d’options de filtre . . . . . . . . 18-22 d’édition en mode conception . . . . . . 19-15
x
Définition des propriétés des composants Chapitre 20
champ à l’exécution . . . . . . . . . . . . 19-16
Création d’ensembles d’attributs pour
Manipulation des tables 20-1
Utilisation des composants table . . . . . . . . 20-1
les composants champ . . . . . . . . . . . 19-17
Configuration d’un composant table. . . . . . 20-2
Association des ensembles d’attributs
Spécification de l’emplacement d’une base
aux composants champ . . . . . . . . . . 19-17
de données . . . . . . . . . . . . . . . . . . 20-2
Suppression des associations d’ensembles
Spécification d’un nom de table. . . . . . . 20-3
d’attributs . . . . . . . . . . . . . . . . . . 19-18
Spécification du type des tables locales . . 20-3
Contrôle ou dissimulation de la saisie
Ouverture et fermeture d’une table. . . . . 20-4
utilisateur . . . . . . . . . . . . . . . . . . 19-18
Contrôle des privilèges d’écriture / lecture
Utilisation des formats par défaut pour
d’une table . . . . . . . . . . . . . . . . . . . . 20-5
les champs numériques, date et heure . 19-19
Recherche d’enregistrements . . . . . . . . . . 20-5
Gestion des événements. . . . . . . . . . . 19-20
Recherche d’enregistrements à partir des
Manipulation des méthodes de champ lors
champs indexés . . . . . . . . . . . . . . . 20-6
de l’exécution. . . . . . . . . . . . . . . . . . 19-20
Exécution d’une recherche avec les
Affichage, conversion et accès aux valeurs
méthodes Goto . . . . . . . . . . . . . . 20-7
des champs . . . . . . . . . . . . . . . . . . . 19-21
Exécution d’une recherche avec les
Affichage de valeurs dans les contrôles
méthodes Find . . . . . . . . . . . . . . 20-8
standard . . . . . . . . . . . . . . . . . . . 19-21
Spécification de l’enregistrement en cours
Conversion des valeurs de champs . . . . 19-22
après une recherche . . . . . . . . . . . . . 20-8
Accès à des valeurs par la propriété
Recherche sur des clés partielles . . . . . . 20-8
d’ensemble de données par défaut . . . 19-23
Recherche avec un index secondaire . . . . 20-9
Accès à des valeurs par la propriété
Réitération ou extension d’une recherche . 20-9
Fields d’un ensemble de données . . . . 19-23
Tri d’enregistrements . . . . . . . . . . . . . . 20-10
Accès à des valeurs par la méthode
Extraction d’une liste d’index disponibles
FieldByName d’un ensemble de
avec GetIndexNames . . . . . . . . . . . 20-10
données . . . . . . . . . . . . . . . . . . . 19-24
Spécification d’un index secondaire avec
Vérification de la valeur en cours d’un
IndexName . . . . . . . . . . . . . . . . . 20-10
champ . . . . . . . . . . . . . . . . . . . . . . 19-25
Spécification d’un fichier d’index
Définition de la valeur par défaut d’un
dBASE . . . . . . . . . . . . . . . . . . 20-10
champ . . . . . . . . . . . . . . . . . . . . . . 19-25
Spécification d’un ordre de tri pour les
Utilisation de contraintes . . . . . . . . . . . . 19-25
tables SQL . . . . . . . . . . . . . . . . . .20-11
Création d’une contrainte personnalisée . 19-25
Spécification de champs avec
Utilisation des contraintes de serveur . . . 19-26
IndexFieldNames . . . . . . . . . . . .20-11
Utilisation des champs objet . . . . . . . . . . 19-27
Vérification de la liste de champs d’un
Affichage des champs ADT et tableau . . 19-27
index . . . . . . . . . . . . . . . . . . . . 20-12
Utilisation des champs ADT . . . . . . . . 19-28
Manipulation d’un sous-ensemble de
Accès aux valeurs de champ ADT . . . 19-28
données. . . . . . . . . . . . . . . . . . . . . 20-12
Utilisation des champs tableau. . . . . . . 19-29
Présentation des différences entre les
Accès aux valeurs de champs tableau . 19-30
portées et les filtres . . . . . . . . . . . . 20-12
Utilisation des champs ensemble de
Création et application d’une nouvelle
données . . . . . . . . . . . . . . . . . . . 19-31
portée . . . . . . . . . . . . . . . . . . . . 20-13
Affichage des champs ensemble de
Définition des valeurs de début de
données . . . . . . . . . . . . . . . . . 19-31
portée . . . . . . . . . . . . . . . . . . 20-13
Accès aux données d’un ensemble de
Définition des valeurs de fin de
données imbriqué. . . . . . . . . . . . 19-31
portée . . . . . . . . . . . . . . . . . . 20-14
Utilisation de champs de référence . . . . 19-31
Définition des valeurs de début et de
Affichage des champs de référence . . 19-32
fin de portée . . . . . . . . . . . . . . 20-15
Accès aux données d’un champ de
référence . . . . . . . . . . . . . . . . . 19-32
xi
Spécification d’une portée à partir de Utilisation d’un composant requête . . . . . . 21-4
clés partielles . . . . . . . . . . . . . . 20-16 Spécification de l’instruction SQL à exécuter . 21-6
Inclusion ou exclusion d’enregis- Spécification de la propriété SQL en phase
trements correspondant aux valeurs de conception . . . . . . . . . . . . . . . . 21-7
d’une portée . . . . . . . . . . . . . . . 20-16 Spécification d’une instruction SQL à
Application d’une portée . . . . . . . . 20-16 l’exécution . . . . . . . . . . . . . . . . . . 21-7
Annulation d’une portée . . . . . . . . 20-17 Définition directe de la propriété SQL . 21-8
Modification d’une portée . . . . . . . . . 20-17 Chargement de la propriété SQL
Modification du début de la portée . . 20-17 depuis un fichier . . . . . . . . . . . . . 21-8
Modification de la fin de la portée . . . 20-18 Chargement de la propriété SQL
Suppression de tous les enregistrements depuis un objet liste de chaînes . . . . 21-9
d’une table . . . . . . . . . . . . . . . . . . . 20-18 Définition de paramètres . . . . . . . . . . . . 21-9
Suppression d’une table . . . . . . . . . . . . 20-18 Attribution de paramètres en phase de
Changement du nom d’une table . . . . . . . 20-18 conception . . . . . . . . . . . . . . . . . 21-10
Création d’une table. . . . . . . . . . . . . . . 20-19 Affectation de paramètres en phase
Importation des données d’une autre table . 20-21 d’exécution . . . . . . . . . . . . . . . . . .21-11
Utilisation de TBatchMove . . . . . . . . . . . 20-22 Utilisation d’une source de données pour
Création d’un composant action lier les paramètres . . . . . . . . . . . . . .21-11
groupée . . . . . . . . . . . . . . . . . . . 20-22 Exécution d’une requête . . . . . . . . . . . . 21-13
Spécification d’un mode d’action Exécution d’une requête pendant la
groupée . . . . . . . . . . . . . . . . . . . 20-23 conception . . . . . . . . . . . . . . . . . 21-13
Ajout . . . . . . . . . . . . . . . . . . . . 20-24 Exécution d’une requête pendant
Mise à jour. . . . . . . . . . . . . . . . . 20-24 l’exécution . . . . . . . . . . . . . . . . . 21-14
Ajout et mise à jour . . . . . . . . . . . 20-24 Exécution d’une requête renvoyant
Copie . . . . . . . . . . . . . . . . . . . . 20-24 un ensemble de résultats . . . . . . . 21-14
Suppression . . . . . . . . . . . . . . . . 20-25 Exécution d’une requête sans
Etablissement d’une correspondance ensemble de résultats . . . . . . . . . 21-15
entre les types de données . . . . . . . . 20-25 Préparation d’une requête . . . . . . . . . . . 21-15
Exécution d’une action groupée . . . . . . 20-26 Réinitialisation de la préparation d’une
Gestion des erreurs relatives aux actions requête . . . . . . . . . . . . . . . . . . . . . 21-15
groupées . . . . . . . . . . . . . . . . . . . 20-26 Création de requêtes hétérogènes . . . . . . 21-16
Synchronisation de tables liées à la même Amélioration des performances d’une
table . . . . . . . . . . . . . . . . . . . . . . . 20-27 requête . . . . . . . . . . . . . . . . . . . . . 21-17
Création de fiches maître-détail . . . . . . . . 20-28 Désactivation des curseurs
Construction d’une fiche maître-détail bidirectionnels . . . . . . . . . . . . . . . 21-17
exemple . . . . . . . . . . . . . . . . . . . 20-28 Manipulation des ensembles de résultats . . 21-17
Utilisation des tables imbriquées . . . . . . . 20-29 Activation de l’édition d’un ensemble de
Configuration d’un composant table résultats. . . . . . . . . . . . . . . . . . . 21-18
imbriquée . . . . . . . . . . . . . . . . . . 20-30 Utilisation de SQL local avec les
ensembles de résultats modifiables . . . 21-18
Chapitre 21 Restrictions relatives aux requêtes
Manipulation des requêtes 21-1 modifiables . . . . . . . . . . . . . . . 21-18
Pour une utilisation efficace des requêtes . . . 21-1 Utilisation de SQL sur serveur distant
Informations pour les développeurs avec les ensembles de résultats
d’applications de bureau . . . . . . . . . . 21-2 modifiables . . . . . . . . . . . . . . . . . 21-19
Informations pour les développeurs Restrictions sur la mise à jour d’un
d’applications sur serveur. . . . . . . . . . 21-3 ensemble de résultats modifiable . . . . 21-19
Bases de données accessibles par un Mise à jour d’un ensemble de résultats
composant requête . . . . . . . . . . . . . . . . 21-4 en lecture seulement . . . . . . . . . . . 21-19
xii
Chapitre 22 Chapitre 23
Manipulation Création et utilisation d’un
des procédures stockées 22-1 ensemble de données client 23-1
Quand utiliser les procédures stockées ? . . . . 22-2 Manipulation des données avec un
Utilisation de procédures stockées . . . . . . . 22-3 ensemble de données client . . . . . . . . . . 23-2
Création d’un composant procédure Navigation parmi les données des
stockée . . . . . . . . . . . . . . . . . . . . . 22-4 ensembles de données client. . . . . . . . 23-2
Création d’une procédure stockée . . . . . . 22-5 Limitation des enregistrements affichés . . 23-3
Préparation et exécution d’une procédure Représentation des relations
stockée . . . . . . . . . . . . . . . . . . . . . 22-5 maître/détail . . . . . . . . . . . . . . . . . 23-3
Utilisation de procédures stockées qui Définition de contraintes pour les valeurs
renvoient des ensembles de résultats . . . 22-6 des données . . . . . . . . . . . . . . . . . 23-4
Extraction d’un ensemble de résultat Comment déclarer des données en lecture
avec un composant TQuery . . . . . . . 22-6 seulement. . . . . . . . . . . . . . . . . . . 23-5
Extraction d’un ensemble de résultat Edition des données . . . . . . . . . . . . . 23-5
avec un composant TStoredProc . . . . 22-7 Annulation des modifications . . . . . . 23-6
Utilisation de procédures stockées qui Enregistrement des modifications . . . . 23-6
renvoient des données à l’aide de Tri et indexation . . . . . . . . . . . . . . . . 23-7
paramètres. . . . . . . . . . . . . . . . . . . 22-8 Ajout d’un nouvel index . . . . . . . . . 23-8
Extraction de valeurs individuelles Suppression et permutation d’index . . 23-8
avec un composant TQuery . . . . . . . 22-8 Utilisation des index pour regrouper
Extraction de valeurs individuelles les données . . . . . . . . . . . . . . . . 23-9
avec un composant TStoredProc . . . . 22-9 Indexation à la volée . . . . . . . . . . 23-10
Utilisation de procédures stockées pour Représentation des valeurs calculées . . . 23-10
manipuler les données. . . . . . . . . . . . 22-9 Utilisation de champs calculés de
Exécution d’une procédure stockée façon interne dans les ensembles
d’action avec un composant de données client . . . . . . . . . . . 23-10
TQuery . . . . . . . . . . . . . . . . . . 22-10 Utilisation des agrégats maintenus . . . . .23-11
Exécution d’une procédure stockée Spécification d’agrégats. . . . . . . . . .23-11
d’action avec un composant Agrégats de groupes d’enregis-
TStoredProc . . . . . . . . . . . . . . . 22-10 trements . . . . . . . . . . . . . . . . . 23-13
Présentation des paramètres des procédures Obtention de valeurs d’agrégat . . . . 23-13
stockées . . . . . . . . . . . . . . . . . . . . . 22-11 Ajout d’informations d’application aux
Utilisation des paramètres d’entrée . . . . 22-12 données . . . . . . . . . . . . . . . . . . . 23-14
Utilisation des paramètres de sortie . . . . 22-13 Copie de données d’un autre ensemble de
Utilisation des paramètres d’entrée/ données. . . . . . . . . . . . . . . . . . . . . 23-14
sortie . . . . . . . . . . . . . . . . . . . . . 22-13 Affectation directe des données . . . . . . 23-15
Utilisation du paramètre résultat . . . . . 22-14 Clonage d’un curseur d’ensemble de
Accès aux paramètres en mode données client . . . . . . . . . . . . . . . 23-16
conception . . . . . . . . . . . . . . . . . . 22-14 Utilisation d’un ensemble de données client
Définition des informations sur les avec un fournisseur de données . . . . . . 23-16
paramètres à la conception . . . . . . . . 22-15 Spécification d’un fournisseur de
Création de paramètres en mode données . . . . . . . . . . . . . . . . . . . 23-16
exécution . . . . . . . . . . . . . . . . . . 22-16 Transmission de paramètres au serveur
Liaison de paramètres . . . . . . . . . . . . 22-17 d’applications . . . . . . . . . . . . . . . 23-17
Visualisation des informations sur les Envoi de paramètres de requête ou
paramètres à la conception . . . . . . . . . . 22-18 de procédure stockée . . . . . . . . . 23-18
Manipulation des procédures stockées Limitation des enregistrements avec
surchargées . . . . . . . . . . . . . . . . . . . 22-19 des paramètres . . . . . . . . . . . . . 23-18
xiii
Extraction des données depuis un serveur Utilisation d’objets mise à jour pour mettre
d’applications . . . . . . . . . . . . . . . . 23-18 à jour un ensemble de données . . . . . . . 24-13
Application de mises à jour à la base de Spécification de la propriété UpdateObject
données . . . . . . . . . . . . . . . . . . . 23-20 d’un ensemble de données . . . . . . . . 24-13
Utilisation d’un ensemble de données client Utilisation d’un seul objet mise à
avec des données de fichier linéaire. . . . . 23-21 jour. . . . . . . . . . . . . . . . . . . . 24-14
Création d’un nouvel ensemble de Utilisation de plusieurs objets mise à
données . . . . . . . . . . . . . . . . . . . 23-21 jour. . . . . . . . . . . . . . . . . . . . 24-14
Chargement des données depuis un Création d’instructions SQL pour les
fichier ou un flux . . . . . . . . . . . . . . 23-21 composants mise à jour. . . . . . . . . . 24-15
Fusion des modifications dans les Création d’instructions SQL lors de la
données . . . . . . . . . . . . . . . . . . . 23-22 conception . . . . . . . . . . . . . . . 24-16
Sauvegarde des données dans un fichier Substitution des paramètres dans les
ou un flux . . . . . . . . . . . . . . . . . . 23-22 instructions SQL de mise à jour . . . 24-17
Elaboration des instructions SQL de
Chapitre 24 mise à jour . . . . . . . . . . . . . . . 24-18
Manipulation des mises à jour Utilisation de la propriété Query d’un
composant mise à jour . . . . . . . . 24-19
en mémoire cache 24-1 Utilisation des propriétés DeleteSQL,
Quand utiliser les mises à jour en mémoire
InsertSQL et ModifySQL . . . . . . . 24-20
cache ? . . . . . . . . . . . . . . . . . . . . . . . 24-1
Exécution des instructions de mise à
Utilisation des mises à jour en mémoire
jour . . . . . . . . . . . . . . . . . . . . . 24-21
cache . . . . . . . . . . . . . . . . . . . . . . . . 24-2
Appel de la méthode Apply . . . . . . 24-21
Activation et désactivation des mises à
Appel de la méthode SetParams . . . 24-22
jour en mémoire cache. . . . . . . . . . . . 24-3
Appel de la méthode ExecSQL . . . . 24-23
Extraction d’enregistrements . . . . . . . . . 24-4
Utilisation de composants ensemble de
Application des mises à jour en mémoire
données pour mettre à jour un
cache . . . . . . . . . . . . . . . . . . . . . . 24-5
ensemble de données . . . . . . . . . . . 24-24
Utilisation de la méthode d’un
Mise à jour d’un ensemble de résultat en
composant base de données. . . . . . . 24-6
lecture seule . . . . . . . . . . . . . . . . . . 24-25
Utilisation des méthodes d’un
Contrôle du processus de mise à jour . . . . 24-25
composant ensemble de données . . . . 24-7
Détermination de la nécessité de
Application des mises à jour à des
contrôler le processus de mise à jour . . 24-26
tables maître / détail . . . . . . . . . . . 24-8
Création d’un gestionnaire d’événement
Annulation des mises à jour en mémoire
OnUpdateRecord . . . . . . . . . . . . . 24-26
cache en suspens . . . . . . . . . . . . . . . 24-9
Gestion des erreurs de mise à jour en
Annulation des mises à jour en
mémoire cache. . . . . . . . . . . . . . . . . 24-28
suspens et désactivation des mises à
Référencement de l’ensemble de
jour suivantes . . . . . . . . . . . . . . . 24-9
données à mettre à jour . . . . . . . . . 24-28
Annulation des mises à jour en
Indication du type de mise à jour ayant
mémoire cache en suspens . . . . . . . 24-9
généré l’erreur . . . . . . . . . . . . . . . 24-28
Annulation des mises à jour apportées
Spécification de l’action à entreprendre . 24-29
à l’enregistrement en cours . . . . . . 24-10
Manipulation du texte d’un message
Récupération d’enregistrements en
d’erreur . . . . . . . . . . . . . . . . . . . 24-30
mémoire cache . . . . . . . . . . . . . . . 24-10
Accès aux propriétés OldValue,
Spécification des enregistrements
NewValue et CurValue d’un champ . . 24-31
visibles en mémoire cache. . . . . . . . . 24-11
Vérification de l’état de la mise à jour . . 24-12
xiv
Chapitre 25 Spécification d’une liste d’après une
Utilisation de contrôles de données 25-1 source de données secondaire . . . . 25-15
Propriétés des boîtes liste et des
Fonctionnalités communes des contrôles de
boîtes à options de référence . . . . . 25-16
données . . . . . . . . . . . . . . . . . . . . . . 25-1
Recherche incrémentale dans les
Association d’un contrôle de données à
valeurs d’une liste d’éléments . . . . 25-16
un ensemble de données . . . . . . . . . . 25-3
Manipulation de champs booléens avec
Edition et mise à jour des données . . . . . 25-3
des cases à cocher . . . . . . . . . . . . . 25-16
Activation de l’édition des contrôles
Limitation de valeurs de champ avec
lors d’une saisie utilisateur . . . . . . . 25-3
des boutons radio . . . . . . . . . . . . . 25-17
Edition des données affichées dans un
Visualisation et édition des données avec
contrôle. . . . . . . . . . . . . . . . . . . 25-4
un contrôle TDBGrid . . . . . . . . . . . . . 25-18
Activation et désactivation de l’affichage
Utilisation d’un contrôle grille à son état
des données . . . . . . . . . . . . . . . . . . 25-5
par défaut . . . . . . . . . . . . . . . . . 25-19
Rafraîchissement de l’affichage des
Création d’une grille personnalisée. . . . 25-20
données . . . . . . . . . . . . . . . . . . . . 25-5
Présentation des colonnes
Activation des événements souris, clavier
persistantes . . . . . . . . . . . . . . . 25-20
et timer . . . . . . . . . . . . . . . . . . . . 25-6
Détermination de la source d’une
Utilisation des sources de données . . . . . . . 25-6
propriété de colonne à l’exécution. . 25-21
Utilisation des propriétés de TDataSource . 25-6
Création de colonnes persistantes . . . 25-22
Propriété DataSet . . . . . . . . . . . . . . 25-7
Suppression de colonnes persistantes. 25-23
Propriété Name . . . . . . . . . . . . . . . 25-7
Modification de l’ordre des colonnes
Propriété Enabled. . . . . . . . . . . . . . 25-7
persistantes . . . . . . . . . . . . . . . 25-23
Propriété AutoEdit . . . . . . . . . . . . . 25-8
Définition d’une colonne de liste de
Utilisation des événements de
référence . . . . . . . . . . . . . . . . 25-23
TDataSource. . . . . . . . . . . . . . . . . . 25-8
Définition d’une colonne de liste de
Evénement OnDataChange . . . . . . . . 25-8
choix . . . . . . . . . . . . . . . . . . . 25-24
Evénement OnUpdateData . . . . . . . . 25-8
Insertion d’un bouton dans une
Evénement OnStateChange . . . . . . . . 25-8
colonne . . . . . . . . . . . . . . . . . 25-24
Contrôles représentant un champ unique . . . 25-9
Définition des propriétés de colonne
Affichage de données en tant que libellés . 25-9
en mode conception . . . . . . . . . . 25-24
Affichage et édition de champs dans une
Restauration des valeurs par défaut
boîte de saisie . . . . . . . . . . . . . . . . 25-10
d’une colonne . . . . . . . . . . . . . 25-26
Affichage et édition de texte dans un
Affichage des champs ADT et tableau . . 25-26
contrôle mémo . . . . . . . . . . . . . . . 25-10
Définition des options de la grille . . . . 25-27
Affichage et édition dans un contrôle
Saisie de modifications dans la grille. . . 25-29
mémo de texte formaté . . . . . . . . . . 25-11
Changement de l’ordre des colonnes à la
Affichage et édition de champs
conception . . . . . . . . . . . . . . . . . 25-29
graphiques dans un contrôle image . . . 25-12
Changement de l’ordre des colonnes à
Affichage de données dans des boîtes
l’exécution . . . . . . . . . . . . . . . . . 25-29
liste et des boîtes à options . . . . . . . . 25-12
Contrôle du dessin de la grille . . . . 25-30
Affichage et édition de données dans
Comment répondre aux actions de
une boîte liste . . . . . . . . . . . . . . 25-13
l’utilisateur à l’exécution . . . . . . . . . 25-30
Affichage et édition de données dans
Création d’une grille contenant d’autres
une boîte à options . . . . . . . . . . . 25-13
contrôles orientés données. . . . . . . . . . 25-31
Affichage dans une boîte liste de
Navigation et manipulation d’enregis-
référence et une boîte à options de
trements . . . . . . . . . . . . . . . . . . . . 25-33
référence . . . . . . . . . . . . . . . . . . . 25-14
Choix des boutons visibles. . . . . . . . . 25-34
Spécification d’une liste basée sur un
champ de référence . . . . . . . . . . . 25-15
xv
Affichage et dissimulation des boutons Réorganisation des lignes et des
en mode conception . . . . . . . . . . 25-34 colonnes d’une grille de décision . . 26-13
Affichage et dissimulation des boutons Perforation pour voir les détails dans
à l’exécution . . . . . . . . . . . . . . . 25-34 les grilles de décision . . . . . . . . . 26-13
Affichage de panneaux d’information. . . 25-35 Limite des dimensions à sélectionner
Utilisation d’un navigateur pour dans les grilles de décision . . . . . . 26-13
plusieurs ensembles de données . . . . . 25-35 Propriétés des grilles de décision . . . . . 26-14
Création et utilisation de graphes de
Chapitre 26 décision. . . . . . . . . . . . . . . . . . . . . 26-15
Utilisation de composants d’aide Création de graphes de décision . . . . . 26-15
Utilisation de graphes de décision . . . . 26-15
à la décision 26-1 Affichage du graphe de décision . . . . . 26-17
Présentation . . . . . . . . . . . . . . . . . . . . 26-1
Personnalisation du graphe de décision . 26-17
Présentation des références croisées. . . . . . . 26-2
Définition des modèles de graphe de
Références croisées à une dimension . . . . 26-3
décision par défaut . . . . . . . . . . 26-18
Références croisées à plusieurs
Personnalisation des séries d’un
dimensions . . . . . . . . . . . . . . . . . . 26-3
graphe de décision. . . . . . . . . . . 26-19
Instructions relatives à l’utilisation de
Utilisation des composants d’aide à la
composants d’aide à la décision . . . . . . . . 26-3
décision à l’exécution. . . . . . . . . . . . . 26-20
Utilisation d’ensembles de données avec les
Pivots de décision à l’exécution . . . . . . 26-20
composants d’aide à la décision . . . . . . . . 26-5
Grilles de décision à l’exécution . . . . . 26-21
Création d’ensembles de données de
Graphes de décision à l’exécution . . . . 26-21
décision avec TQuery ou TTable . . . . . . 26-6
Considérations relatives au contrôle de la
Création d’ensembles de données de
mémoire . . . . . . . . . . . . . . . . . . . . 26-21
décision avec l’éditeur de requête de
Définition du maximum de dimensions,
décision . . . . . . . . . . . . . . . . . . . . 26-6
de champs récapitulatifs, et de cellules 26-22
Utilisation de l’éditeur de requête de
Définition de l’état des dimensions. . . . 26-22
décision . . . . . . . . . . . . . . . . . . 26-7
Utilisation de dimensions paginées. . . . 26-23
Propriétés d’une requête de décision . . . . 26-7
Utilisation des cubes de décision . . . . . . . . 26-8
Propriétés et événements des cubes de
Partie III
décision . . . . . . . . . . . . . . . . . . . . 26-8 Ecriture d’applications distribuées
Utilisation de l’éditeur de cube de
décision . . . . . . . . . . . . . . . . . . . . 26-8 Chapitre 27
Visualisation et modification des Ecriture d’applications CORBA 27-1
paramètres de dimensions. . . . . . . . 26-9 Vue générale d’une application CORBA. . . . 27-2
Définition du maximum de dimensions Stubs et squelettes. . . . . . . . . . . . . . . 27-2
et de récapitulations . . . . . . . . . . . 26-9 Utilisation de Smart Agents . . . . . . . . . 27-3
Visualisation et modification des Activation d’applications serveur. . . . . . 27-4
options de conception . . . . . . . . . 26-10 Liaison dynamique d’appels d’interfaces . 27-4
Utilisation de sources de décision . . . . . . . 26-10 Ecriture de serveurs CORBA . . . . . . . . . . 27-5
Propriétés et événements . . . . . . . . . . 26-10 Utilisation des experts CORBA . . . . . . . 27-5
Utilisation de pivots de décision . . . . . . . 26-11 Définition d’interfaces d’objets . . . . . . . 27-6
Propriétés des pivots de décision . . . . . 26-11 Code généré automatiquement . . . . . . . 27-8
Création et utilisation de grilles de Recensement d’interfaces serveur. . . . . . 27-8
décision . . . . . . . . . . . . . . . . . . . . . 26-12 Recensement d’interfaces avec le
Création de grilles de décision . . . . . . . 26-12 référentiel d’interfaces. . . . . . . . . . 27-9
Utilisation de grilles de décision . . . . . . 26-12 Recensement d’interfaces avec l’Object
Ouverture et fermeture des champs Activation Daemon . . . . . . . . . . 27-10
d’une grille de décision . . . . . . . . 26-12
xvi
Ecriture de clients CORBA . . . . . . . . . . . 27-12 Type de méthode de requête . . . . . . 28-10
Utilisation de stubs . . . . . . . . . . . . . 27-13 Activation et désactivation des
Utilisation de l’interface d’appel éléments d’action . . . . . . . . . . . .28-11
dynamique . . . . . . . . . . . . . . . . . 27-14 Choix d’un élément d’action par
Obtention de l’interface . . . . . . . . . 27-14 défaut . . . . . . . . . . . . . . . . . . .28-11
Appel d’interfaces avec DII . . . . . . . 27-15 Réponse aux messages de requête avec
Personnalisation d’applications CORBA . . . 27-16 des éléments d’action . . . . . . . . . . . 28-12
Affichage d’objets dans l’interface Envoi de la réponse . . . . . . . . . . . 28-12
utilisateur . . . . . . . . . . . . . . . . . . 27-16 Utilisation de plusieurs éléments
Présentation et dissimulation d’objets d’action . . . . . . . . . . . . . . . . . 28-12
CORBA . . . . . . . . . . . . . . . . . . . 27-17 Accès aux informations de requêtes client . 28-13
Transmission d’informations client à des Propriétés contenant des informations
objets serveur . . . . . . . . . . . . . . . . 27-17 d’en-tête de requête . . . . . . . . . . . . 28-13
Déploiement d’applications CORBA . . . . . 27-17 Propriétés identifiant la destination. . 28-13
Configuration de Smart Agents . . . . . . 27-19 Propriétés décrivant le client Web. . . 28-13
Démarrage du Smart Agent. . . . . . . 27-19 Propriétés identifiant le but de la
Configuration de domaines ORB . . . . 27-19 requête . . . . . . . . . . . . . . . . . 28-14
Connexion de Smart Agents avec Propriétés décrivant la réponse
d’autres réseaux locaux . . . . . . . . 27-20 attendue . . . . . . . . . . . . . . . . . 28-14
Propriétés décrivant le contenu . . . . 28-14
Chapitre 28 Contenu d’un message de requête
Création d’applications serveur HTTP . . . . . . . . . . . . . . . . . . . . 28-15
Création de messages de réponse HTTP . . 28-15
pour Internet 28-1 Informations d’en-tête de réponse . . . . 28-15
Terminologie et standard . . . . . . . . . . . . . 28-1
Indication du statut de la réponse . . 28-15
Composition d’un URL (Uniform Resource
Indication d’attente d’une action du
Locator) . . . . . . . . . . . . . . . . . . . . 28-2
client . . . . . . . . . . . . . . . . . . . 28-16
URI et URL . . . . . . . . . . . . . . . . . 28-2
Description de l’application serveur . 28-16
En-tête de message de requête HTTP . . . . 28-2
Description du contenu . . . . . . . . . 28-16
Activité d’un serveur HTTP . . . . . . . . . . . 28-3
Définition du contenu de la réponse . . . 28-16
Composition des requêtes client . . . . . . . 28-3
Envoi de la réponse. . . . . . . . . . . . . 28-17
Traitement des requêtes client par le
Génération du contenu des messages de
serveur . . . . . . . . . . . . . . . . . . . . . 28-4
réponse . . . . . . . . . . . . . . . . . . . . . 28-17
Réponses aux requêtes client . . . . . . . . . 28-4
Utilisation du composant générateur de
Applications serveur Web . . . . . . . . . . . . 28-5
page . . . . . . . . . . . . . . . . . . . . . 28-18
Types d’applications serveur Web . . . . . . 28-5
Modèles HTML . . . . . . . . . . . . . 28-18
ISAPI et NSAPI . . . . . . . . . . . . . . . 28-5
Choix du modèle HTML . . . . . . . . 28-19
CGI autonome . . . . . . . . . . . . . . . 28-5
Conversion des balises HTML
Win-CGI autonome. . . . . . . . . . . . . 28-5
transparentes . . . . . . . . . . . . . . 28-19
Création d’applications serveur Web . . . . 28-6
Utilisation du générateur de page
Le module Web. . . . . . . . . . . . . . . . . 28-6
depuis un élément d’action. . . . . . 28-20
L’objet application Web . . . . . . . . . . . . 28-7
Chaînage de générateurs de page . . . 28-20
Structure d’une application serveur Web. . . . 28-7
Utilisation des bases de données dans les
Le répartiteur Web. . . . . . . . . . . . . . . . . 28-8
réponses . . . . . . . . . . . . . . . . . . . . 28-21
Ajout d’actions au répartiteur . . . . . . . . 28-9
Ajout d’une session au module Web . . . 28-21
Répartition des messages de requête . . . . 28-9
Représentation HTML d’une base de
Eléments d’action . . . . . . . . . . . . . . . . 28-10
données . . . . . . . . . . . . . . . . . . . 28-22
Choix des propriétés d’un élément
Utilisation des générateurs de page
d’action . . . . . . . . . . . . . . . . . . . 28-10
ensemble de données . . . . . . . . . 28-22
URL de destination. . . . . . . . . . . . 28-10
xvii
Utilisation des générateurs de Ecoute des requêtes client . . . . . . . . 29-7
tableau . . . . . . . . . . . . . . . . . . 28-23 Connexion aux clients. . . . . . . . . . . 29-7
Choix des attributs de tableau . . . . . 28-23 Obtenir des informations sur les
Choix des attributs de lignes . . . . . . 28-23 connexions . . . . . . . . . . . . . . . . 29-8
Choix des attributs de colonnes . . . . 28-24 Fermeture des connexions serveur . . . 29-8
Incorporation de tableaux dans un Réponse aux événements socket . . . . . . . . 29-8
document HTML . . . . . . . . . . . . 28-24 Evénements d’erreurs. . . . . . . . . . . . . 29-9
Configuration d’un générateur de Evénements client . . . . . . . . . . . . . . . 29-9
tableau ensemble de données . . . . . 28-24 Evénements serveur . . . . . . . . . . . . 29-10
Configuration d’un générateur de Evénements d’écoute . . . . . . . . . . 29-10
tableau requête . . . . . . . . . . . . . 28-25 Evénements de connexions client . . . 29-10
Débogage d’applications serveur . . . . . . . 28-25 Lectures et écritures sur des connexions
Débogage d’applications ISAPI et socket . . . . . . . . . . . . . . . . . . . . . . .29-11
NSAPI . . . . . . . . . . . . . . . . . . . . 28-25 Connexions non bloquantes . . . . . . . . .29-11
Débogage sous Windows NT . . . . . . 28-26 Lecture et écriture d’événements . . . .29-11
Débogage avec Microsoft IIS Server . . 28-26 Connexions bloquantes. . . . . . . . . . . 29-12
Débogage avec Personal Web Server Utilisation de threads avec des
pour Windows 95 . . . . . . . . . . . . 28-26 connexions bloquantes . . . . . . . . 29-12
Débogage avec Netscape Server Utilisation de TWinSocketStream . . . 29-13
Version 2.0 . . . . . . . . . . . . . . . . 28-26 Ecriture de threads client . . . . . . . . 29-13
Débogage d’applications CGI et Ecriture de threads serveur . . . . . . 29-14
Win-CGI . . . . . . . . . . . . . . . . . . . 28-27
Simulation du serveur . . . . . . . . . . 28-27 Partie IV
Débogage en tant que DLL . . . . . . . 28-27 Création de composants
Chapitre 29 personnalisés
Utilisation des sockets 29-1
Implémentation des services . . . . . . . . . . . 29-1
Chapitre 30
Description des protocoles de services . . . 29-2 Présentation générale de la
Communication avec les applications . . 29-2 création d’un composant 30-1
Services et ports . . . . . . . . . . . . . . . . 29-2 La bibliothèque des composants visuels. . . . 30-1
Types de connexions par socket . . . . . . . . . 29-2 Composants et classes . . . . . . . . . . . . . . 30-2
Connexions client . . . . . . . . . . . . . . . 29-3 Comment créer un composant ? . . . . . . . . 30-2
Connexions d’écoute. . . . . . . . . . . . . . 29-3 Modification de contrôles existants . . . . . 30-3
Connexions serveur . . . . . . . . . . . . . . 29-3 Création de contrôles fenêtrés . . . . . . . . 30-4
Description des sockets . . . . . . . . . . . . . . 29-3 Création de contrôles graphiques . . . . . . 30-4
Description des hôtes . . . . . . . . . . . . . 29-4 Sous-classement de contrôles Windows . . 30-4
Choix entre le nom de l’hôte et son Création de composants non visuels . . . . 30-5
adresse IP . . . . . . . . . . . . . . . . . 29-4 Contenu d’un composant ? . . . . . . . . . . . 30-5
Utilisation des ports . . . . . . . . . . . . . . 29-5 Suppression des dépendances . . . . . . . . 30-5
Utilisation des composants socket. . . . . . . . 29-5 Propriétés, méthodes et événements . . . . 30-6
Utilisation de sockets client. . . . . . . . . . 29-6 Propriétés . . . . . . . . . . . . . . . . . . 30-6
Désignation du serveur souhaité . . . . . 29-6 Evénements. . . . . . . . . . . . . . . . . 30-7
Formation de la connexion . . . . . . . . 29-6 Méthodes . . . . . . . . . . . . . . . . . . 30-7
Obtention d’informations sur la Encapsulation des graphiques. . . . . . . . 30-7
connexion . . . . . . . . . . . . . . . . . 29-6 Recensement . . . . . . . . . . . . . . . . . . 30-8
Fermeture de la connexion . . . . . . . . 29-7 Création d’un nouveau composant. . . . . . . 30-8
Utilisation de sockets serveur . . . . . . . . 29-7 Utilisation de l’expert composant . . . . . . 30-9
Désignation du port . . . . . . . . . . . . 29-7
xviii
Création manuelle d’un composant . . . . 30-11 Création de propriétés tableau . . . . . . . . . 32-9
Création d’un fichier unité . . . . . . . 30-11 Stockage et chargement des propriétés . . . 32-10
Dérivation du composant . . . . . . . . 30-12 Utilisation du mécanisme de stockage
Recensement du composant. . . . . . . 30-12 et de chargement . . . . . . . . . . . . . 32-10
Test des composants non installés . . . . . . . 30-13 Spécification des valeurs par défaut . . . .32-11
Détermination du stockage . . . . . . . . .32-11
Chapitre 31 Initialisation après chargement . . . . . . 32-12
Programmation orientée objet
et écriture des composants 31-1 Chapitre 33
Définition de nouvelles classes . . . . . . . . . 31-2 Création d’événements 33-1
Dérivation de nouvelles classes . . . . . . . 31-2 Qu’est-ce qu’un événement ? . . . . . . . . . . 33-1
Modifier les valeurs par défaut d’une Les événements sont des pointeurs sur
classe pour éviter les répétitions . . . . 31-2 des méthodes . . . . . . . . . . . . . . . . 33-2
Ajout de nouvelles capacités à une Les événements sont des propriétés . . . . 33-2
classe . . . . . . . . . . . . . . . . . . . . 31-3 Les types d’événements sont des types
Déclaration d’une nouvelle classe de de pointeurs sur des méthodes . . . . . . 33-3
composant . . . . . . . . . . . . . . . . . . . 31-3 Les types gestionnaire d’événement
Ancêtres, descendants et hiérarchies des sont des procédures . . . . . . . . . . . 33-3
classes . . . . . . . . . . . . . . . . . . . . . . . 31-4 Les gestionnaires d’événements sont
Contrôle des accès . . . . . . . . . . . . . . . . . 31-4 facultatifs . . . . . . . . . . . . . . . . . . . 33-4
Masquer les détails d’implémentation . . . 31-5 Implémentation des événements standard . . 33-5
Définition de l’interface avec le concepteur Identification des événements standard . . 33-5
des composants . . . . . . . . . . . . . . . . 31-6 Evénements standard pour tous les
Définition de l’interface d’exécution. . . . . 31-6 contrôles. . . . . . . . . . . . . . . . . . 33-5
Définition de l’interface de conception . . . 31-7 Evénements standard pour les contrôles
Répartition des méthodes . . . . . . . . . . . . 31-8 standard. . . . . . . . . . . . . . . . . . 33-5
Méthodes statiques. . . . . . . . . . . . . . . 31-8 Rendre visibles des événements. . . . . . . 33-6
Méthodes virtuelles . . . . . . . . . . . . . . 31-9 Changement de la gestion des événements
Surcharge des méthodes . . . . . . . . . . 31-9 standard . . . . . . . . . . . . . . . . . . . 33-6
Membres abstraits d’une classe . . . . . . . . 31-10 Définition de vos propres événements. . . . . 33-7
Classes et pointeurs . . . . . . . . . . . . . . . 31-10 Déclenchement de l’événement . . . . . . . 33-7
Deux sortes d’événements . . . . . . . . 33-7
Chapitre 32 Définition du type de gestionnaire . . . . . 33-8
Notifications simples . . . . . . . . . . . 33-8
Création de propriétés 32-1 Gestionnaires d’événements
Pourquoi créer des propriétés ? . . . . . . . . . 32-1
spécifiques . . . . . . . . . . . . . . . . 33-8
Types de propriétés . . . . . . . . . . . . . . . . 32-2
Renvoi d’informations à partir du
Publication des propriétés héritées . . . . . . . 32-3
gestionnaire. . . . . . . . . . . . . . . . 33-8
Définition des propriétés . . . . . . . . . . . . . 32-4
Déclaration de l’événement . . . . . . . . . 33-9
Déclaration des propriétés . . . . . . . . . . 32-4
Les noms d’événement débutent par
Stockage interne des données . . . . . . . . 32-4
“On” . . . . . . . . . . . . . . . . . . . . 33-9
Accès direct . . . . . . . . . . . . . . . . . . . 32-5
Appel de l’événement . . . . . . . . . . . . 33-9
Méthodes d’accès. . . . . . . . . . . . . . . . 32-5
Les gestionnaires vides doivent être
Méthode read . . . . . . . . . . . . . . . . 32-7
valides . . . . . . . . . . . . . . . . . . . 33-9
Méthode write . . . . . . . . . . . . . . . 32-7
Les utilisateurs peuvent surcharger la
Valeurs par défaut d’une propriété . . . . . 32-8
gestion par défaut . . . . . . . . . . . 33-10
Spécification d’aucune valeur par
défaut. . . . . . . . . . . . . . . . . . . . 32-8
xix
Chapitre 34 Chapitre 37
Création de méthodes 34-1 Accessibilité des composants au
Eviter les interdépendances . . . . . . . . . . . 34-1 moment de la conception 37-1
Noms des méthodes. . . . . . . . . . . . . . . . 34-2 Recensement des composants. . . . . . . . . . 37-1
Protection des méthodes . . . . . . . . . . . . . 34-3 Déclaration de la procédure Register. . . . 37-2
Méthodes qui doivent être publiques . . . . 34-3 Ecriture de la procédure Register . . . . . . 37-2
Méthodes qui doivent être protégées . . . . 34-3 Spécification des composants . . . . . . 37-3
Méthodes abstraites . . . . . . . . . . . . . . 34-4 Spécification de la page de palette . . . 37-3
Rendre virtuelles des méthodes . . . . . . . . . 34-4 Utilisation de la fonction
Déclaration des méthodes . . . . . . . . . . . . 34-4 RegisterComponents . . . . . . . . . . 37-3
Ajout de bitmaps à la palette . . . . . . . . . . 37-4
Chapitre 35 Fournir l’aide pour vos composants . . . . . . 37-4
Graphiques et composants 35-1 Création du fichier d’aide . . . . . . . . . . 37-4
Présentation des graphiques . . . . . . . . . . . 35-1 Création des entrées. . . . . . . . . . . . 37-5
Utilisation du canevas . . . . . . . . . . . . . . 35-3 Aide contextuelle des composants . . . 37-6
Travail sur les images . . . . . . . . . . . . . . . 35-3 Ajout de fichiers d’aide à l’aide de
Utilisation d’une image, d’un graphique Delphi . . . . . . . . . . . . . . . . . . . 37-7
ou d’un canevas . . . . . . . . . . . . . . . 35-4 Ajout d’éditeurs de propriétés . . . . . . . . . 37-7
Chargement et stockage des graphiques . . 35-4 Dérivation d’une classe éditeur de
Gestion des palettes . . . . . . . . . . . . . . 35-5 propriétés. . . . . . . . . . . . . . . . . . . 37-7
Spécification d’une palette pour un Modification de la propriété sous une
contrôle. . . . . . . . . . . . . . . . . . . 35-6 forme textuelle . . . . . . . . . . . . . . . . 37-9
Réponse aux changements de palette . . 35-6 Affichage de la valeur de la propriété . 37-9
Bitmaps hors écran . . . . . . . . . . . . . . . . 35-6 Définition de la valeur de la propriété . 37-9
Création et gestion des bitmaps hors Modification globale de la propriété . . . 37-10
écran . . . . . . . . . . . . . . . . . . . . . . 35-6 Spécification des attributs de l’éditeur . . .37-11
Copie des images bitmap . . . . . . . . . . . 35-7 Recensement de l’éditeur de propriétés . 37-12
Réponse aux changements . . . . . . . . . . . . 35-7 Ajout d’éditeurs de composants . . . . . . . 37-13
Ajout d’éléments au menu contextuel . . 37-14
Chapitre 36 Spécification d’éléments de menu. . . 37-14
Gestion des messages 36-1 Implémentation des commandes . . . 37-15
Compréhension du système de gestion des Modification du comportement suite à
messages . . . . . . . . . . . . . . . . . . . . . 36-1 un double-clic . . . . . . . . . . . . . . . 37-15
Que contient un message Windows ? . . . . 36-2 Ajout de formats de Presse-papiers. . . . 37-16
Répartition des messages . . . . . . . . . . . 36-2 Recensement d’un éditeur de
Suivi du flux des messages . . . . . . . . 36-3 composants. . . . . . . . . . . . . . . . . 37-16
Modification de la gestion des messages . . . . 36-3 Compilation des composants en paquets . . 37-17
Surcharge de la méthode du gestionnaire . 36-4
Utilisation des paramètres d’un message . . 36-4 Chapitre 38
Interception des messages . . . . . . . . . . 36-4 Modification d’un composant
Création de nouveaux gestionnaires de existant 38-1
messages . . . . . . . . . . . . . . . . . . . . . 36-5 Création et recensement du composant . . . . 38-1
Définition de vos propres messages . . . . . 36-5 Modification de la classe composant. . . . . . 38-2
Déclaration d’un identificateur de Surcharge du constructeur . . . . . . . . . . 38-2
message . . . . . . . . . . . . . . . . . . 36-6 Spécification de la nouvelle valeur par
Déclaration d’un type d’enregistrement défaut de la propriété. . . . . . . . . . . . 38-3
de message . . . . . . . . . . . . . . . . 36-6
Déclaration d’une nouvelle méthode de
gestion d’un message . . . . . . . . . . . . 36-7
xx
Chapitre 39 Chapitre 41
Création d’un composant Contrôles orientés données 41-1
graphique 39-1 Création d’un contrôle pour scruter les
Création et recensement du composant . . . . 39-1 données. . . . . . . . . . . . . . . . . . . . . . 41-2
Publication des propriétés héritées . . . . . . . 39-2 Création et recensement du composant . . 41-2
Ajout de fonctionnalités graphiques . . . . . . 39-3 Fonctionnement du contrôle en lecture
Détermination de ce qui doit être dessiné . 39-3 seulement. . . . . . . . . . . . . . . . . . . 41-3
Déclaration du type de la propriété . . . 39-3 Ajout de la propriété ReadOnly . . . . . 41-3
Déclaration de la propriété . . . . . . . . 39-4 Autorisation des mises à jour
Ecriture de la méthode d’implémen- nécessaires . . . . . . . . . . . . . . . . 41-4
tation . . . . . . . . . . . . . . . . . . . . 39-4 Ajout du lien aux données. . . . . . . . . . 41-5
Surcharge du constructeur et du Déclaration de la donnée membre de la
destructeur . . . . . . . . . . . . . . . . . . 39-4 classe . . . . . . . . . . . . . . . . . . . 41-5
Modification des valeurs par défaut Déclaration des propriétés d’accès . . . 41-5
des propriétés . . . . . . . . . . . . . . . 39-4 Exemple de déclaration des propriétés
Publication du crayon et du pinceau . . . . 39-5 d’accès. . . . . . . . . . . . . . . . . . . 41-6
Déclaration des données membres . . . . 39-5 Initialisation du lien de données . . . . 41-6
Déclaration des propriétés d’accès . . . . 39-6 Réponse aux changements de données . . 41-7
Initialisation des classes ayant un Création d’un contrôle pour modifier les
propriétaire . . . . . . . . . . . . . . . . 39-7 données. . . . . . . . . . . . . . . . . . . . . . 41-8
Définition des propriétés des classes Modification de la valeur par défaut de
ayant un propriétaire . . . . . . . . . . . 39-7 FReadOnly . . . . . . . . . . . . . . . . . . 41-9
Dessin de l’image du composant . . . . . . 39-8 Gestion des messages liés à la souris ou
Adaptation du dessin de la forme . . . . . . 39-9 au clavier . . . . . . . . . . . . . . . . . . . 41-9
Réponse aux messages indiquant la
Chapitre 40 manipulation de la souris. . . . . . . . 41-9
Réponse aux messages indiquant la
Personnalisation d’une grille 40-1 manipulation du clavier . . . . . . . 41-10
Création et recensement du composant . . . . 40-1
Mise à jour de la classe lien de données
Publication des propriétés héritées . . . . . . . 40-2
sur un champ . . . . . . . . . . . . . . . .41-11
Modification des valeurs initiales . . . . . . . . 40-3
Modification de la méthode Change . . . 41-12
Redimensionnement des cellules . . . . . . . . 40-4
Mise à jour de l’ensemble de données . . 41-12
Remplissage des cellules . . . . . . . . . . . . . 40-5
Suivi de la date . . . . . . . . . . . . . . . . . 40-5
Stockage interne de la date . . . . . . . . 40-6
Chapitre 42
Accès au jour, au mois et à l’année . . . 40-6 Transformation d’une boîte de
Génération des numéros de jours . . . . 40-8 dialogue en composant 42-1
Sélection du jour en cours. . . . . . . . 40-10 Définition de l’interface du composant . . . . 42-2
Navigation de mois en mois et d’année en Création et recensement du composant . . . . 42-2
année . . . . . . . . . . . . . . . . . . . . . . 40-10 Création de l’interface du composant . . . . . 42-3
Navigation de jour en jour . . . . . . . . . . . 40-11 Inclusion des fichiers de l’unité de la
Déplacement de la sélection . . . . . . . . 40-11 fiche . . . . . . . . . . . . . . . . . . . . . . 42-3
Fourniture d’un événement OnChange . . 40-12 Ajout des propriétés de l’interface . . . . . 42-3
Exclusion des cellules vides . . . . . . . . 40-13 Ajout de la méthode Execute . . . . . . . . 42-5
Test du composant . . . . . . . . . . . . . . . . 42-6
xxi
Partie V Recensement d’un objet COM . . . . . . . . . 44-6
Test d’un objet COM . . . . . . . . . . . . . . . 44-6
Développement d’applications COM
Chapitre 45
Chapitre 43 Création d’un contrôleur
Présentation des technologies Automation 45-1
COM 43-1 Création d’un contrôleur Automation en
COM, spécification et implémentation . 43-1 important une bibliothèque de types. . . . . 45-2
Extensions de COM . . . . . . . . . . . . 43-2 Contrôle d’un serveur Automation avec
Composantes d’une application COM . . . . . 43-2 une interface double . . . . . . . . . . . . 45-2
Interfaces COM. . . . . . . . . . . . . . . . . 43-3 Contrôle d’un serveur Automation avec
L’interface COM de base, IUnknown . . 43-4 une interface de répartition . . . . . . . . 45-3
Pointeurs d’interface COM . . . . . . . . 43-4 Exemple : impression d’un document
Serveurs COM . . . . . . . . . . . . . . . . . 43-5 dans Microsoft Word . . . . . . . . . . . . 45-3
CoClasses et fabricants de classes . . . . 43-6 Etape 1 : importation de la
Serveurs en processus, hors processus bibliothèque de types Word . . . . . . 45-3
et distants . . . . . . . . . . . . . . . . . 43-6 Etape 2 : utilisation d’un objet interface
Le mécanisme du marshaling. . . . . . . 43-8 double ou dispatch pour contrôler
Clients COM . . . . . . . . . . . . . . . . . . 43-8 Microsoft Word. . . . . . . . . . . . . . 45-3
Extensions de COM . . . . . . . . . . . . . . . . 43-9 Autres sources d’informations. . . . . . . . 45-5
Serveurs et contrôleurs Automation . . . . 43-10 Création d’un contrôleur Automation en
Contrôles ActiveX . . . . . . . . . . . . . . 43-12 utilisant des variants . . . . . . . . . . . . . . 45-5
Bibliothèques de types . . . . . . . . . . . 43-12 Exemple : impression d’un document avec
Contenu d’une bibliothèque de types . 43-13 Microsoft Word . . . . . . . . . . . . . . . 45-5
Création de bibliothèques de types . . 43-13 Etape 1 : création d’un objet Variant
Quand utiliser les bibliothèques de pour Word Basic . . . . . . . . . . . . . 45-5
types . . . . . . . . . . . . . . . . . . . 43-13 Etape 2 : utilisation de la méthode
Accès aux bibliothèques de types . . . 43-14 Variant pour imprimer le document . 45-6
Avantages des bibliothèques de Détermination du type de variant . . . . . 45-6
types . . . . . . . . . . . . . . . . . . . 43-14 Automation et registre . . . . . . . . . . . . . . 45-7
Utilisation des outils de bibliothèques Exécution en arrière-plan d’un serveur
de types . . . . . . . . . . . . . . . . . 43-15 Automation . . . . . . . . . . . . . . . . . . . 45-7
Documents Active . . . . . . . . . . . . . . 43-15 Paramètres d’Automation facultatifs :
Objets visuels inter-processus . . . . . . . 43-16 nommés et de position . . . . . . . . . . . 45-8
Implémentation des objets COM à l’aide Utilisation de tableaux de variants . . . . . . . 45-9
d’experts . . . . . . . . . . . . . . . . . . . . 43-16 Création de tableaux de variants . . . . . 45-10
Redimensionnement des tableaux de
Chapitre 44 variants . . . . . . . . . . . . . . . . . . . 45-10
Création d’un objet COM simple 44-1 Création d’un tableau de variants à une
Présentation de la création d’un objet COM . . 44-1 dimension . . . . . . . . . . . . . . . . . .45-11
Conception d’un objet COM . . . . . . . . . . . 44-2 Obtenir les limites et les dimensions des
Création d’un objet COM avec l’expert tableaux de variants. . . . . . . . . . . . .45-11
objet COM . . . . . . . . . . . . . . . . . . . . 44-2 Verrouillage des tableaux de variants . . 45-12
Types d’instanciation des objets COM . . . . . 44-3
Choix d’un modèle de thread . . . . . . . . . . 44-3 Chapitre 46
Ecriture d’un objet supportant le modèle Création d’un serveur Automation 46-1
de thread libre . . . . . . . . . . . . . . . . 44-5 Création d’un objet Automation pour une
Ecriture d’un objet supportant le modèle application . . . . . . . . . . . . . . . . . . . . 46-1
de thread apartment . . . . . . . . . . . . . 44-5
xxii
Gestion des événements de l’objet Comment Delphi ajoute les
Automation . . . . . . . . . . . . . . . . . . . . 46-2 événements . . . . . . . . . . . . . . . .47-11
Exposition des propriétés, méthodes et Activation de la liaison de données
événements d’une application . . . . . . . . . 46-3 simple avec la bibliothèque de types . . .47-11
Exposition d’une propriété à Activation de la liaison de données
l’Automation . . . . . . . . . . . . . . . . . 46-3 simple des contrôles ActiveX dans le
Exposition d’une méthode à conteneur Delphi . . . . . . . . . . . . . 47-12
l’Automation . . . . . . . . . . . . . . . . . 46-4 Création d’une page de propriétés pour un
Exposition d’un événement à contrôle ActiveX . . . . . . . . . . . . . . . 47-14
l’Automation . . . . . . . . . . . . . . . . . 46-4 Création d’une nouvelle page de
Autres sources d’informations . . . . . . . . 46-5 propriétés. . . . . . . . . . . . . . . . . . 47-15
Recensement d’une application comme Ajout des contrôles à une page de
serveur Automation . . . . . . . . . . . . . . . 46-6 propriétés. . . . . . . . . . . . . . . . . . 47-15
Recensement d’un serveur en processus . . 46-6 Association des contrôles de la page de
Recensement d’un serveur hors propriétés aux propriétés du contrôle
processus . . . . . . . . . . . . . . . . . . . 46-6 ActiveX . . . . . . . . . . . . . . . . . . . 47-15
Test et débogage de l’application . . . . . . . . 46-6 Actualisation de la page de
Interfaces Automation . . . . . . . . . . . . . . 46-7 propriétés . . . . . . . . . . . . . . . . 47-16
Interfaces doubles . . . . . . . . . . . . . . . 46-7 Actualisation de l’objet . . . . . . . . . 47-16
Interfaces de répartition . . . . . . . . . . . . 46-8 Connexion d’une page de propriétés à
Interfaces personnalisées . . . . . . . . . . . 46-9 un contrôle ActiveX . . . . . . . . . . . . 47-16
Marshaling des données . . . . . . . . . . . . . 46-9 Publication des propriétés d’un contrôle
Types compatibles avec l’Automation. . . . 46-9 ActiveX . . . . . . . . . . . . . . . . . . . . . 47-17
Restrictions de type pour le marshaling Recensement d’un contrôle ActiveX . . . . . 47-18
automatique . . . . . . . . . . . . . . . . . 46-10 Test d’un contrôle ActiveX . . . . . . . . . . 47-18
Marshaling personnalisé . . . . . . . . . . 46-11 Déploiement d’un contrôle ActiveX sur le
Web . . . . . . . . . . . . . . . . . . . . . . . 47-18
Chapitre 47 Paramétrage des options de déploiement
Création d’un contrôle ActiveX 47-1 Web . . . . . . . . . . . . . . . . . . . . . 47-19
Présentation de la création d’un contrôle Case à cocher Défaut des Options de
ActiveX . . . . . . . . . . . . . . . . . . . . . . 47-1 déploiement Web . . . . . . . . . . . 47-20
Eléments d’un contrôle ActiveX . . . . . . . 47-2 Fichier .INF . . . . . . . . . . . . . . . . 47-21
Contrôle VCL . . . . . . . . . . . . . . . . 47-2 Combinaisons d’options . . . . . . . . 47-21
Bibliothèque de types . . . . . . . . . . . 47-3 Page Projet . . . . . . . . . . . . . . . . . . 47-22
Propriétés, méthodes et événements . . . 47-3 Page Paquets. . . . . . . . . . . . . . . . . 47-23
Page de propriétés . . . . . . . . . . . . . 47-3 Paquets utilisés par ce projet. . . . . . 47-23
Conception d’un contrôle ActiveX . . . . . . . 47-3 Options CAB . . . . . . . . . . . . . . . 47-23
Génération d’un contrôle ActiveX à partir Options de sortie . . . . . . . . . . . . 47-23
d’un contrôle VCL . . . . . . . . . . . . . . . . 47-4 Options de répertoire et URL . . . . . 47-23
Génération d’un contrôle ActiveX basé sur Page Fichiers supplémentaires . . . . . . 47-24
une fiche VCL . . . . . . . . . . . . . . . . . . 47-6 Fichiers associés au projet . . . . . . . 47-24
Manipulation des propriétés, méthodes et Options CAB . . . . . . . . . . . . . . . 47-24
événements d’un contrôle ActiveX . . . . . . 47-9 Options de sortie . . . . . . . . . . . . 47-24
Ajout de propriétés, méthodes et Options de répertoire et URL . . . . . 47-24
événements supplémentaires . . . . . . . . 47-9 Page Encodage . . . . . . . . . . . . . . . 47-25
Comment Delphi ajoute les Informations requises . . . . . . . . . . 47-25
propriétés . . . . . . . . . . . . . . . . 47-10 Informations facultatives . . . . . . . . 47-25
Comment Delphi ajoute les Serveur de date de validité. . . . . . . 47-25
méthodes. . . . . . . . . . . . . . . . . 47-10 Algorithme cryptographique. . . . . . 47-26
xxiii
Chapitre 48 Membres d’un module . . . . . . . . . . . 48-21
Utilisation des bibliothèques Méthodes d’un module . . . . . . . . . 48-21
Constantes de module . . . . . . . . . 48-22
de types 48-1 Création de nouvelles bibliothèques de
L’éditeur de bibliothèques de types . . . . . . . 48-2 types . . . . . . . . . . . . . . . . . . . . . . 48-22
Barre d’outils . . . . . . . . . . . . . . . . . . 48-3 Types autorisés . . . . . . . . . . . . . . . 48-22
Volet liste des objets . . . . . . . . . . . . . . 48-4 Les SafeArray . . . . . . . . . . . . . . 48-24
Barre d’état . . . . . . . . . . . . . . . . . . . 48-4 Utilisation de la syntaxe Pascal Objet ou
Les pages d’informations de type . . . . . . 48-5 IDL . . . . . . . . . . . . . . . . . . . . . 48-24
Page Attributs. . . . . . . . . . . . . . . . 48-5 Spécifications des attributs . . . . . . . 48-25
Page Texte . . . . . . . . . . . . . . . . . . 48-6 Syntaxe pour une interface. . . . . . . 48-26
Pages Indicateurs . . . . . . . . . . . . . . 48-6 Syntaxe pour une interface de
Informations de type d’une bibliothèque. . . . 48-6 répartition. . . . . . . . . . . . . . . . 48-27
Page Attributs d’une bibliothèque de Syntaxe pour une CoClasse . . . . . . 48-27
types . . . . . . . . . . . . . . . . . . . . . . 48-7 Syntaxe pour une énumération . . . . 48-28
Page Utilise d’une bibliothèque de types . . 48-7 Syntaxe pour un alias . . . . . . . . . . 48-28
Page Indicateurs d’une bibliothèque de Syntaxe pour un enregistrement. . . . 48-29
types . . . . . . . . . . . . . . . . . . . . . . 48-7 Syntaxe pour une union . . . . . . . . 48-29
Pages d’une interface . . . . . . . . . . . . . . . 48-8 Syntaxe pour un module . . . . . . . . 48-30
Page Attributs d’une interface . . . . . . . . 48-8 Création d’une nouvelle bibliothèque de
Indicateurs d’une interface . . . . . . . . . . 48-8 types . . . . . . . . . . . . . . . . . . . . 48-30
Membres d’une interface . . . . . . . . . . . 48-9 Ouverture d’une bibliothèque de types
Méthodes d’une interface . . . . . . . . . 48-9 existante . . . . . . . . . . . . . . . . . . 48-31
Propriétés d’une interface . . . . . . . . 48-10 Ajout d’une interface à une bibliothèque
Page Paramètres des propriétés et de types. . . . . . . . . . . . . . . . . . . 48-31
méthodes. . . . . . . . . . . . . . . . . 48-11 Ajout de propriétés et méthodes à une
Informations de type d’une interface de bibliothèque de types . . . . . . . . . . . 48-31
répartition. . . . . . . . . . . . . . . . . . . . 48-13 Ajout d’une CoClasse à une bibliothèque
Page Attributs d’une interface de de types. . . . . . . . . . . . . . . . . . . 48-32
répartition . . . . . . . . . . . . . . . . . . 48-14 Ajout d’une énumération à une
Page Indicateurs d’une interface de bibliothèque de types . . . . . . . . . . . 48-32
répartition . . . . . . . . . . . . . . . . . . 48-14 Enregistrement et recensement des
Membres d’une interface de répartition. . 48-14 informations d’une bibliothèque de
Pages d’une CoClasse . . . . . . . . . . . . . . 48-15 types . . . . . . . . . . . . . . . . . . . . 48-33
Page Attributs d’une CoClasse . . . . . . . 48-15 Enregistrement d’une bibliothèque de
Page Implémente d’une CoClasse . . . . . 48-15 types . . . . . . . . . . . . . . . . . . . 48-33
Indicateurs d’une CoClasse . . . . . . . . . 48-16 Rafraîchissement de la bibliothèque
Informations de type d’une énumération . . 48-16 de types . . . . . . . . . . . . . . . . . 48-34
Page Attributs d’une énumération. . . . . 48-17 Recensement d’une bibliothèque de
Membres d’une énumération . . . . . . . . 48-17 types . . . . . . . . . . . . . . . . . . . 48-34
Informations de type d’un alias . . . . . . . . 48-17 Exportation d’un fichier IDL . . . . . . 48-34
Page Attributs d’un alias . . . . . . . . . . 48-18 Déploiement des bibliothèques de types . . 48-34
Informations de type d’un enregistrement . . 48-18
Page Attributs d’un enregistrement . . . . 48-18 Chapitre 49
Membres d’un enregistrement . . . . . . . 48-19 Création des objets MTS 49-1
Informations de type d’une union . . . . . . 48-19
Composants Microsoft Transaction Server . . 49-2
Page Attributs d’une union . . . . . . . . . 48-19
Exigences d’un composant MTS . . . . . . 49-4
Membres d’une union . . . . . . . . . . . . 48-20
Gestion des ressources avec l’activation
Informations de type d’un module . . . . . . 48-20
just-in-time et le pooling . . . . . . . . . . . . 49-4
Page Attributs d’un module . . . . . . . . 48-21
xxiv
Activation just-in-time. . . . . . . . . . . . . 49-5 Clients de base et composants MTS . . . . . 49-15
Pooling des ressources. . . . . . . . . . . . . 49-5 Technologies sous-jacentes de MTS, COM
Libération des ressources . . . . . . . . . . . 49-6 et DCOM. . . . . . . . . . . . . . . . . . . . 49-15
Pooling des objets . . . . . . . . . . . . . . . 49-6 Présentation de la création des objets
Accès au contexte d’un objet . . . . . . . . . 49-7 MTS . . . . . . . . . . . . . . . . . . . . . . . 49-16
Support transactionnel MTS . . . . . . . . . . . 49-7 Utilisation de l’expert objet MTS . . . . . . . 49-16
Attributs transactionnels . . . . . . . . . . . 49-8 Choix d’un modèle de thread pour un
Le contexte d’objet contient l’attribut de la objet MTS. . . . . . . . . . . . . . . . . . 49-17
transaction. . . . . . . . . . . . . . . . . . . 49-9 Activités MTS . . . . . . . . . . . . . . . . 49-18
Objets avec état et sans état . . . . . . . . . 49-9 Définition de l’attribut transactionnel . . . . 49-19
Activation de plusieurs objets pour Transmission de références à des objets . . . 49-19
supporter les transactions . . . . . . . . . . 49-9 Utilisation de la méthode SafeRef . . . 49-20
Transactions contrôlées par MTS ou par Callbacks . . . . . . . . . . . . . . . . . 49-20
le client . . . . . . . . . . . . . . . . . . . 49-10 Définition d’un objet transaction côté client 49-21
Avantage des transactions . . . . . . . . . 49-11 Définition d’un objet transaction côté
Temporisation des transactions. . . . . . . 49-11 serveur . . . . . . . . . . . . . . . . . . . . . 49-21
Sécurité en fonction des rôles . . . . . . . . . 49-12 Débogage et test des objets MTS . . . . . . . 49-22
Dispenseurs de ressources . . . . . . . . . . . 49-12 Installation des objets MTS dans un paquet
Dispenseur de ressources BDE . . . . . . . 49-12 MTS . . . . . . . . . . . . . . . . . . . . . . . 49-23
Gestionnaire de propriétés partagées . . . 49-13 Administration des objets MTS avec
Exemple : Partage de propriétés entre l’Explorateur MTS . . . . . . . . . . . . . . 49-23
les instances d’un objet MTS . . . . . 49-13 Utilisation de la documentation MTS . . . . 49-24
Conseils d’utilisation du gestionnaire
de propriétés partagées . . . . . . . . 49-14 Index I-1
xxv
Chapitre
1
Introduction
Chapter 1
Contenu de ce manuel
Ce manuel comporte cinq parties décomposées comme suit :
• La partie I, “Programmation avec Delphi,” décrit la manière de concevoir des
applications Delphi généralistes. Cette partie donne des détails sur les
techniques de programmation utilisables dans toute application Delphi. Elle
décrit, par exemple, la manière d’utiliser les objets courants de la bibliothèque
de composants visuels qui simplifient la programmation de l’interface
utilisateur comme la gestion de chaînes, la manipulation de texte,
l’implémentation des boîtes de dialogue standard Windows et les barres
d’outils. Elle contient également des chapitres décrivant la manipulation des
graphiques et la gestion des erreurs et des exceptions, l’utilisation des DLL,
l’automation OLE et l’écriture d’applications internationales.
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 la manière de
déterminer les paquets, DLL et autres bibliothèques qu’il faut utiliser pour
générer la version distribuée d’une application.
Introduction 1-1
Contenu de ce manuel
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 :
Introduction 1-3
1-4 Guide du développeur
Partie
I
Programmation avec Delphi
Part I
Tous les objets VCL, en fait tous les objets Pascal Objet, sont dérivés de TObject.
TObject est unique car c’est un objet abstrait n’ayant ni propriétés ni événements
et seulement des méthodes qui vous permettent de dériver des objets de cette
classe de base. Utilisez TObject comme classe de base immédiate quand vous
écrivez des objets simples qui ne sont pas des composants. Les composants sont
des objets que vous pouvez manipuler à la conception. Tous les composants de
la VCL dérivent du type de composant abstrait TComponent. Les composants
VCL que vous utiliserez le plus fréquemment sont des contrôles de la VCL,
comme TForm ou TSpeedButton. Les contrôles sont des composants visuels qui
dérivent du type de composant abstrait TControl.
Vous pouvez utiliser Delphi pour créer des objets Pascal Objet sans utiliser la
VCL, même si tout objet créé en Pascal Objet a un ancêtre commun avec les
objets de la VCL : TObject. Cependant, en dérivant de nouveaux objets à partir
d’objets VCL, vous évitez une bonne partie de travail de développement
d’applications qui est alors fait par Delphi. Si, par exemple, vous voulez utiliser
une barre de progression dans une application mais n’êtes pas satisfait par
TProgressBar, le contrôle Delphi qui crée une barre de progression, vous pouvez
créer un nouvel objet basé sur TProgressBar et redéfinir ses propriétés,
événements et méthodes.
type
TColorBox = class(TForm){ remplacement de TForm1 par TColorBox }
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées}
public
{ Déclarations publiques }
end;
var
ColorBox: TColorBox;{ Remplacement de Form1 par ColorBox }
implementation
{$R *.DFM}
procedure TColorBox.Button1Click(Sender: TObject);
begin
Form1.Color := clGreen;{ La référence à Form1 n’a pas été actualisée! }
end;
end.
Le nom du type d’objet fiche a changé de TForm1 en TColorBox. De même, la
variable fiche s’appelle maintenant ColorBox, le nom attribué à la fiche. Les
références à la variable ColorBox et au type TColorBox apparaissent également
dans le begin end final du bloc de code, le code qui crée l’objet fiche et démarre
l’exécution de l’application. Si le code a été généré initialement par Delphi, il est
actualisé automatiquement quand vous utilisez l’inspecteur d’objets pour changer
le nom de la fiche ou d’un autre composant.
Par contre, le code écrit dans le gestionnaire d’événement OnClick du bouton n’a
pas changé. Comme c’est le programmeur qui a écrit ce code, c’est à lui de
l’actualiser et de corriger les références à la fiche quand le nom de la fiche est
changé. Si vous ne faites pas la modification, le code ne se compile pas. Dans cet
exemple, modifiez le code de la manière suivante :
procedure TColorBox.Button1Click(Sender: TObject);
begin
ColorBox.Color := clGreen;
end;
Vous devez toujours utiliser l’inspecteur d’objets pour modifier le nom d’un
composant. Même si rien ne vous empêche de modifier le code généré par
Delphi et de changer le nom des variables composant, vous ne pourrez plus
compiler votre programme.
Comment peut-il être possible de faire tout cela avec une fiche ne contenant en
tout et pour tout qu’une seule fiche et une seule méthode ?
La notion d’héritage constitue la réponse. Reprenez l’image de la bicyclette : une
fois assemblés tous les objets constituant un "objet bicyclette" complet, vous
pouvez rouler avec car il possède toutes les caractéristiques d’une bicyclette : des
pédales permettant de faire tourner les roues, un selle sur lequel s’asseoir, un
guidon, etc. De même, quand vous ajoutez une nouvelle fiche à votre projet, elle
dispose de toutes les caractéristiques d’une fiche. Ainsi, toutes les fiches
proposent une zone permettant d’y placer d’autres composants, toutes les fiches
ont des méthodes pour s’ouvrir, se fermer, se masquer, etc.
Si vous décidiez de personnaliser cette bicyclette, vous feriez comme pour
personnaliser un objet fiche Delphi. Vous pouvez régler le dérailleur, ajouter une
lumière ou modifier le son de la sonnette ; tout comme vous pouvez
personnaliser une fiche en ajoutant ou en modifiant des boutons, en changeant la
valeur de quelques propriétés ou en ajoutant une nouvelle méthode qui permette
à la fiche d’apparaître avec un fond écossais.
Pour modifier la bicyclette afin qu’elle corresponde à vos souhaits, vous partez
du modèle de base que vous personnalisez. Vous procédez de même avec les
fiches Delphi. Quand vous ajoutez une nouvelle fiche dans un projet, vous avez
ajouté une fiche “modèle de base”. En ajoutant des composants à la fiche, en
modifiant la valeur de propriétés et en écrivant des gestionnaires d’événements,
vous personnalisez la nouvelle fiche.
Pour personnaliser un objet, que ce soit une fiche vide ou une fiche contenant
plusieurs contrôles utilisée comme boîte de dialogue ou une nouvelle version du
bouton bitmap Delphi, vous commencez par dériver un nouveau type d’objet
d’un type d’objet existant. Quand vous ajoutez une nouvelle fiche à un projet,
Delphi dérive automatiquement du type TForm un nouveau type d’objet fiche.
Au moment de l’ajout d’une nouvelle fiche à un projet, le nouvel objet fiche est
identique au type TForm. Mais, dès que vous lui ajoutez des composants, que
vous modifiez des propriétés ou écrivez des gestionnaires d’événements, le
nouvel objet fiche devient différent du type TForm.
Peu importe comment vous personnalisez votre bicyclette, elle peut toujours faire
ce que l’on attend d’une bicyclette. De même, un objet fiche personnalisé
propose toutes les possibilités prédéfinies d’une fiche, il sait faire tout ce qu’une
fiche doit savoir faire : changer de couleur ou de taille, se refermer, etc. Cela est
possible car le nouvel objet fiche hérite de tous les champs de données,
propriétés, méthodes et événements du type TForm.
Quand vous ajoutez une nouvelle fiche à un projet Delphi, Delphi crée un
nouveau type d’objet, TForm1, en le dérivant du type objet plus générique
TForm. La première ligne de la déclaration du type TForm1 spécifie que TForm1
dérive de TForm :
TForm1 = class(TForm)
Comme TForm1 dérive de TForm, tous les éléments appartenant au type TForm
font automatiquement partie du type TForm1. Si vous recherchez TForm dans
l’aide en ligne (par exemple en cliquant sur la fiche puis en appuyant sur F1),
vous voyez une liste de toutes les propriétés, méthodes et événements du type
objet TForm. Vous pouvez utiliser tous les éléments hérités de TForm dans votre
application. N’apparaissent dans la déclaration du type TForm1 que les éléments
que vous avez spécifiquement ajouté à votre type TForm1 : les composants que
vous avez placé dans la fiche ou les gestionnaires d’événements (méthodes) que
vous avez écrits pour répondre aux événements. Ce sont les éléments qui font
que TForm1 est différent de TForm.
L’objet plus large, plus générique dont un autre objet plus personnalisé hérite le
code et les données, est appelé l’ancêtre de l’objet personnalisé. L’objet
personnalisé est lui un descendant de son ancêtre. Si un objet ne peut avoir qu’un
seul ancêtre immédiat, il peut par contre avoir plusieurs descendants. Ainsi,
TForm est le type ancêtre de TForm1 et TForm1 est un des descendants de TForm.
Tous les objets fiche sont des descendants de TForm et vous pouvez dériver de
nombreux objets fiche de TForm.
Figure 2.2 Héritage de TForm
TForm
TObject
TComponent
TControl
fréquemment appelés des composants. Les composants, qui héritent des données
et du code du type TObject, sont des objets disposant de propriétés, de méthodes
et d’événements leur permettant d’avoir des rôles spécialisés, par exemple la
capacité d’enregistrer leur état dans un fichier. Les contrôles, qui héritent des
données et du code du type TComponent (qui lui à son tour hérite d’éléments de
TObject), disposent de capacités spécialisées supplémentaires, par exemple la
capacité d’afficher quelque chose. Ainsi, les contrôles sont des composants et des
objets ; les composants sont des objets mais pas nécessairement des contrôles ; les
objets quant à eux sont simplement des objets. Dans ce chapitre, tous les
composants et contrôles sont désignés par le terme objet.
Bien que TCheckBox ne soit pas un descendant immédiat de TObject, il dispose
quand même de tous les attributs d’un objet car, en dernier ressort TCheckBox
dérive de TObject dans la hiérarchie VCL. TCheckBox est une forme d’objet très
spécialisée qui hérite de toutes les fonctionnalités de TObject, TComponent et
TControl, et définit certaines caractéristiques uniques qui lui sont propres.
Les déclarations dans la partie private sont d’un accès restreint. Si vous déclarez
des champs ou des méthodes privées, elles sont inconnues et inaccessibles en
dehors de l’unité dans laquelle ils sont définis. Utilisez la partie private pour :
• Déclarer des champs de données accessibles uniquement depuis les méthodes
de l’unité en cours.
• Déclarer des méthodes accessibles uniquement depuis les objets définis dans
l’unité en cours.
Pour ajouter des champs de données ou des méthodes aux sections public ou
private, placez les déclarations de champs ou de méthodes après le commentaire
approprié ou supprimez les commentaires avant d’ajouter le code. Par exemple :
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Déclarations privées }
Number: Integer;
function Calculate(X, Y: Integer): Integer;
public
{ Déclarations publiques }
procedure ChangeColor;
end;
Placez le code qui implémente les méthodes Calculate et ChangeColor dans la
section implementation de l’unité.
Le champ de données Number et la fonction Calculate sont déclarés comme étant
privés (private). Seuls les objets de l’unité peuvent utiliser Number et Calculate.
Généralement, cette restriction signifie que seul l’objet fiche peut les utiliser car
une unité Delphi ne contient qu’une seule déclaration de type objet de type
TForm.
Comme la méthode ChangeColor est déclarée comme étant publique (public), le
code d’autres unités peut l’utiliser. L’appel de cette méthode depuis une autre
unité doit comporter le nom de l’objet dans l’appel :
Form1.ChangeColor;
L’unité appelant la méthode doit faire référence à Form1 dans sa clause uses.
Remarque Quand vous ajoutez des champs ou des méthodes dans un objet, placez toujours
les champs avant les déclarations de méthode à l’intérieur des parties public et
private.
exemple, votre fiche contient une boîte de saisie dont vous souhaitez modifier la
valeur de la propriété Text, vous devez écrire une instruction d’affectation de la
forme suivante, en spécifiant bien le nom de la boîte de saisie, ici Edit1 :
Edit1.Text := 'Frank Borland était ici';
De même, pour effacer le texte sélectionné dans le contrôle boîte de saisie, vous
pouvez écrire l’appel de la méthode ClearSelection comme suit :
Edit1.ClearSelection;
Si vous souhaitez changer la valeur de plusieurs propriétés ou appeler plusieurs
méthodes d’un objet qui est un champ de l’objet fiche, vous pouvez utiliser
l’instruction with afin de simplifier votre code. L’utilisation de l’instruction with
est judicieuse avec les objets comme avec les enregistrements. Voici, par exemple,
un gestionnaire d’événement faisant plusieurs modifications dans une boîte liste
quand l’utilisateur choisit un bouton de la fiche :
procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear;
ListBox1.MultiSelect := True;
ListBox1.Items.Add('Un');
ListBox1.Items.Add('Deux');
ListBox1.Items.Add('Trois');
ListBox1.Sorted := True;
ListBox1.Font.Style := [fsBold];
ListBox1.Font.Color := clPurple;
ListBox1.Font.Name := 'Times New Roman';
ListBox1.ScaleBy(125, 100);
end;
En utilisant l’instruction with dans le code, vous obtenez :
procedure TForm1.Button1Click(Sender: TObject);
begin
with ListBox1 do
begin
Clear;
MultiSelect := True;
Items.Add('Un');
Items.Add('Deux');
Items.Add('Trois');
Sorted := True;
Font.Style := [fsBold];
Font.Color := clPurple;
Font.Name := 'Times New Roman';
ScaleBy(125, 100);
end;
end;
En utilisant l’instruction with, il n’est pas nécessaire de qualifier chaque
référence de propriété ou de méthode de ListBox1 avec l’identificateur ListBox1. A
l’intérieur de l’instruction with, toutes les propriétés et méthodes appelées sont
locales dans la portée de la variable objet ListBox1.
Pour déclarer une instance du type TEmploye, votre code doit appeler Create
avant d’accéder aux champs de l’objet :
Employe := TEmploye.Create;
Il n’y a pas de méthode Create dans la déclaration du type TEmploye, mais
TEmploye dérive de TObject, et TObject définit la méthode Create. TEmploye peut
donc appeler Create pour créer une instance de TEmploye qui est affectée à la
variable Employe.
Vous pouvez maintenant accéder aux champs d’un objet Employe comme à ceux
des autres objets Delphi.
Destruction d’objets
Quand vous en avez fini avec un objet, vous devez le détruire afin de libérer la
mémoire utilisée par l’objet. Pour détruire un objet, il faut appeler un destructeur,
une méthode qui libère la mémoire allouée à l’objet.
Delphi propose deux destructeurs : Destroy et Free. Vous devez presque toujours
utiliser Free. L’implémentation de la méthode Free appelle Destroy uniquement si
le pointeur d’instance ne vaut pas nil ; en d’autres termes, si le pointeur désigne
effectivement l’instance. Il est donc plus prudent d’appeler Free que Destroy. De
plus, l’appel de Free produit un code légèrement plus compact.
Pour détruire l’objet Employe une fois que vous avez fini de l’utiliser, vous devez
donc faire l’appel suivant :
Employe.Free;
Tout comme il hérite de la méthode Create, TEmploye hérite de la méthode Free
de TObject.
Pour respecter de bonnes habitudes de programmation, il faut placer l’appel du
destructeur dans la partie finally d’un bloc try..finally et placer le code utilisant
l’objet dans la partie try. Cela garantit que la mémoire allouée à l’objet est bien
libérée même si une exception se produit quand le code tente d’utiliser l’objet.
Pour davantage d’informations sur les exceptions et le bloc try..finally, voir le
Guide du langage Pascal Objet.
Utilisation de composants
Delphi utilise intensivement les composants pour faciliter le développement
d’applications. Les composants sont des objets utilisés pour créer l’interface
utilisateur et d’autres fonctions, non visuelles, des programmes. Dans Delphi, la
palette des composants contient la plupart des composants que vous utiliserez
pour créer des applications. Tous les composants dérivent de la classe
TComponent de la VCL. Vous pouvez également créer vos propres composants
qui proposent des fonctionnalités absentes dans la VCL. Pour davantage
d’informations sur la création de composants, voir partie IV, “Création de
composants personnalisés.”
Organisation de la VCL
Chaque composant placé dans une fiche devient un objet de l’interface
utilisateur, un objet de base de données ou une fonction système (par exemple,
un timer système). En plaçant des composants dans les fiches, vous concevez
l’interface de votre application.
Les composants sont réellement des objets au sens de la programmation orientée
objet (OPP). Comme ce sont des objets, les composants Delphi :
• Encapsulent ensemble des données et des fonctions d’accès aux données.
• Hérite des données et des comportements des objets dont ils dérivent (leurs
ancêtres)
• Sont interchangeables avec les objets dérivant d’un même ancêtre, grâce au
concept de polymorphisme
Même si chaque composant a des caractéristiques propres, tous les composants
partagent certaines qualités qu’ils héritent d’un objet ancêtre commun appelé
TComponent. TComponent définit l’ensemble d’attributs minimum nécessaires au
fonctionnement d’un composant dans l’environnement Delphi.
A ce niveau, il est important de comprendre que les composants contiennent
trois sortes d’informations :
• Informations d’état. Ce sont des informations sur l’état actuel du composant,
appelées aussi les propriétés du composant. Les propriétés sont appelées les
attributs d’un composant que l’utilisateur ou l’application peut lire ou
initialiser. Height et Color sont des exemples de propriétés des composants.
• Informations d’action. Les composants disposent de certaines actions qu’ils
peuvent effectuer à la demande. Ces actions sont définies par des méthodes qui
sont des procédures ou des fonctions que vous pouvez appeler dans le code
afin de dire au composant ce qu’il doit faire. Hide et Refresh sont des exemples
de méthodes de composant.
• Information de rétroaction. Les composants permettent aux développeurs
d’applications d’attacher du code associé à certaines situations, appelées des
événements, ce qui rend les composants pleinement interactifs. En répondant
aux événements, vous créez réellement votre application. OnClick et
OnKeyDown sont des exemples d’événements de composant.
Les composants ayant des fonctions similaires sont regroupés en pages dans la
palette des composants. Le tableau 2.1 énumère les pages définies par défaut et
le type de composants qu’elles contiennent.
Tableau 2.1 Les pages de la palette des composants Delphi
Nom de page Contenu
Standard Contrôles Windows standard, menus.
Supplément Contrôles personnalisés
Win32 Contrôles communs Windows 95/NT 4.0.
Système Composants et contrôles permettant un accès au niveau du système, y
compris les timers, le système de fichier, le multimédia et le DDE.
Internet Composants aidant à la gestion des applications client/serveur : les
composants proposant divers protocoles de communications Internet ; les
sockets permettant la gestion TCP/IP de bas niveau et les objets utilisés
pour la conception d’applications serveur Web.
AccèsBD Composants non visuels qui accèdent aux bases de données, aux requêtes
et aux états.
ContrôleBD Composants visuels orientés données.
Decision Cube Des contrôles permettant de faire des statistiques sur les informations
contenues dans des bases de données et de les visualiser sous différents
angles en changeant dynamiquement d’angle de vue (disponible dans
certaines versions seulement).
QReport Les composants Quick Report utilisés pour simplifier la création d’états
incorporés.
Dialogues Boîtes de dialogue standard Windows.
Win 3.1 Composants proposés pour la compatibilité avec les projets Delphi 1.0. Les
composants boîte de dialogue de cette page servent également pour
concevoir des boîtes de dialogue personnalisées d’aspect compatibles avec
les boîtes de dialogue 32 bits.
Exemples Composants personnalisés exemple : une jauge, une grille de couleurs, des
incrémenteurs, une arborescence de répertoires et une grille de calendrier.
ActiveX Contrôles ActiveX exemple.
MIDAS Composant MIDAS utilisés pour créer des applications de base de données
multiniveaux (disponible dans certaines versions seulement).
Pour des informations sur chaque composant de la palette par défaut, voir l’aide
en ligne. Dans le menu Aide, choisissez Rubriques d’aide puis Utilisation de
Delphi|Fonctions élémentaires|Manipulation des composants|A propos de la
palette des composants.
Propriétés d’affichage
Quatre propriétés définissent l’aspect général d’un contrôle :
• BorderStyle spécifie si le contrôle a une bordure.
• Color spécifie la couleur de fond d’un contrôle.
• Ctrl3D spécifie si le contrôle a un aspect 3D ou un bord plat.
• Font modifie la couleur, le nom, le style ou la taille du texte. Vous pouvez
définir individuellement les différents aspects d’une fonte, par exemple sa
taille ou sa couleur ou utiliser une boîte de dialogue Police pour changer
plusieurs aspects à la fois.
Propriétés du parent
Pour conserver un aspect homogène dans une application, chaque composant
peut avoir le même aspect (pour les propriétés d’affichage) que son conteneur.
L’affectation de la valeur True aux propriétés ParentColor, ParentFont ou
ParentCtrl3D permet de répercuter automatiquement les modifications des
propriétés d’affichage dans tous les composants d’une fiche.
Si vous modifiez Font, Color ou Ctrl3D après avoir affecté la valeur True à la
propriété parent correspondante, votre spécification de couleur ou de fonte prend
effet et la valeur False est affectée à la propriété parent correspondante.
Propriétés de déplacement
Plusieurs propriétés déterminent comment les utilisateurs peuvent se déplacer
entre les divers contrôles d’une fiche :
• Caption contient la chaîne de texte qui intitule un composant. Pour souligner
un caractère d’une chaîne, faites-le précéder d’un caractère &. Ce type de
caractère est appelé un caractère accélérateur. L’utilisateur peut alors accéder
au contrôle ou à l’élément de menu en appuyant sur Alt et sur le caractère
souligné.
• TabOrder indique la position du contrôle dans l’ordre de tabulation du parent :
l’ordre dans lequel les contrôles reçoivent la focalisation quand l’utilisateur
appuie sur la touche Tab. Initialement, l’ordre de tabulation correspond à
l’ordre d’ajout des composants dans la fiche. Vous pouvez le modifier en
changeant TabOrder. TabOrder n’a de sens que si TabStop a la valeur True.
• TabStop détermine si l’utilisateur peut tabuler sur un contrôle. Si TabStop a la
valeur True, le contrôle est dans l’ordre de tabulation.
Propriétés de glisser-déplacer
Deux propriétés des composants affectent le comportement du glisser-déplacer:
• DragMode détermine la manière dont un glisser commence. Par défaut,
DragMode a la valeur dmManual et vous devez appeler la méthode BeginDrag
pour commencer un glisser. Si DragMode a la valeur dmAutomatic, le glisser
commence dès que le bouton de la souris est enfoncé.
• DragCursor détermine la forme du pointeur de la souris quand il se trouve au-
dessus d’un composant qui accepte un objet en train de glisser.
Propriétés de glisser-empiler
Les propriétés suivantes des composants contrôlent le comportement de glisser-
empiler :
• DockSite
• DragKind
• DragMode
• FloatingDockSiteClass
• AutoSize
Pour davantage d’informations, voir “Implémentation du glisser-empiler dans les
contrôles” à la page 6-5.
Contrôles texte
Dans de nombreuses applications, l’utilisateur doit saisir ou consulter du texte.
Le type de contrôle à employer pour contenir les informations dépend de la
taille et du format des informations.
Utilisez ce
composant : Quand vous voulez :
Edit Modifier une seule ligne de texte.
Memo Modifier plusieurs lignes de texte.
MaskEdit Utiliser un format particulier, par exemple celui d’un code postal ou d’un
numéro de téléphone.
RichEdit Modifier une quantité illimitée de texte ou utiliser du texte mis en forme.
Contrôles mémo
Un contrôle mémo gère le texte comme un composant boîte de saisie, mais le
composant mémo peut gérer plusieurs lignes de texte.
• Le texte d’un mémo est défini par la valeur de la propriété Text. Une
application peut savoir si le texte a été modifié en testant la propriété Modified.
• Pour que le texte d’un mémo soit automatiquement sélectionné quand il
devient le contrôle actif, affectez la valeur True à la propriété AutoSelect.
• A l’exécution, vous pouvez sélectionner tout le texte d’un mémo en utilisant la
méthode SelectAll.
• Pour déterminer le texte sélectionné par l’utilisateur dans le mémo ou pour
définir le texte sélectionné, utilisez la propriété SelText.
• Pour ne sélectionner qu’une partie du texte ou pour déterminer quelle partie
du texte est sélectionnée, utilisez les propriétés SelStart et SelLength.
Barres de défilement
Le composant barre de défilement est une barre de défilement Windows, utilisée
pour faire défiler le contenu d’une fenêtre, d’une fiche ou d’un contrôle. Le code
écrit dans le gestionnaire d’événement OnScroll détermine comment la fenêtre, la
fiche ou le contrôle se comporte quand l’utilisateur fait défiler la barre de
défilement.
• LargeChange détermine le déplacement du curseur de défilement quand
l’utilisateur clique dans la barre de défilement de part ou d’autre du curseur.
• SmallChange détermine le déplacement du curseur de défilement quand
l’utilisateur clique sur les flèches aux extrémités de la barre de défilement ou
utilise les touches de déplacement du clavier. La valeur par défaut est 1.
• Les propriétés Min et Max déterminent ensemble le nombre de positions
possibles du curseur de défilement dans la barre de défilement.
• Votre application peut spécifier la position du curseur de défilement à l’aide
de la propriété Position ou utiliser cette propriété à l’exécution pour
déterminer de combien la barre a défilé.
• Par défaut, l’utilisateur peut se déplacer d’une graduation vers le haut ou vers
le bas en utilisant les touches de déplacement correspondantes. Affectez
LineSize pour changer cet incrément.
• Affectez PageSize pour déterminer le nombre de graduations du déplacement
quand l’utilisateur appuie sur les touches Pg. Haut et Pg. Bas.
Contrôle séparateur
Ajoutez un séparateur dans une fiche entre deux contrôles alignés afin de
permettre à l’utilisateur de redimensionner les contrôles. Le séparateur se place
entre un contrôle aligné sur l’un des bords de la fiche et les contrôles qui
remplissent le reste de zone client. Donnez au diviseur le même alignement que
le contrôle qui est ancré sur le bord de la fiche.
Utilisez chaque contrôle de la fiche comme un volet séparé. Une fois chaque
volet placé, positionnez un séparateur avec le même alignement afin de
permettre le redimensionnement de ce volet. Le dernier volet placé dans la fiche
doit être aligné sur le client afin qu’il se redimensionne automatiquement pour
remplir l’espace restant une fois tous les autres volets redimensionnés.
• Affectez MinSize afin de spécifier la taille minimum que le séparateur doit
laisser quand il redimensionne le contrôle voisin.
• Affectez la valeur True à Beveled pour donner au bord du séparateur un aspect
3D.
Contrôles bouton
Un composant bouton est un contrôle bouton poussoir. Les utilisateurs cliquent
sur des contrôles bouton (les choisissent) pour initier des actions. En double-
cliquant sur un bouton à la conception, vous affichez le gestionnaire
d’événement OnClick du bouton dans l’éditeur de code.
• Affectez la valeur True à la propriété Cancel pour que le bouton déclenche son
événement OnClick quand l’utilisateur appuie sur Echap.
• Affectez la valeur True à la propriété Default pour que la touche Entrée
déclenche l’événement OnClick du bouton. Entrée déclenche l’événement
OnClick même si un autre contrôle détient la focalisation.
Boutons bitmap
Un composant bouton bitmap est un contrôle bouton poussoir qui contient un
bitmap. Vous pouvez choisir parmi des styles prédéfinis de bouton bitmap ou
spécifier votre propre bitmap.
• Pour attribuer un bitmap personnalisé à votre bouton, affectez la propriété Glyph.
• Utilisez la propriété Kind pour configurer automatiquement un bouton avec
un glyphe et un comportement par défaut.
• Par défaut, le glyphe est à gauche du texte. Pour le déplacer, utilisez la
propriété Layout.
• Le glyphe et le texte sont automatiquement centrés dans le bouton. Pour
changer leur position, utilisez la propriété Margin. Margin détermine le
nombre de pixels entre le bord de l’image et le bord du bouton.
• Par défaut, l’image et le texte sont séparés par 4 pixels. Utilisez Spacing pour
augmenter ou réduire cette distance.
• Les boutons bitmap peuvent avoir 3 états : haut, bas et enfoncé. Affectez la valeur
3 à la propriété NumGlyphs pour attribuer un bitmap différent à chaque état.
Turboboutons
Les composants turboboutons sont des boutons affichant des images graphiques
qui exécutent des commandes ou définissent des modes. Ils ont des
caractéristiques uniques qui leur permettent de fonctionner comme un ensemble.
Les turboboutons sont fréquemment utilisés avec des volets afin de créer des
barres d’outils.
• Par défaut, des turboboutons apparaissent à l’état haut (non sélectionné). Pour
afficher un turbobouton à l’état sélectionné, affectez la valeur True à la
propriété Down.
Cases à cocher
Une case à cocher permet à l’utilisateur d’effectuer un choix binaire de la forme
oui/non, homme/femme.
• Affectez True à Checked pour afficher une marque de sélection dans la case à
cocher, ce qui indique que l’option est sélectionnée.
• La valeur de la propriété AllowGrayed détermine si une case à cocher peut
avoir deux ou trois états possibles. Si AllowGrayed a la valeur False, la valeur
par défaut, cliquer sur une case à cocher la coche ou la décoche. Si
AllowGrayed a la valeur True, cliquer sur une case à cocher peut la cocher, la
griser ou la décocher.
• La propriété State détermine les divers états que peut prendre un contrôle case
à cocher. cbUnchecked : la case n’a pas de marque de sélection. cbChecked : la
case est cochée ce qui indique que l’utilisateur a sélectionné l’option, cbGrayed :
la case à cocher est grisée, ce qui indique un troisième état qui n’est ni coché,
ni non coché. C’est votre application qui détermine la signification d’une case
à cocher grisée.
Boutons radio
Les boutons radio proposent un ensemble de choix mutuellement exclusifs. Vous
pouvez utiliser le composant bouton radio pour placer des composants
individuels ou utiliser le composant groupe de boutons radio pour définir une
zone rectangulaire ayant une propriété Caption et une liste des éléments bouton
radio en utilisant la propriété Items. Pour davantage d’informations, voir
“Regroupement de composants” à la page 2-32 .
• Utilisez la propriété Caption pour définir la valeur d’un bouton radio.
• Quand Checked a la valeur True, un cercle noir apparaît dans le bouton radio,
ce qui indique que l’option est sélectionnée.
Barres d’outils
Les barres d’outils permettent aisément d’organiser et de gérer des contrôles
visuels. Vous pouvez créer une barre d’outils à partir d’un composant volet et de
turboboutons ou utiliser le composant barre d’outils puis choisir Nouveau
bouton dans son menu contextuel pour chaque bouton à ajouter. L’utilisation de
cette dernière méthode présente les avantages suivants :
• Tous les boutons outils d’une barre d’outils ont une largeur et une hauteur
identique.
• Les autres contrôles placés dans la barre d’outils sont maintenus en place par
des boutons outils invisibles et ont la même hauteur.
• Les contrôles peuvent passer automatiquement à la ligne quand il n’y a pas
suffisamment de place pour qu’ils tiennent sur une même ligne.
• Les espaces et les séparateurs (boutons outils configurés spécialement)
permettent de regrouper les boutons dans la barre d’outils.
• Vous disposez d’options d’affichage supplémentaires, par exemple les
bordures en relief ou la transparence.
Barres multiples
Une barre multiple contient des contrôles enfant qui peuvent être déplacés ou
redimensionnés de manière indépendante. Chaque contrôle se trouve dans une
bande indépendante. L’utilisateur positionne les contrôles en utilisant la poignée
de redimensionnement à gauche de chaque bande.
Le composant bande multiple (TCoolBar) exige, à la conception et à l’exécution,
une version 4.70, ou ultérieure, de COMCTL32.DLL (qui se trouve généralement
dans le répertoire WINDOWS\SYSTEM ou WINDOWS\SYSTEM32).
• La propriété Bands contient une collection d’objets TCoolBand. A la conception,
vous pouvez ajouter, retirer ou modifier les bandes à l’aide de l’éditeur de
bandes. Pour l’ouvrir, sélectionnez la propriété Bands dans l’inspecteur d’objets
puis double-cliquez dans la colonne des valeurs à droite ou cliquez sur le
bouton points de suspension (...). Vous pouvez également ajouter des bandes
simplement en ajoutant de nouveaux contrôles fenêtrés de la palette.
• Vous pouvez spécifier si l’utilisateur peut réordonner les bandes en affectant
la valeur True ou False à la propriété FixedOrder.
• Spécifiez si les bandes ont automatiquement une hauteur ou une largeur
uniforme à l’aide de la propriété FixedSize.
Gestion de listes
Les listes proposent à l’utilisateur une collection d’éléments dans laquelle il peut
choisir. Plusieurs composants affichent des listes:
Boîtes liste
Une boîte liste affiche une liste dans laquelle l’utilisateur peut sélectionner un ou
plusieurs éléments. Les propriétés suivantes sont essentielles pour utiliser une
boîte liste :
• Vous pouvez ajouter, supprimer ou insérer des éléments dans la boîte liste en
utilisant les méthodes Add, Delete et Insert de la propriété Items qui est une
liste de chaînes.
• Si MultiSelect a la valeur True, les utilisateurs peuvent sélectionner plusieurs
éléments à la fois. Par défaut, le processus de sélection multiple dans les
boîtes liste permet à l’utilisateur de sélectionner successivement des éléments
individuels en maintenant la touche Ctrl enfoncée. L’appui de la touche Maj n’a
aucun effet. Pour activer Maj afin de sélectionner des plages de valeurs,
affectez True à MultiSelect et à ExtendedSelect.
• La propriété Style détermine comment une boîte liste affiche ses éléments. Par
défaut, sa valeur est lbStandard, ce qui signifie que la boîte liste affiche chaque
élément sous la forme d’une chaîne de caractères. En modifiant la valeur de
Style, vous pouvez créer des boîtes liste dessinées par le propriétaire, dans ce
cas les éléments peuvent être graphiques et de hauteur fixe ou variable.
Pour des informations sur l’implémentation de contrôles dessinés par le
propriétaire, voir chapitre 22.
Boîtes à options
Un composant boîte à options est un contrôle qui combine une boîte de saisie et
une liste qui ressemble beaucoup à une boîte liste. Les utilisateurs peuvent saisir
du texte dans la boîte de saisie ou sélectionner un élément dans la liste.
• Quand les utilisateurs saisissent des données dans la boîte à options, en
entrant du texte ou en sélectionnant un élément de la liste, la valeur de la
propriété Text est modifiée.
• Par défaut, la liste déroulante affiche huit éléments. Pour augmenter ou
réduire le nombre d’éléments affichés, modifiez la valeur de la propriété
DropDownCount.
Les boîtes à options peuvent avoir cinq styles différents. Utilisez la propriété
Style pour sélectionner le type de boîte à options dont vous avez besoin :
• Utilisez csDropdown si vous voulez une liste de valeurs semblable à une boîte
liste mais qui n’apparaît que si l’utilisateur choisit le bouton. Par défaut, la
zone de texte est modifiable.
• Utilisez le style csDropDownList pour que la zone de saisie de la boîte à options
soit en lecture seule. L’utilisateur ne peut modifier un élément ou saisir une
nouvelle valeur, par contre il peut sélectionner des éléments dans la liste.
• Utilisez csSimple pour créer une boîte à options utilisant une liste de taille fixe
qui ne se referme pas.
Vues arborescentes
Un contrôle vue arborescente est un contrôle boîte liste particulier qui affiche un
ensemble d’objets comme une table des matières indentée selon des relations
hiérarchiques logiques. Le contrôle contient des boutons qui permettent de
développer ou de réduire l’arborescence. Une vue arborescente permet de visualiser
les relations entre un ensemble de conteneurs et d’autres éléments hiérarchisés.
Vous pouvez inclure des icônes associées au libellé texte pour chaque élément de
l’arborescence. Des icônes différentes peuvent être affichées quand l’utilisateur
développe ou réduit l’élément de l’arborescence. Vous pouvez, de plus, ajouter
un graphique (par exemple une case à cocher) utilisé pour refléter des
informations sur l’état de l’élément.
Le contrôle permet également de dessiner des lignes qui définissent les liens
hiérarchiques entre les éléments de la liste et des boutons pour développer ou
réduire l’arborescence.
• Indent définit le nombre de pixels qui séparent horizontalement un enfant de
son parent.
• Affectez la valeur False à ShowButtons pour retirer le bouton '+' qui indique
quand un élément peut être développé.
• Affectez la valeur False à ShowLines pour retirer les lignes de connexion de la
vue arborescente.
• Affectez la valeur False à ShowRoot pour retirer les lignes connectant les
éléments racine (les éléments de niveau supérieur).
Sélecteurs Date/Heure
Le sélecteur date/heure affiche une boîte liste permettant de saisir des dates ou
des heures. Pour utiliser ce composant, vous devez disposer de la dernière
version de COMCTL32.DLL (placée normalement dans le répertoire WINDOWS\
SYSTEM ou WINDOWS\SYSTEM32).
Regroupement de composants
Il est plus facile pour l’utilisateur de parcourir une application quand les
informations sont regroupées. Delphi propose plusieurs composants qui
permettent de regrouper des informations :
Boîtes groupe
Le composant boîte groupe correspond à la boîte groupe standard de Windows.
Utilisez ce composant pour regrouper des contrôles associés d’une fiche. Les
contrôles le plus fréquemment rassemblés dans un groupe sont les boutons radio.
Placez la boîte groupe dans la fiche, puis sélectionnez dans la palette des
composants les composants qui doivent apparaître à l’intérieur de la boîte
groupe dans la fiche.
Le texte identifiant le groupe est spécifié par la valeur de la propriété Caption.
Volets
Le composant volet est utilisé pour placer dans une fiche des volets à l’intérieur
desquels d’autres contrôles peuvent être placés. Vous pouvez, par exemple, créer
une barre d’outils en utilisant un volet. Les volets sont des conteneurs. Si vous
souhaitez obtenir uniquement un effet visuel, utilisez des composants biseau.
Il est possible d’aligner un volet à l’intérieur de la fiche afin qu’il conserver la
même position relativement à la fiche, même quand la fiche est redimensionnée.
• La propriété BorderWidth détermine la largeur, en pixels, de la bordure
entourant un volet. La valeur par défaut est 0, c’est-à-dire pas de bordure.
• La propriété Locked détermine si un volet peut être remplacé par un objet OLE
actif in situ. Si Locked a la valeur False, le serveur OLE peut remplacer le volet.
Si Locked a la valeur True et si le volet est aligné sur l’un des bords de la
fiche, le volet reste quand un objet OLE d’un composant conteneur OLE est
activé in situ. Utilisez Locked pour empêcher le remplacement de la barre
d’état ou d’élément similaire de l’interface.
Contrôles pages
Le composant contrôle pages est un ensemble de pages utilisé pour constituer
une boîte de dialogue multipage. A la conception, pour créer une nouvelle page
dans le contrôle page, cliquez avec le bouton droit de la souris sur le contrôles
pages et choisissez Nouvelle page.
• La propriété ActivePage spécifie l’objet page à onglet active.
• Affectez la valeur True à Multiline pour autoriser plusieurs lignes d’onglets.
• PageCount spécifie le nombre de pages.
• Pages donne accès aux pages de l’objet contrôle pages.
• La propriété TabHeight spécifie la hauteur, en pixels, des onglets. TabWidth
spécifie la largeur, en pixels, de chaque onglet. Si sa valeur est nulle, TabWidth
redimensionne automatiquement les onglets pour les ajuster à leur texte.
Contrôles onglets
Le composant contrôle onglets a l’aspect des séparateurs d’un classeur. Pour
créer une boîte de dialogue multipage, utilisez un contrôle pages. Le contrôle
onglets remplace l’ensemble d’onglets proposé dans Delphi 1.0.
Boîtes de défilement
Les composants boîte de défilement permettent de créer dans une fiche des zones
défilantes plus petites que la fiche entière. Il y a de nombreuses situations dans
lesquelles une application a besoin d’afficher davantage d’informations qu’il ne
peut en tenir dans une zone particulière. Certains contrôles, comme les boîtes
liste ou les mémos peuvent faire défiler leur contenu automatiquement. Mais il
est parfois nécessaire de faire défiler d’autres contrôles ou même des fiches
pleines de contrôles. Delphi gère ces zones défilantes à l’aide d’un contrôle
appelé une boîte de défilement.
Une boîte de défilement est semblable à un volet ou à une boîte groupe car elle
peut contenir d’autres contrôles. Mais, normalement une boîte de défilement est
invisible. Mais quand les contrôles placés dans la boîte de défilement ne peuvent
pas tenir dans la zone visible de la boîte de défilement, cette dernière affiche
automatiquement une ou deux barres de défilement, ce qui permet à l’utilisateur
de déplacer les contrôles invisibles de manière à les placer dans une zone où ils
sont visibles et utilisables.
• Définissez les limites de la boîte de défilement pour délimiter la zone qui doit
défiler.
• Utilisez la propriété Kind pour déterminer si la boîte de défilement a des
barres de défilement horizontale ou verticale.
• Vous pouvez utilisez la propriété Align d’une boîte de défilement pour ajuster
la taille et la position de la boîte de défilement à celle d’une fiche ou d’une
partie de fiche.
Contrôles en-tête
Le composant contrôle en-tête est un contrôle visuel divisé en zones qui affiche
du texte et qui permet de redimensionner individuellement chaque zone avec la
souris. A la conception, redimensionnez une section en cliquant avec le bouton
gauche de la souris sur la bordure d’un en-tête de section et en la faisant glisser
la souris. La largeur des autres sections n’est pas affectée.
• Utilisez la propriété Sections pour spécifier les diverses sections d’un en-tête.
Le contrôle en-tête permet également à l’utilisateur de faire glisser les séparations
entre les en-têtes pour définir la largeur de chaque colonne. Une option permet à
l’utilisateur de définir automatiquement un formatage sur la colonne quand
l’utilisateur double-clique sur la séparation, par exemple redimensionner
automatiquement la colonne en fonction de la plus grande valeur contenue dans
la colonne.
Rétroaction visuelle
Une application bien conçue donne à l’utilisateur des informations sur l’état en
cours du programme. Ces informations sont fournies en utilisant les composants
suivants :
Utilisez ce composant
ou cette propriété : Pour :
Label Afficher une chaîne de texte non modifiable.
ProgressBar Afficher le pourcentage restant à effectuer d’une tâche donnée.
StatusBar Afficher une zone d’état non modifiable en bas d’une fenêtre.
StaticText Afficher dans un composant un texte non modifiable, disposant
d’un handle de fenêtre.
Hint et ShowHint Activer les conseils d’aide.
HelpContext Effectuer la liaison avec le système d’aide en ligne.
Libellés
Le composant libellé affiche du texte dans une fiche. Généralement, les libellés
sont placés à côté de boîtes de saisie ou d’autres contrôles. Le libellé est un
contrôle non fenêtré, il ne peut donc pas recevoir la focalisation.
• Caption contient la chaîne de texte, l’intitulé, du libellé.
• La propriété FocusControl relie le contrôle libellé à un autre contrôle de la
fiche. Si l’intitulé du libellé comporte une touche accélératrice, le contrôle
spécifié dans la propriété FocusControl obtient la focalisation quand l’utilisateur
appuie sur la touche de raccourci.
• Si un libellé doit apparaître au-dessus d’un graphique laissant voir au travers
du libellé afin de ne pas masquer une portion du graphique/bitmap, affectez
la valeur True à la propriété Transparent.
• La propriété ShowAccelChar détermine comment apparaît le caractère & dans
l’intitulé du libellé. Si ShowAccelChar a la valeur True, un caractère & apparaît
sous la forme d’un soulignement du caractère placé à sa droite dans l’intitulé,
ce qui indique que ce caractère est un caractère de raccourci. Sinon, le
caractère & est affiché directement.
Barres de progression
Une barre de progression est un contrôle que vous pouvez utiliser pour montrer
le pourcentage de réalisation d’une opération longue. Elle est composée d’une
barre rectangulaire qui se “remplit” de gauche à droite. Utilisez ce contrôle pour
donner des informations sur le déroulement d’opérations longues ou s’effectuant
en arrière-plan.
Figure 2.5 Une barre de progression
• Utilisez la propriété Position pour spécifier une position par défaut dans la
barre de progression. A l’exécution, Position reflète la position exacte au fur et
à mesure que la valeur augmente.
• Utilisez les propriétés Max et Min pour définir l’intervalle à l’intérieur duquel
varie Position.
• Par défaut, l’indicateur de progression avance d’une valeur à la fois. Affectez
une valeur plus grande à la propriété StepBy pour accroître l’incrément. Pour
davantage d’informations, voir la méthode StepIt dans l’aide en ligne.
Barres d’état
Une barre d’état apparaît généralement en bas d’une fenêtre et affiche du texte.
Même si le composant volet de Delphi peut s’utiliser en guise de barre d’état, il
est plus simple d’employer le composant barre d’état Windows. En général, la
barre d’état est divisée en plusieurs zones de texte.
• La valeur par défaut de la propriété Align d’un composant barre d’état est
alBottom, qui gère automatiquement sa position et sa largeur.
• Pour créer des sous-volets à l’intérieur d’un composant barre d’état, utilisez la
propriété Panels : dans la colonne des valeurs de l’inspecteur d’objets, cliquez
sur le bouton points de suspension (..) pour ouvrir l’éditeur de volets.
• Affectez la propriété Width de chaque volet quand l’éditeur de volets est
ouvert et qu’un volet y est sélectionné. Définissez alors également Alignment et
les autres propriétés des volets.
• Ajoutez individuellement du code aux volets d’état pour refléter l’état de
l’application.
Remarque Une application exemple, placée dans le répertoire DEMOS\DOC\GRAPHEX,
utilise une barre d’état constituée de deux volets. Le premier volet indique le
point de départ d’un dessin quand l’utilisateur a cliqué sur le bouton de la
souris. L’autre volet indique la position en cours. Utilisez cette application
comme exemple pour concevoir vos propres barres de progression.
Affichage tabulaire
Les grilles sont constituées d’ensembles de lignes et de colonnes qui définissent
une collection de cellules. Le contenu de chaque cellule dépend de l’application
et du type de contrôle grille utilisé :
Grilles de dessin
Un composant grille de dessin est un contrôle grille qui permet l’affichage d’une
structure de données existante avec une disposition lignes/colonnes.
• La grille utilise l’événement OnDrawCell pour remplir les cellules de la grille.
Si la propriété DefaultDrawing a la valeur False, le code du gestionnaire
d’événement OnDrawCell dessine le contenu des cellules. Si DefaultDrawing a
la valeur True, le contenu des cellules est automatiquement dessiné en utilisant
certaines valeurs par défaut.
Grilles de chaînes
Le composant grille de chaînes est un contrôle grille conçu pour simplifier la
gestion de chaînes de caractères et d’objets associés tout en conservant les
caractéristiques d’un composant grille de dessin.
• Toutes les chaînes d’une grille de chaînes sont contenues dans la propriété
Cells que vous pouvez utiliser pour accéder à une chaîne donnée de la grille.
Tous les objets associés aux chaînes d’une grille sont contenus dans la
propriété Objects.
• Il est possible d’accéder à toutes les chaînes et objets associés d’une colonne
en utilisant la propriété Cols. De même, la propriété Rows vous donne accès à
toutes les chaînes et objets associés d’une ligne donnée.
En plus de ces propriétés, méthodes et événements, ce composant dispose
également des propriétés, méthodes et événements s’appliquant à tous les
contrôles fenêtrés.
Affichage graphique
Les graphiques, utilisés opportunément, peuvent améliorer une application et la
mettre en valeur. Pour incorporer des graphiques dans une application Delphi,
utilisez les composants suivants :
Images
Le composant image affiche une image graphique (bitmap, icône ou métafichier)
dans une fiche. Delphi propose une bibliothèque d’images dans le sous-répertoire
IMAGES. Utilisez les propriétés suivantes pour configurer les composants image.
• Sélectionnez l’image à afficher en cliquant sur la propriété Picture.
• Par défaut, l’image apparaît centrée dans le composant image, pour aligner
l’image dans le coin supérieur gauche, affectez la valeur False à la propriété
Center.
• Pour que l’image grandisse ou se réduise en fonction de la taille du
composant, affectez la valeur True à la propriété Stretch.
Formes
Le composant forme affiche une forme géométrique dans une fiche. C’est un
composant non fenêtré qui ne peut donc pas recevoir la focalisation.
• La forme géométrique utilisée est spécifiée à l’aide de la propriété Shape.
• Pour modifier la couleur du contour, utilisez la propriété BorderColor.
• Pour modifier la couleur de la forme ou spécifier un motif, utilisez la
propriété Brush. La manière de dessiner la forme dépend de deux propriétés
imbriquées de l’objet Brush : Color et Style.
Biseaux
Le composant biseau permet de placer des lignes, des boîtes ou des cadres
biseautés dans les fiches d’une application.
• Un composant volet contient deux biseaux : un biseau extérieur dessiné à côté
de la bordure du contrôle et un biseau intérieur dessiné à l’intérieur du biseau
extérieur. Utilisez les propriétés BevelInner et BevelOuter pour déterminer le
style d’un biseau : aucun, en relief ou en creux.
• La propriété BevelWidth détermine la distance, en pixels, séparant les deux
biseaux d’un volet.
Boîtes à peindre
Le composant boîte à peindre permet à une application de dessiner dans une
zone rectangulaire d’une fiche en utilisant du code. Elle empêche le dessin de
déborder hors des limites de la boîte à peindre. Quand vous avez ajouté une
boîte à peindre à une fiche, utilisez son gestionnaire d’événement OnPaint pour
dessiner dans son canevas (Canvas).
Pour des informations sur la manière de dessiner dans un canevas, voir
chapitre 7, “Utilisation de graphiques”.
Contrôles animation
Le composant animation est une fenêtre qui affiche silencieusement une séquence
vidéo AVI. Une séquence AVI est composée d’une série de plans bitmap, comme
un film. Les séquences AVI peuvent être sonorisées, mais les contrôles animation
ne fonctionnent qu’avec les séquences AVI silencieuses. Les fichiers utilisés
doivent être des fichiers AVI non compressés ou des séquences AVI compressées
en utilisant l’algorithme RLE. Voici quelques unes des propriétés d’un composant
animation :
• ResHandle est le handle Windows du module contenant la séquence AVI sous
forme de ressource. A l’exécution, affectez à ResHandle le handle d’instance ou
handle de module du module contenant la ressource animation. Après avoir
initialisé ResHandle, affectez la propriété ResID ou ResName pour spécifier
quelle ressource du module indiqué contient la séquence AVI à afficher dans
le contrôle animation.
• Affectez la valeur True à la propriété AutoSize pour que le contrôle animation
ajuste sa taille aux plans de la séquence AVI.
• StartFrame et StopFrame spécifient les plans de début et de fin de l’animation.
• Vous pouvez utiliser la propriété CommonAVI pour afficher l’une des
séquences AVI standard Windows définies dans Shell32.DLL.
• Pour commencer ou arrêter l’animation, affectez, respectivement True et False à
la propriété Active ; la propriété Repetitions permet de spécifier le nombre de
répétitions de la séquence.
• La propriété Timers permet d’afficher les plans en utilisant un timer. Cela
permet de synchroniser la séquence d’animation avec d’autres actions, par
exemple l’exécution d’une piste sonore.
Chaque boîte de dialogue s’ouvre quand sa méthode Execute est appelée. Execute
renvoie une valeur booléenne. Si l’utilisateur a choisi OK pour valider les
modifications effectuées dans la boîte de dialogue, Execute renvoie True. Si
l’utilisateur a choisi Annuler pour sortir de la boîte de dialogue sans effectuer
l’opération, Execute renvoie False.
Pour des informations détaillées sur les autres types d’éditeur de propriété,
recherchez la rubrique de l’aide en ligne Editeurs de propriétés.”
Appel de méthodes
Les méthodes utilisent les mêmes conventions d’appel que les procédures et
fonctions ordinaires à cette différence que chaque méthode comporte un
paramètre implicite supplémentaire, Self qui désigne l’instance ou la classe
appelant la méthode. Le paramètre Self est toujours transmis sous la forme d’un
pointeur 32 bits.
• Avec la convention register, le paramètre Self se comporte comme s’il était
placé avant tous les autres paramètres. Il est donc toujours transmis via le
registre EAX.
• Avec la convention pascal, le paramètre Self se comporte comme s’il était
déclaré après tous les autres paramètres, y compris le paramètre var
supplémentaire qui peut être transmis pour le résultat de la fonction. Il est
donc toujours empilé en dernier se retrouvant à une adresse inférieure à celle
des autres paramètres.
• Pour les conventions cdecl, stdcall et safecall, le paramètre Self se comporte
comme s’il était déclaré avant tous les autres paramètres, mais après le
paramètre var supplémentaire qui peut être transmis pour le résultat d’une
fonction. Il est donc empilé en avant-dernier, juste avant l’éventuel paramètre
var d’un résultat de fonction.
Remarque Tous les composants n’ont pas d’événement par défaut. Certains, comme le
biseau, n’ont pas du tout d’événement. Pour ces composants, le fait de double-
cliquer dessus dans la fiche ne génère pas un gestionnaire d’événement. Double-
cliquer dans certains autres composants, comme le composant image ou les
composants menu, ouvre une boîte de dialogue qui permet de modifier les
propriétés à la conception.
Vous pouvez également générer un gestionnaire de l’événement par défaut dans
l’inspecteur d’objets : dans la page Evénements, double-cliquez dans la colonne
des valeurs d’un événement.
begin
for Index := 0 to ListBox1.Items.Count - 1 do
ListBox1.Items[Index] := UpperCase(ListBox1.Items[Index]);
end;
public
{ Déclarations publiques}
ClickList: TStrings;{ déclare le champ}
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
ClickList := TStringList.Create;{ construit la liste }
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
ClickList.SaveToFile(ChangeFileExt(Application.ExeName, '.LOG'));{ enregistre la liste }
ClickList.Free;{ détruit l’objet liste }
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ClickList.Add(Format('Clic en (%d, %d)', [X, Y]));{ ajoute une chaîne à la liste }
end;
end.
Tableau 2.2 Méthodes correspondantes pour les chaînes et les objets d’une liste de chaînes
Opération Pour les chaînes Pour les objets
Accéder à un élément Strings (propriété) Objects (propriété)
Ajouter un élément Add (méthode) AddObject (méthode)
Insérer un élément Insert (méthode) InsertObject (méthode)
Rechercher un élément IndexOf (méthode) IndexOfObject (méthode)
Les méthodes LoadFromFile et SaveToFile n’agissent que sur les chaînes car elles
utilisent des fichiers texte.
Des méthodes comme Delete, Clear et Move agissent globalement sur un élément
de la liste, c’est-à-dire que la suppression d’un élément supprime à la fois la
chaîne et l’objet correspondant de la liste.
public
{ Déclarations publiques }
procedure LineItemsCalcFields(DataSet: TDataSet); { Une procédure ajoutée }
end;
var
CustomerData: TCustomerData;
Les procédures et fonctions que vous codez doivent suivre dans la section
implémentation de l’unité du module.
Avant de faire glisser des champs dans une fiche, définissez la source de
données des champs que vous voulez déposer. Delphi utilise une source de
données existante dans le module de données si elle est déjà connectée à
l’ensemble de données.
S’il n’y a pas de source de données définie, Delphi ajoute un nouveau
composant source de données à la fiche et affecte cette source de données à la
propriété DataSource des contrôles créés. La source de données même est associée
à un composant table ou requête du module de données. Si cela se produit, vous
pouvez garder cette organisation ou la changer si vous préférez conserver la
clarté de votre modèle d’accès aux données. Supprimez le composant source de
données dans la fiche et affectez la propriété DataSource du contrôle de la fiche
afin de désigner directement la source de données appropriée du module de
données.
Installer composant
Utilisez la commande Composant|Installer composant pour installer un
composant dans un paquet, existant ou nouveau. Que le composant soit installé
dans un paquet existant ou nouveau, vous devez spécifier le code du composant
identifié par le nom de l’unité.
Installer paquet
Utilisez la commande Composant|Installer paquet pour installer des paquets
compilés de composants utilisables dans l’EDI Delphi ou pour gérer les
composants installés.
Installation de composants
Pour installer des composants, développés par vous ou acquis auprès de tiers,
procédez de la manière suivante :
1 Copiez ou déplacez les fichiers nécessaires dans un répertoire local.
• Si le paquet est livré avec des fichiers .BPL, .DCP et .DCU séparés, vous
devez copier tous ces fichiers dans le répertoire local.
• Si le paquet est livré avec un fichier .DPC (collection de paquets), il suffit
de copier ce fichier qui contient tous les autres fichiers.
Remarque Le répertoire où vous placez le fichier .DCP et les fichiers .DCU (s’ils sont
inclus dans la distribution) doit faire partie du chemin de la bibliothèque
Delphi. L’habitude est de placer les fichiers exécutables dans le répertoire
Delphi\BIN.
2 Choisissez Composant|Installer paquets, ou choisissez Projet|Options et
cliquez sur l’onglet Paquets.
3 Une liste des paquets disponibles apparaît dans la zone Paquets disponibles.
• Pour ajouter un paquet à la liste, choisissez le bouton Ajouter et utilisez la
boîte de dialogue Ajout d’un paquet de conception pour vous placer dans
le répertoire où se trouvent les fichiers .BPL ou .DPC (voir étape 1).
Sélectionnez le fichier .BPL ou .DPC et choisissez Ouvrir. Si vous
sélectionnez un fichier .DPC, une autre boîte de dialogue est affichée pour
vous permettre de contrôler l’extraction des fichiers .BPL et autres contenus
dans la collection de paquets.
• Pour installer un paquet, cochez la case adjacente.
• Pour désinstaller un paquet, retirez la coche de sa case à cocher.
• Pour voir une liste des composants proposés dans un paquet installé,
sélectionnez le paquet et choisissez Composants.
• Pour retirer un paquet de la liste, sélectionnez le paquet et choisissez Retirer.
4 Choisissez OK.
Les composants du paquet sont installés dans les pages de la palette des
composants spécifiées dans la procédure RegisterComponents des composants (les
composants portant le nom qui leur est attribué dans cette même procédure).
A moins de changer les paramètres par défaut, les nouveaux projets sont créés
avec tous les paquets disponibles installés. Pour faire de la configuration en
cours les paramètres par défaut des nouveaux projets, cochez la case Défaut dans
le bas de la boîte de dialogue.
Création d’applications, de
Chapter 3
3
composants et de bibliothèques
Ce chapitre donne un aperçu de la manière d’utiliser Delphi pour créer des
applications, des bibliothèques et des composants.
Création d’applications
L’utilisation principale de Delphi est la conception, la génération et la
compilation d’applications Windows. Il y a trois types de base d’applications
Windows :
• Les applications d’interface utilisateur graphique Windows
• Les applications console
• Les applications service
Les applications d’interface utilisateur graphique Windows correspondent à
l’essentiel des programmes disponibles sur la plate-forme Windows. L’interface
utilisateur (IU) est constituée de fenêtres, de boîtes de dialogue qui travaillent en
association pour proposer un ensemble de fonctionnalités. Les traitements de
texte, les tableurs ou Delphi sont des exemples d’applications d’interface
utilisateur graphique.
Les applications console sont des applications 32 bits Windows qui s’exécutent
sans interface utilisateur graphique, généralement dans une fenêtre console.
Généralement, ces applications ne nécessitent pas de saisies de l’utilisateur et
effectuent un ensemble limité de fonctions. L’utilitaire Grep proposé avec Delphi
est un exemple d’application console tout comme le compilateur et le lieur en
ligne de commande fournis avec Delphi.
Les applications service sont des applications qui attendent des requêtes
d’applications client, traitent ces requêtes et renvoient des informations aux
applications client. Généralement, elles s’exécutent en tâche de fond sans
nécessiter des saisies utilisateur fréquentes. Les serveurs Web, FTP ou de courrier
électronique sont des exemples d’application service.
Applications SDI
Pour créer une nouvelle application SDI :
1 Sélectionnez Fichier|Nouveau pour afficher la boîte de dialogue Nouveaux
éléments.
2 Cliquez sur l’onglet Projets et sélectionnez Application SDI.
3 Choisissez OK.
Par défaut, la propriété FormStyle de l’objet Form a la valeur fsNormal, Delphi
suppose que toute nouvelle application est une application SDI.
Applications MDI
Pour créer une nouvelle application MDI :
1 Sélectionnez Fichier|Nouveau pour afficher la boîte de dialogue Nouveaux
éléments.
2 Cliquez sur l’onglet Projets et sélectionnez Application MDI.
3 Choisissez OK.
Les applications MDI nécessitent plus de réflexion et sont plus complexes à
concevoir que les applications SDI. Néanmoins, les mêmes principes sont mis en
oeuvre pour créer une interface utilisateur bien conçue, que ce soit dans une
application MDI ou SDI.
Les applications MDI contiennent des fenêtres enfant qui se trouvent dans la
fenêtre client. Dans une application MDI Delphi, la fiche principale de
l’application 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
paramètres 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 de base.
Applications console
Les applications console sont des programmes écrits sans interface utilisateur
graphique. A l’exécution, une application console s’exécute dans une fenêtre
console Windows. Les contrôles visuels de la VCL qui s’utilisent normalement en
programmation Windows ne peuvent pas être utilisés dans les applications
console. A la création d’une nouvelle application console, Delphi ne crée pas une
nouvelle fiche. Seul l’éditeur de code est affiché. Vous pouvez néanmoins utiliser
la VCL dans les applications console.
Applications service
Pour créer une application qui implémente un service Win32, choisissez Fichier|
Nouveau puis sélectionnez Application service dans la boîte de dialogue
Nouveaux éléments. Cela ajoute à votre projet une variable globale appelée
Application de type TServiceApplication.
Une fois une application service créée, une fenêtre apparaît dans le concepteur
qui 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. Vous
pouvez ajouter des services supplémentaires en choisissant 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.
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. 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.
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
ScktComp;
type
TService1 = class(TService)
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure Service1Execute(Sender: TService);
private
{ Déclarations privées}
Stream: TMemoryStream;
public
{ Déclarations publiques }
function GetServiceController: PServiceController; override ;
end;
var
Service1: TService1;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord); stdcall;
begin
Service1.Controller(CtrlCode);
end;
function TService1.GetServiceController: PServiceController;
begin
Result := @ServiceController;
end;
procedure TService1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
Buffer: PChar;
begin
Buffer := nil;
while Socket.ReceiveLength > 0 do begin
try
Buffer := AllocMem(Socket.ReceiveLength);
Socket.ReceiveBuf(Buffer^, Socket.ReceiveLength);
Stream.Write(Buffer^, StrLen(Buffer));
finally
FreeMem(Buffer);
end;
Stream.Seek(0, soFromBeginning);
Stream.SaveToFile('c:\Temp\Weblog' + IntToStr(ServiceThread.ThreadID) + '.log');
end;
end;
procedure TService1.Service1Execute(Sender: TService);
begin
Stream := TMemoryStream.Create;
try
ServerSocket1.Port := 80; // port WWW
ServerSocket1.Active := True;
while not Terminated do begin
ServiceThread.ProcessRequests(False);
end;
ServerSocket1.Active := False;
finally
Stream.Free;
end;
end;
end.
Quand vous utilisez des services, vous devez tenir compte des :
• Threads de service
• Propriétés de nom d’un service
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 TService.OnExecute. 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 d’un service peut prendre longtemps et 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. Cette manière de procéder est illustrée par
l’exemple suivant :
{
Ce Service sonne tous les 500 millisecondes à l’intérieur d’un TThread standard. Il
gère la pause, la reprise et l’arrêt du Thread quand il est demandé au service de
faire une pause, de reprendre ou de s’arrêter.
}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;
type
TService2 = class(TService)
procedure Service1Start(Sender: TService; var Started: Boolean);
procedure Service1Continue(Sender: TService; var Continued: Boolean);
procedure Service1Pause(Sender: TService; var Paused: Boolean);
procedure Service1Stop(Sender: TService; var Stopped: Boolean);
private
{ Déclarations privées}
public
function GetServiceController: PServiceController; override;
{ Déclarations publiques }
end;
TSparkyThread = class(TThread)
public
procedure Execute; override ;
end;
var
Service2: TService2;
implementation
{$R *.DFM}
var
SparkyThread: TSparkyThread;
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.
Modèles de programmation
Les modèles de programmation font partie de caractéristiques proposées par les
fonctions d’audit de code Delphi. Ce sont des structures de code courantes et
générales qui vous permettent d’ajouter le code spécifique à vos programmes
sans avoir à ressaisir les structures générales de code. Par exemple, si vous
voulez insérer une boucle for dans votre projet, vous pouvez sélectionner l’un
des modèles de boucle for. Le code suivant est inséré :
for := to do
begin
end;
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 également ajouter
vos propres modèles à cette collection. Pour ajouter un modèle :
1 Sélectionnez Outils|Options d’environnement.
2 Choisissez l’onglet Audit de code.
3 Dans la section Modèles, choisissez Ajouter.
4 Saisissez un nom court et entrez une description brève du nouveau modèle.
5 Spécifiez le modèle de code dans la boîte de saisie Code.
6 Choisissez OK.
Votre nouveau modèle est maintenant disponible en appuyant sur Ctrl-j.
interface avec une base de données stockant toutes les informations sur ces
transactions. En concevant une application client distribuée, par exemple une
application utilisant le Web, la maintenance et la mise à jours des clients est
grandement simplifiée.
Delphi propose plusieurs options pour le modèle d’implémentation des
applications distribuées :
• Applications TCP/IP
• Applications COM et DCOM
• Applications CORBA
• Applications de base de données
COM et ActiveX
Vous devez toujours recenser tous les objets COM et les contrôles ActiveX quand
vous distribuez des applications utilisant COM et ActiveX. Cela s’effectue
souvent lors de l’installation de l’application ; le recensement des objets COM et
des contrôles ActiveX étant ultérieurement annulé quand l’application est
désinstallée. Le recensement de l’objet COM ou du contrôle ActiveX permet à
d’autres applications de trouver et d’utiliser l’objet.
MTS
Le serveur de transaction Microsoft (MTS) est un environnement robuste qui met
à la disposition des applications distribuées COM, des services de transaction, la
sécurité et la mise en commun des ressources.
Pour davantage d’informations sur MTS, voir chapitre 49, “Création des objets
MTS” et “Utilisation de MTS” à la page 15-6.
try
( code utilisant les deux ressources
bloc protégé
finally
( libérer la seconde ressource )
end;
finally
( libérer la première resource )
end;
Vous pouvez également utiliser des blocs imbriqués afin de définir une gestion
locale, pour des exceptions spécifiques, qui redéfinit la gestion du bloc
environnant. Conceptuellement, cela peut se représenter de la manière suivante :
try
bloc de gestion des exceptions
( code protégé)
try
bloc de gestion
begin
ADividend := 0;
GetMem(APointer, 1024);{ allouer 1Ko de mémoire }
try
AnInteger := 10 div ADividend;{ cela génère une erreur }
finally
FreeMem(APointer, 1024);{ malgré l’erreur, l’exécution reprend ici }
end;
end;
Les instructions placées dans le code de conclusion ne dépendent pas de
l’apparition d’une exception. Si les instructions de la partie try ne déclenchent
pas d’exceptions, l’exécution se poursuit quand même dans le code de conclusion
placé dans la partie finally.
Pour une liste des types d’exception RTL, voir l’unité SysUtils dans le système
d’aide.
Quand une instruction de la partie try déclenche une exception, l’exécution passe
immédiatement à la partie except où elle passe en revue les instructions de
gestion d’exception spécifiées ou les gestionnaires d’exceptions, jusqu’à trouver
un gestionnaire s’appliquant à l’exception en cours.
Quand l’application a trouvé un gestionnaire d’exception qui gère l’exception,
elle exécute l’instruction puis détruit automatiquement l’objet exception.
L’exécution reprend ensuite après la fin du bloc en cours.
Vous pouvez toujours définir des gestionnaires plus spécifiques pour des
exceptions plus spécifiques. Vous devez juste placer les gestionnaires spécifiques
avant le gestionnaire générique car l’application recherche les gestionnaires dans
leur ordre d’apparition et exécute le premier gestionnaire applicable trouvé. Par
exemple, le bloc suivant définit une gestion spécifique des erreurs d’étendue et
un autre gestionnaire pour toutes les autres erreurs de calcul entier :
try
{ instructions effectuant des opérations de calcul entier }
except
on ERangeError do { gestion des calculs hors étendue };
on EIntError do { gestion des autres erreurs de calcul entier };
end;
Par contre, si le gestionnaire de EIntError est placé avant le gestionnaire de
ERangeError, l’exécution n’atteint jamais le gestionnaire spécifique à ERangeError.
Redéclenchement de l’exception
Parfois, quand vous gérez localement une exception, vous voulez juste étendre la
gestion définie par le bloc conteneur et pas la remplacer. Mais, bien entendu,
quand votre gestionnaire local en a fini avec l’exception, il détruit
automatiquement l’instance d’exception et le gestionnaire du bloc conteneur ne
peut donc pas agir dessus. Vous pouvez néanmoins empêcher le gestionnaire de
détruire l’exception, ce qui laisse au gestionnaire du conteneur l’opportunité d’y
répondre.
Exemple Quand une exception se produit, vous voulez afficher un message à l’utilisateur,
puis laisser faire la gestion standard. Pour ce faire, déclarez un gestionnaire local
de l’exception qui affiche le message puis utilise le mot réservé raise. C’est ce
que l’on appelle redéclencher l’exception, comme le montre le code suivant :
try
{ instructions }
try
{ instructions spéciales }
except
on ESomething do
begin
{ gestions des instructions spéciales }
raise;{ redéclenche l’exception }
end;
end;
except
on ESomething do ...;{ gestion à effectuer dans tous les cas }
end;
Si le code de la partie { instructions } déclenche une exception ESomething, seul le
gestionnaire de la partie except extérieure s’exécute. Par contre, si c’est le code
de la partie { instructions spéciales } qui déclenche une exception ESomething, la
gestion définie dans la partie except intérieure est exécutée suivie par celle, plus
générale, de la partie except extérieure.
Utilisation de TApplication.HandleException
HandleException propose une gestion par défaut des exceptions au niveau de
l’application. Si une exception passe au travers de tous les blocs try du code de
l’application, l’application appelle automatiquement la méthode HandleException
qui affiche une boîte de dialogue indiquant qu’une erreur a eu lieu. Vous pouvez
utiliser HandleException de la manière suivante :
try
{ instructions }
except
Application.HandleException(Self);
end;
Pour toutes les exceptions sauf EAbort, HandleException appelle, s’il existe, le
gestionnaire d’événement OnException. Si vous voulez à la fois gérer l’exception
et proposer, comme la VCL, ce comportement par défaut, ajoutez un appel de
HandleException à votre code :
try
{ instructions spéciales }
except
on ESomething do
begin
{ ne gère que les instructions spéciales }
Application.HandleException(Self);{ appelle HandleException }
end;
end;
Pour davantage d’informations, voir dans l’aide en ligne la liste des routines de
gestion des exceptions
Exceptions silencieuses
Les applications Delphi gèrent la plupart des exceptions qui ne sont pas gérées
spécifiquement dans votre code en affichant une boîte de message qui affiche la
chaîne de message de l’objet exception. Vous pouvez également définir des
exceptions “silencieuses” pour lesquelles, par défaut l’application n’affiche pas le
message d’erreur.
Les exceptions silencieuses sont utiles quand vous ne voulez pas gérer une
exception mais simplement abandonner l’opération. L’abandon d’une opération
est semblable à l’utilisation des procédures Break et Exit pour sortir d’un bloc,
mais elle permet de sortir de plusieurs niveaux de blocs imbriqués.
Les exceptions silencieuses descendent toutes du type d’exception standard
EAbort. Le gestionnaire d’exception par défaut des applications VCL Delphi
affiche la boîte de dialogue de message d’erreur pour toutes les exceptions qu’il
reçoit sauf pour celles qui dérivent de EAbort.
Remarque Dans les applications console, la boîte de dialogue d’erreur est affichée même
pour une exception EAbort.
Il y a un moyen rapide de déclencher des exceptions silencieuses : au lieu de
construire l’objet manuellement, vous pouvez appeler la procédure Abort. Abort
déclenche automatiquement une exception EAbort qui sort de l’opération en
cours sans afficher de message d’erreur.
Exemple L’exemple suivant propose un exemple simple d’abandon d’une opération. Dans
une fiche contenant une boîte liste vide et un bouton, attachez le code suivant à
l’événement OnClick du bouton :
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 1 to 10 do{ boucler dix fois }
begin
ListBox1.Items.Add(IntToStr(I));{ ajouter un nombre à la liste }
if I = 7 then Abort;{ arrêter au septième }
end;
end;
Pour déclencher une exception, appelez le mot réservé raise en le faisant suivre
par une instance d’un objet exception. Quand un gestionnaire d’exception gère
effectivement l’exception, il se termine en détruisant l’instance d’exception : vous
n’avez donc jamais à le faire vous-même.
L’initialisation de l’adresse de l’exception se fait par l’intermédiaire de la variable
ErrorAddr définie dans l’unité System. Le déclenchement d’une exception affecte à
cette variable l’adresse à laquelle l’application déclenche l’exception. Vous
pouvez faire référence à ErrorAddr dans vos gestionnaires d’exceptions, par
exemple pour informer l’utilisateur de l’emplacement de l’erreur. Vous pouvez
aussi spécifier la valeur de ErrorAddr quand vous déclenchez une exception.
Pour spécifier l’adresse de l’erreur d’une exception, ajoutez le mot réservé at
après l’instance d’exception en la faisant suivre d’une expression adresse, par
exemple un identificateur.
Par exemple, étant donné la déclaration suivante :
type
EPasswordInvalid = class(Exception);
vous pouvez déclencher une exception “mot de passe incorrect” à tout moment
en appelant raise avec une instance de EPasswordInvalid, comme suit :
if Password <> CorrectPassword then
raise EPasswordInvalid.Create('Mot de passe saisi incorrect');
Création d’interfaces
Une interface est semblable à une classe ne contenant que des méthodes
abstraites et une définition claire de ses fonctionnalités. Strictement parlant, les
définitions des méthodes d’interface spécifient le nombre et le type de leurs
paramètres, le type renvoyé et le comportement prévu. Les méthodes d’une
interface sont reliées, sémantiquement ou logiquement, pour indiquer le rôle de
l’interface. Par convention, les interfaces sont nommées en fonction de leur
comportement en préfixant leur nom par une lettre I en majuscule. Par exemple,
une interface IMalloc doit allouer, libérer et gérer de la mémoire. De même, une
interface IPersist peut être utilisée comme une interface de base générale pour
Que ces deux classes aient ou non un ancêtre commun, elles sont toujours
compatibles pour l’affectation avec une variable de type IPaint :
var
Painter: IPaint;
begin
Painter := TSquare.Create;
Painter.Paint;
Painter := TCircle.Create;
Painter.Paint;
end;
Il est possible d’obtenir le même résultat en faisant dériver TCircle et TSquare
d’une classe TFigure qui implémente la méthode virtuelle Paint. Dans ce cas
TCircle et TSquare doivent surcharger la méthode Paint. IPaint est alors remplacée
par TFigure. Cependant, considérez l’interface suivante :
IRotate = interface
procedure Rotate(Degrees: Integer);
end;
qui a du sens pour un rectangle, mais pas pour le cercle. Les classes seraient
alors définies de la manière suivante :
TSquare = class(TRectangularObject, IPaint, IRotate)
procedure Paint;
procedure Rotate(Degrees: Integer);
end;
TCircle = class(TCustomShape, IPaint)
procedure Paint;
end;
Vous pouvez, ultérieurement créer une classe TFilledCircle qui implémente
l’interface IRotate afin de permettre la rotation du motif utilisé pour remplir le
cercle sans avoir à ajouter la rotation au cercle simple.
Remarque Dans ces exemples, on suppose que la classe de base immédiate ou une classe
ancêtre a implémenté les méthodes de IUnknown qui gèrent le comptage de
références. Pour davantage d’informations, voir “Implémentation de IUnknown”
à la page 4-18 et “Gestion mémoire des objets interface” à la page 4-22.
Implémentation de IUnknown
Toutes les interfaces dérivent, directement ou non, de l’interface IUnknown. Cette
interface définit les fonctionnalités essentielles d’une interface, c’est-à-dire
l’interrogation dynamique et la gestion de la durée de vie. Ces fonctionnalités
sont mises en place par les trois méthodes de IUnknown :
• QueryInterface est une méthode d’interrogation dynamique d’un objet donné
qui obtient les références des interfaces gérées par l’objet.
• AddRef est une méthode de comptage de références qui incrémente le
compteur à chaque appel réussi de QueryInterface. Tant que le compteur de
référence est non nul, l’objet doit rester en mémoire.
• Release est utilisée en conjonction avec AddRef pour permettre à un objet de
connaître sa durée de vie et de déterminer s’il peut se supprimer lui-même.
Quand le compteur de références atteint zéro, l’implémentation de l’interface
libère les objets sous-jacents.
Chaque classe qui implémente des interfaces doit implémenter les trois méthodes
de IUnknown, les autres méthodes déclarées dans toutes ses interfaces ancêtre,
ainsi que toutes les méthodes déclarées dans l’interface même. Néanmoins, vous
pouvez hériter de l’implémentation des méthodes d’interface déclarées dans
votre classe.
TInterfacedObject
La VCL définit une classe simple, TInterfacedObject qui, pratiquement, sert de
classe de base car elle implémente les méthodes de IUnknown. La classe
TInterfacedObject est déclarée de la manière suivante dans l’unité System :
type
TInterfacedObject = class(TObject, IUnknown)
private
FRefCount: Integer;
protected
function QueryInterface(const IID: TGUID; out Obj): Integer; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
property RefCount: Integer read FRefCount;
end;
Dériver directement de TInterfacedObject est trivial. Dans l’exemple de déclaration
suivant, TDerived est un descendant direct de TInterfacedObject qui implémente
une interface hypothétique, IPaint :
type
TDerived = class(TInterfacedObject, IPaint)
...
end;
Comme TInterfacedObject implémente les méthodes de IUnknown, elle gère
automatiquement le comptage de références et la gestion mémoire pour les objets
interfacés. Pour davantage d’informations, voir “Gestion mémoire des objets
interface” à la page 4-22 qui traite également de l’écriture de classes
implémentant des interfaces sans utiliser le mécanisme de comptage de
références inhérent à TInterfacedObject.
Utilisation de l’opérateur as
Les classes implémentant des interfaces peuvent utiliser l’opérateur as pour se
lier dynamiquement à l’interface. Dans l’exemple suivant :
procedure PaintObjects(P: TInterfacedObject)
var
X: IPaint;
begin
X := P as IPaint;
{ instructions }
end;
la variable P, de type TInterfacedObject, peut être affectée à la variable X qui est
une référence à l’interface IPaint. La liaison dynamique rend cette affectation
possible. Le compilateur génère pour cette affectation le code appelant la
méthode QueryInterface de l’interface IUnknown de P ; le compilateur ne peut
savoir à partir du type déclaré de P si l’instance de P gère réellement IPaint. A
l’exécution, soit P se résoud en une référence à une interface IPaint, soit une
exception est déclenchée. Dans l’un ou l’autre cas, l’affectation de P à X ne
génère pas une erreur à la compilation comme se serait le cas si P avait pour
type une classe n’implémentant pas IUnknown.
Quand vous utilisez l’opérateur as pour une liaison dynamique avec une
interface, vous devez respecter les règles suivantes :
• Déclaration explicite de IUnknown : même si toutes les interfaces dérivent de
IUnknown, il ne suffit pas qu’une classe implémente les méthodes de
IUnknown pour pouvoir utiliser l’opérateur as. Cela reste vrai même si la classe
IColorRef = interface
['{1d76360b-f4f5-11d1-87d4-00c04fb17199}']
function Color: Integer;
end;
{ TRGB8ColorRefAdapter associe un IRGB8bit à un IColorRef }
TRGB8ColorRefAdapter = class(TInterfacedObject, IRGB8bit, IColorRef)
private
FRGB8bit: IRGB8bit;
FPalRelative: Boolean;
public
constructor Create(rgb: IRGB8bit);
property RGB8Intf: IRGB8bit read FRGB8bit implements IRGB8bit;
property PalRelative: Boolean read FPalRelative write FPalRelative;
function Color: Integer;
end;
implementation
constructor TRGB8ColorRefAdapter.Create(rgb: IRGB8bit);
begin
FRGB8bit := rgb;
end;
function TRGB8ColorRefAdapter.Color: Integer;
begin
if FPalRelative then
Result := PaletteRGB(RGB8Intf.Red, RGB8Intf.Green, RGB8Intf.Blue)
else
Result := RGB(RGB8Intf.Red, RGB8Intf.Green, RGB8Intf.Blue);
end;
end.
Pour davantage d’informations sur la syntaxe, les détails de l’implémentation et
les règles concernant le mot-clé implements, voir dans le Guide du Langage Pascal
Objet, le chapitre Interfaces d’objet.
Agrégation
L’agrégation propose une approche modulaire de la réutilisation de code via des
sous-objets définissant les fonctionnalités d’un objet conteneur tout en lui cachant
les détails de l’implémentation. Dans l’agrégation, un objet externe implémente
une ou plusieurs interfaces. La seule exigence est qu’il implémente IUnknown.
L’objet interne (il peut y en avoir plusieurs) peut implémenter une ou plusieurs
interfaces, mais seul l’objet externe expose les interfaces. Cela vaut pour les
interfaces qu’il implémente et pour celles implémentées par les objets qu’il
contient. Les clients ne savent rien des objets internes. C’est l’objet externe qui
donne accès aux interfaces de l’objet interne, leur implémentation étant
totalement transparente. Cependant la classe objet externe peut échanger le type
de classe de l’objet interne avec toute classe qui implémente la même interface.
Réciproquement, le code des classes d’objet interne peut être partagé avec les
autres classes souhaitant l’utiliser.
begin
y := TTest.Create; // comme y est de type ITest, le compteur de références vaut un
beep(y); // l’appel de la fonction beep incrémente le compteur de références
// et le décrémente à son retour
y.something; // l’objet est toujours là avec un compteur de références valant un
end;
C’est la manière la plus claire et la plus prudente de gérer la mémoire et, si vous
utilisez TInterfacedObject, elle est utilisée automatiquement. Si vous ne respectez
pas ces règles, votre objet peut disparaître inopinément, comme l’illustre le code
suivant :
function test_func()
var
x: TTest;
begin
x := TTest.Create; // pas encore de compteur de références pour l’objet
beep(x as ITest); // le compteur est incrémenté par l’appel de beep
// et décrémenté à son retour
x.something; // surprise! l’objet n’est plus là
end;
Remarque Dans les exemples précédents, la procédure beep, telle qu’elle est déclarée,
incrémente le compteur de référence (appel de AddRef) pour le paramètre. Par
contre, les déclarations suivantes :
procedure beep(const x: ITest);
ou
procedure beep(var x: ITest);
ne le font pas. Ces déclarations génèrent un code plus concis et plus rapide.
Vous ne pouvez pas utiliser le comptage de références dans un cas : si votre
objet est un composant ou un contrôle contenu dans un autre composant. Dans
un tel cas, le comptage de références ne peut être appliqué de manière
cohérente : vous pouvez toujours utiliser les interfaces, mais vous ne devez pas
utiliser le comptage de référence car la durée de vie de l’objet n’est pas
gouvernée par ses interfaces.
CORBA est une autre technologie d’application utilisant des objets distribués.
L’utilisation des interfaces dans les applications CORBA se fait par
l’intermédiaire de classes stub pour le client et de classes squelettes pour le
serveur. Ces classes stub et squelettes gèrent les détails du marshaling des appels
d’interface afin que les valeurs des paramètres et les valeurs renvoyées soient
correctement transmises. Les applications doivent utiliser une classe stub ou
squelette, ou employer l’interface d’appel dynamique (abrégé en anglais par DII)
qui convertit tous les paramètres en variants spéciaux afin qu’ils contiennent
eux-même leurs propres informations de type. Bien que cela ne soit pas une
caractéristique impérative dans la technologie CORBA, Delphi implémente
CORBA en utilisant des fabricants de classe, de la même manière que COM
utilise les fabricants de classe et les CoClasses. En unifiant ainsi ces deux
architectures distribuées, Delphi peut gérer un serveur combiné COM/CORBA
capable de répondre simultanément à des clients COM ou CORBA. Pour
davantage d’informations sur l’utilisation des interfaces dans Corba, voir
chapitre 27, “Ecriture d’applications CORBA”.
Types caractère
Delphi a trois types caractère : Char, AnsiChar et WideChar.
Le type caractère Char provient du Pascal standard, il a été utilisé dans Turbo
Pascal puis en Pascal Objet. Plus tard, le Pascal Objet a ajouté les types AnsiChar
et WideChar comme des types caractère spécifiques utilisés pour gérer les
représentations standard des caractères dans le système d’exploitation Windows.
AnsiChar a été ajouté pour gérer le jeu de caractères ANSI sur 8 bits et WideChar
pour gérer le jeu de caractères 16 bits Unicode. Les caractères de type WideChar
sont également appelés caractères étendus. Les caractères étendus sont codés sur
deux octets afin que le jeu de caractères puisse représenter davantage de
caractères différents. Quand AnsiChar et WideChar ont été implémentés, Char est
devenu le type caractère par défaut représentant l’implémentation dont
l’utilisation est conseillée pour un système donné. Si vous utilisez Char dans une
application, n’oubliez pas que son implémentation est susceptible de changer des
versions ultérieures de Delphi.
Pour davantage d’informations sur l’utilisation de ces types caractère, voir dans
l’aide en ligne du Guide du langage Pascal Objet la rubrique Types caractère.
Pour davantage d’informations sur les caractères Unicode, voir dans l’aide en
ligne du Guide du langage Pascal Objet la rubrique “A propos des jeux de
caractère étendus”
Types chaîne
Delphi propose trois catégories de types que vous pouvez utiliser pour
manipuler des chaînes : les pointeurs de caractère, les types chaîne et les classes
chaîne VCL. Cette sectionprésente les types chaîne et décrit leur utilisation avec
les pointeurs de caractère. Pour des informations sur les classes chaîne VCL, voir
dans l’aide en ligne la rubrique TStrings.
Delphi dispose aujourd’hui de trois implémentations de chaîne : les chaînes
courtes, les chaînes longues et les chaînes étendues. Il existe plusieurs types
chaîne qui représentent ces implémentations. De plus, le mot réservé string
correspond par défaut à l’implémentation de chaîne actuellement recommandée.
Chaînes courtes
String a été le premier type chaîne utilisé en Turbo Pascal. String était à
l’origine implémenté avec une chaîne courte. Les chaînes courtes allouent entre 1
et 256 octets : le premier octet contenant la longueur de la chaîne, les octets
restants contenant les caractères de la chaîne :
S: string [0..n]// le type string original
Quand les chaînes longues ont été implémentées, string a été modifié pour
exploiter par défaut une implémentation de chaîne longue et ShortString a été
introduit comme type permettant la compatibilité ascendante. ShortString est un
type prédéfini pour une chaîne de longueur maximum :
S: string [255]// Le type ShortString
La quantité de mémoire allouée pour un ShortString est statique, c’est-à-dire
qu’elle est déterminée à la compilation. Par contre, l’emplacement de la mémoire
d’un ShortString peut être allouée dynamiquement (par exemple si vous utilisez
un PShortString qui est un pointeur sur un ShortString). Le nombre d’octets de
Chaînes longues
Les chaînes longues sont des chaînes allouées dynamiquement dont la longueur
maximum est limitée uniquement par la mémoire disponible. Comme les chaînes
courtes, les chaînes longues utilisent des caractères ANSI sur 8 bits et un
indicateur de longueur. A la différence des chaînes courtes, les chaînes longues
n’ont pas un élément zéro contenant la longueur dynamique de la chaîne. Pour
connaître la longueur d’une chaîne longue, vous devez utiliser la fonction
standard Length et pour spécifier sa longueur vous devez utiliser la procédure
standard SetLength. Les chaînes longues utilisent le comptage de références et,
comme les PChars, ce sont des chaînes à zéro terminal. Pour davantage
d’informations sur l’implémentation des chaînes longues, voir dans l’aide en
ligne du Guide du langage Pascal Objet la rubrique Chaînes longues
Les chaînes longues sont désignées par le mot réservé string et par
l’identificateur prédéfini AnsiString. Dans les nouvelles applications, il est
conseillé d’utiliser le type chaîne longue. Tous les composants de la VCL sont
compilés de cette manière, généralement en utilisant string. Si vous écrivez des
composants, ils doivent également utiliser des chaînes longues tout comme doit
le faire le code recevant des données provenant de propriétés VCL de type
chaîne. Si vous voulez écrire du code spécifique qui utilise systématiquement
une chaîne longue, vous devez utiliser AnsiString. Si vous voulez écrire du code
flexible qui vous permet de changer facilement le type quand une nouvelle
implémentation de chaîne deviendra la norme, vous devez alors utiliser string.
Chaînes étendues
Le type WideChar permet de représenter des chaînes de caractères étendus comme
des tableaux de WideChars. Les chaînes étendues sont des chaînes composées de
caractères Unicode sur 16 bits. Comme les chaînes longues, les chaînes étendues
sont allouées dynamiquement et leur longueur maximum n’est limitée que par la
quantité de mémoire disponible. Par contre, les chaînes étendues n’utilisent pas le
comptage de références. La mémoire allouée dynamiquement pour la chaîne est
libérée quand la chaîne étendue sort de portée. Pour tout le reste, les chaînes
étendues ont les mêmes attributs que les chaînes longues. Le type chaîne étendu
est désigné par l’identificateur prédéfini WideString.
Comme la version 32 bits de OLE utilise Unicode, toutes les chaînes doivent être
de type chaîne étendu dans les propriétés et paramètres de méthodes OLE
Automation. De plus, la plupart des fonctions de l’API OLE utilisent des chaînes
étendues à zéro terminal.
Pour davantage d’informations sur les chaînes étendues, voir dans l’aide en ligne
du Guide du langage Pascal Objet la rubrique Chaînes étendues
Types PChar
Un PChar est un pointeur sur une chaîne à zéro terminal de caractères de type
Char. Chacun des trois types caractère dispose d’un type de pointeur prédéfini :
• Un PChar est un pointeur sur une chaîne à zéro terminal de caractères 8 bits.
• Un PAnsiChar est un pointeur sur une chaîne à zéro terminal de caractères 8 bits.
• Un PWideChar est un pointeur sur une chaîne à zéro terminal de caractères
16 bits.
PChar est, avec les chaînes courtes, l’un des types chaîne qui existaient à l’origine
dans le Pascal Objet. Il a été conçu à l’origine pour assurer la compatibilité avec
les types du langage C et de l’API Windows.
Chaînes ouvertes
Le type OpenString est largement obsolète mais vous pouvez le rencontrer dans
du code ancien. Il n’existe que pour la compatibilité 16 bits et n’est autorisé que
dans les paramètres. Les chaînes ouvertes étaient utilisées, avant
l’implémentation des chaînes longues, pour permettre le transfert comme
paramètre d’une chaîne courte de taille indéterminée. Le type OpenString était
donc utile quand le type chaîne courte était la seule représentation possible pour
une chaîne. Par exemple, la déclaration suivante :
procedure a(v : openstring);
permet de transmettre comme paramètre une chaîne de longueur quelconque. En
son absence, la longueur de chaîne des paramètres formel et réel doivent
correspondre exactement. Vous n’avez pas besoin d’utiliser OpenString dans les
nouvelles applications que vous écrivez.
Pour d’autres informations sur la directive de compilation {$P+/-} voir
“Directives de compilation portant sur les chaînes”.
Les routines utilisées pour les noms de fichier sous forme de chaîne :
AnsiCompareFileName, AnsiLowerCaseFileName et AnsiUpperCaseFileName utilisent
toutes la localisation Windows. Vous devez toujours utiliser des noms de fichier
totalement portables car la localisation (le jeu de caractères) utilisée pour les
noms de fichier peut changer selon l’interface utilisateur par défaut.
Dépendances de chaîne
Il est parfois nécessaire de convertir des chaînes longues en chaînes à zéro
terminal, par exemple si vous utilisez une fonction qui attend un PChar.
Cependant, comme les chaînes longues utilisent le comptage de références, le
transtypage d’une chaîne en un PChar augmente de un les dépendances de la
chaîne sans augmenter également le compteur de références. Quand le compteur
de références atteint zéro, la chaîne est détruite même s’il y a encore des
dépendances portant dessus. Le transtypage en PChar disparaît également, et ce
alors même que la routine à laquelle vous l’avez transmis l’utilise peut-être
encore. Si vous transtypez une chaîne en un PChar, c’est vous qui êtes
responsable de la durée de vie du PChar résultant. Par exemple :
procedure my_func(x: string);
begin
// faire quelque chose avec x
some_proc(PChar(x)); // transtype la chaîne en PChar
// vous devez maintenant garantir que la chaîne existe
// tant que la procédure some_proc a besoin de l’utiliser
end;
Sujets apparentés
Voici une liste de thèmes concernant également les types caractère et chaîne :
Tableaux de caractères
Pour des informations sur la manipulation des tableaux de caractères, voir dans
la version en ligne du Guide du langage Pascal Objet la rubrique “Utilisation de
chaînes à zéro terminal”.
Chaînes de caractères
Pour des informations sur les chaînes de caractères, voir dans la version en ligne
du Guide du langage Pascal Objet la rubrique Chaînes de caractères
Pointeurs de caractère
Pour des informations sur les pointeurs de caractère, voir dans la version en
ligne du Guide du langage Pascal Objet la rubrique Pointeurs de caractère
Opérateurs de chaîne
Pour des informations sur les opérateurs de chaîne, voir dans la version en ligne
du Guide du langage Pascal Objet la rubrique Opérateurs de chaîne
Remarque Les versions précédentes du langage Pascal Objet effectuaient les opérations sur les
fichiers mêmes et non pas sur des paramètres nom de fichier, comme c’est le cas
aujourd’hui. Avec les anciens types fichier, vous deviez trouver le fichier, l’affecter
à une variable fichier avant de pouvoir, par exemple, renommer le fichier.
Manipulation de fichiers
Plusieurs opérations courantes portant sur les fichiers sont prédéfinies dans la
bibliothèque d’exécution Pascal Objet. Les procédures et fonctions manipulant les
fichiers agissent à un niveau élevé. Pour la plupart des routines, il vous suffit de
spécifier le nom du fichier et la routine fait pour vous les appels nécessaires au
système d’exploitation. Dans certains cas, vous utiliserez à la place des handles de
fichier. Le Pascal Objet propose des routines pour la plupart des manipulations de
fichier. Quand ce n’est pas le cas, d’autres routines sont décrites.
Fichiers Pascal ancien style – Ce sont les types fichier utilisés pour les anciennes
variables fichier, généralement de la forme "F: Text: ou "F: File". Il existe trois
formes de ces fichiers : typé, texte et sans type. De nombreuses routines de
gestion de fichier Delphi, comme AssignPrn ou writeln, les utilisent. Ces types
fichier sont globalement obsolètes et sont incompatibles avec les handles de
fichier Windows. Si vous avez besoin de travailler avec ces types de fichier
ancienne manière, consultez l’aide en ligne du Guide du langage Pascal Objet qui
aborde en détail leur utilisation pour les E/S de fichier.
Handles de fichier Windows – Les handles de fichier Pascal Objet encapsulent
le type de handle de fichier Windows. Les routines de manipulation de fichier
de la bibliothèque d’exécution qui utilisent des handles de fichier Windows
encapsulent généralement des fonctions de l’API Windows. Ainsi, FileRead
appelle la fonction Windows ReadFile. Comme les fonctions Delphi utilisent la
syntaxe Pascal Objet et peuvent spécifier la valeur par défaut de paramètres,
elles peuvent servir commodément d’interface avec l’API Windows. L’utilisation
de ces routines est évidente et, si vous êtes à l’aise avec les routines de fichier de
l’API Windows, vous pouvez les utiliser pour manipuler les E/S de fichier.
Flux fichier – Les flux fichier sont des instances d’objet de la classe TFileStream
de la VCL utilisées pour accéder aux informations de fichiers disque. Les flux
fichier sont portables et proposent une approche de haut niveau des opérations
d’E/S de fichier. TFileStream a une propriété Handle qui vous donne accès au
handle de fichier Windows. La section suivante décrit TFileStream.
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.
Valeur Signification
fmShareCompat Le partage est compatible avec la manière d’ouvrir les FCB.
fmShareExclusive En aucun cas, les autres applications ne peuvent 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.
Vous devez tout d’abord transtyper la chaîne en Pointer ou un PChar, puis alors
seulement la déréférencer. Par exemple :
procedure cast-string;
var
fs: TFileStream;
s: string = 'Hello';
begin
fs := TFileStream.Create('foo', fmCreate or fmOpenRead);
fs.Write(s, Length(s));// cela donne un résultat faux
fs.Write(PChar(s)^, Length(s));// Cela donne le bon résultat
end;
Valeur Signification
soFromBeginning Offset part du début de la ressource. Seek place à la position Offset. Offset
doit être >= 0.
soFromCurrent Offset part de la position en cours dans la ressource. Seek place à la
position 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.
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 du fichier. Si la taille du
fichier ne peut être modifiée, une exception est déclenchée. Ainsi, tenter de
modifier la taille d’un fichier ouvert dans le mode fmOpenRead déclenche une
exception.
Copie
CopyFrom copie le nombre spécifié d’octets d’un flux (fichier) dans un autre.
function CopyFrom(Source: TStream; Count: Longint): Longint;
L’utilisation de CopyFrom évite à l’utilisateur qui veut copier des données de
créer un tampon, d’y placer les données, de les écrire puis de libérer le tampon.
CopyFrom copie Count octets de Source dans le flux. CopyFrom déplace ensuite la
position en cours de Count octets et renvoie le nombre d’octets copiés. Si Count
vaut 0, CopyFrom initialise la position dans Source à 0 avant de lire puis de
copier dans le flux la totalité des données de Source. Si Count est supérieur ou
inférieur à 0, CopyFrom lit à partir de la position en cours dans Source.
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.
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|Utiliser unité.
3 Sélectionnez le nom de l’unité de la fiche qui doit être référencée.
4 Choisissez OK.
Lier une fiche à une autre signifie simplement que la clause uses de l’unité
d’une fiche contient une référence à l’unité de l’autre fiche. Ainsi la fiche liée et
ses composants rentrent dans la portée de la fiche.
Manipulation de l’application
La variable globale Application de type TApplication se trouve dans chaque
application Delphi Windows. 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.
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 et d’autres comportements de l’écran. Si
votre application 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.
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é sur un côté particulier de son
parent sans être redimensionné pour autant 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.
TControl introduit un événement protégé, OnConstrainedResize, de type
TConstrainedResizeEvent :
TConstrainedResizeEvent = procedure (Sender: TObject; var MinWidth, MinHeight, MaxWidth,
MaxHeight: Integer) of object;
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.
Conception de 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 vous pouvez partir de l’un des modèles de menu prédéfinis
proposés par Delphi.
Comme pour le composant menu, Delphi 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.
Remarque Vous ne pouvez pas supprimer l’emplacement par défaut qui apparaît en
dessous du dernier élément ajouté à la liste de menus ou à côté du dernier
élément de la barre de menu. Cet emplacement n’apparaît pas dans le menu à
l’exécution.
Création de sous-menus
La plupart des menus d’application contiennent des liste déroulantes qui
apparaissent à côté d’un élément de menu afin de proposer des commandes
associées supplémentaires. De telles listes sont signalées par un pointeur à droite
de l’élément de menu. Delphi gère les niveaux de sous-menus sans aucune
limitation dans l’imbrication.
Elément de menu de
la barre de menu
Elément de menu
d’une liste de menus
Elément de menu
imbriqué
Remarque Pour un affichage correct dans les menus, utilisez des images de 16 sur 16 pixels.
Même si vous pouvez utiliser d’autres tailles pour les images placées dans les
menus, il peut y avoir des problèmes d’alignement si vous utilisez des images
plus grandes ou plus petites que 16 x 16 pixels.
Affichage du menu
Vous pouvez voir votre menu dans la fiche à la conception sans exécuter le code
de votre programme. Les composants menu surgissant sont visibles dans la fiche
à la conception, mais pas le menu surgissant lui-même. Utilisez le concepteur de
menus pour visualiser un menu surgissant à la conception.
Pour visualiser le menu :
1 Si la fiche n’est pas visible, cliquez dans la fiche ou dans le menu Voir,
choisissez la fiche que vous voulez voir.
2 Si la fiche contient plusieurs menus, sélectionnez le menu à visualiser dans la
liste déroulante de la propriété Menu de la fiche.
Le menu apparaît dans la fiche exactement tel qu’il apparaîtra à l’exécution du
programme.
Pour utiliser le menu contextuel afin de passer d’un menu de la fiche à un autre :
1 Cliquez avec le bouton droit de la souris dans le concepteur de menus et
choisissez Sélectionnez un menu.
La boîte de dialogue Sélection de menu s’affiche.
Figure 5.6 Boîte de dialogue Sélection de menu
Cette boîte de dialogue énumère tous les menus associés à la fiche dont les
menus sont ouverts dans le concepteur de menus.
2 Dans la liste de la boîte de dialogue Sélection de menu, choisissez le menu
que vous voulez voir ou modifier.
Pour utiliser l’inspecteur d’objets afin de passer d’un menu de la fiche à un
autre :
1 Sélectionnez la fiche dont vous voulez choisir un menu.
2 Dans la liste des composants, sélectionnez le menu que vous voulez modifier.
3 Dans la page Propriétés de l’inspecteur d’objets, sélectionnez la propriété Items
de ce menu, puis cliquez sur le bouton points de suspension ou double-
cliquez sur [Menu].
2 Sélectionnez le modèle de menu que vous voulez insérer, puis appuyez sur
Entrée ou choisissez OK.
Cela insère le menu dans votre fiche à la position courante du curseur. Si, par
exemple, le curseur est positionné sur un élément de menu d’une liste, le
modèle de menu est inséré en dessous de l’élément sélectionné. Si le curseur
est dans la barre de menu, le modèle de menu est inséré à gauche du curseur.
Pour supprimer un modèle de menu :
1 Cliquez avec le bouton droit de la souris dans le concepteur de menus et
choisissez Supprimer les modèles.
(S’il n’y a pas de modèles, l’option Supprimer les modèles apparaît estompée
dans le menu contextuel.)
La boîte de dialogue Suppression de modèles est ouverte et affiche une liste
des modèles existants.
2 Sélectionnez le modèle de menu à supprimer et appuyez sur Suppr.
Delphi supprime le modèle dans la liste des modèles et sur le disque dur.
Les modèles de menu que vous enregistrez sont stockés dans le sous-répertoire
BIN dans des fichiers .DMT.
Pour enregistrer un menu comme modèle
1 Concevez le menu que vous voulez pouvoir réutiliser.
Ce menu peut contenir de nombreux éléments, commandes et sous-menus :
tout dans le contenu de la fenêtre active du concepteur de menus est
enregistré comme un seul menu réutilisable.
2 Cliquez avec le bouton droit de la souris dans le concepteur de menus et
choisissez Enregistrer comme modèle.
La boîte de dialogue Enregistrement de modèle s’ouvre.
Figure 5.8 Boîte de dialogue Enregistrement de modèle des menus
Fusion de menus
Dans les applications MDI, comme l’application exemple éditeur de texte ou
dans les applications client OLE, le menu principal de votre application doit être
capable d’intégrer les éléments de menu d’une autre fiche ou d’un objet serveur
OLE. Ce processus s’appelle la fusion de menus.
Pour préparer des menus à la fusion, vous devez spécifier les valeurs de deux
propriétés :
• Menu, une propriété de la fiche.
• GroupIndex, une propriété des éléments du menu.
La hauteur par défaut d’un volet est 41 et la hauteur par défaut d’un
turbobouton est 25. Si vous affectez la valeur 8 à la propriété Top de chaque
bouton, ils sont centrés verticalement. Le paramétrage par défaut de la grille
aligne verticalement le turbobouton sur cette position.
Si, par exemple, votre application propose un outil de dessin activé par défaut,
vérifiez que le bouton correspondant de la barre d’outils est enfoncé au
démarrage de l’application. Pour ce faire, affectez une valeur non nulle à sa
propriété GroupIndex et la valeur True à sa propriété Down.
Seuls les composants dérivant de TWinControl sont des contrôles fenêtrés. Vous
pouvez ajouter à la barre multiple des contrôles graphiques (comme les libellés
ou les turboboutons), mais ils n’apparaissent pas dans des bandes distinctes.
Remarque Le composant barre multiple nécessite une version 4.70 ou ultérieure de
COMCTL.DLL.
end;
Il reste alors à spécifier les actions effectuées quand l’utilisateur a cliqué sur ce
bouton.
Objets action
Les actions sont des commandes utilisateur portant sur des objets cible. Les
actions sont créées dans l’éditeur de composant liste d’actions. Ces actions sont
ultérieurement connectées à des contrôles client via leur liaison d’action. Le
mécanisme action/liste d’action fait intervenir les composants suivants :
• Une action (TAction) est l’implémentation d’une action (par exemple, copier le
texte sélectionné) dans une cible (par exemple, un contrôle de saisie). Une
action est déclenchée par un client en réponse à une commande de
l’utilisateur (c’est-à-dire un clic de la souris). Les clients sont habituellement
des éléments de menu ou des boutons. L’unité StdActns contient des classes,
dérivées de TAction, qui implémentent les commandes de menu (les actions)
standard d’édition et de manipulation des fenêtres qui apparaissent dans la
plupart des applications Windows.
• Une liste d’actions (TActionList) est un composant qui gère une liste d’actions
(TAction). Les listes d’actions servent à la conception d’interface utilisateur
permettant de manipuler des actions.
• Une liaison d’action (TActionLink) est un objet qui gère la connexion entre les
actions et les clients. Les liaisons d’action déterminent si une action, et
laquelle, est actuellement applicable à un client donné.
• Le client d’une action est habituellement un élément de menu ou un bouton
(TToolButton, TSpeedButton, TMenuItem, TButton, TCheckBox, TRadioButton, etc).
Une action est initiée par une commande correspondante dans le client.
Généralement un Click client est associé à l’Execute d’une action.
• La cible d’une action est généralement un contrôle, par exemple un éditeur de
texte formaté, un mémo ou un contrôle de données. L’unité DBActns, par
exemple, contient des classes qui implémentent des actions spécifiques aux
contrôles ensemble de données. Les concepteurs 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.
La figure suivante illustre les relations entre ces objets. Dans ce diagramme,
Couper1 est l’action, ActionList1 est la liste d’actions contenant Couper1,
SpeedButton1 est le client de Couper1 et Memo1 est la cible. A la différence des
actions, des listes d’actions, des clients d’action et des cibles d’action, les liaisons
d’action sont des objets non visuels. La liaison d’action est donc indiquée dans
ce diagramme par un rectangle blanc. La liaison d’action relie ensemble le client
SpeedButton1 et l’action Couper1 contenue dans ActionList1.
Figure 5.9 Mécanismes d’une liste d’action
• ComCtrls.pas : TToolButtonActionLink.
• Menus.pas : TMenuActionLink.
• StdCtrls.pas : TButtonActionLink.
Deux autres unités, StdActns et DBActns, contiennent des classes auxiliaires qui
implémentent des actions spécifiques courantes de Windows et des ensembles de
données. Pour davantage d’informations, voir “Classes d’actions prédéfinies” à la
page 5-40. La plupart des contrôles de la VCL proposent des propriétés (c’est-à-
dire Action) et des méthodes (c’est-à-dire ExecuteAction) qui permettent de les
utiliser comme client ou comme cible d’actions.
Centralisation du code
De nombreux contrôles, par exemple TToolButton, TSpeedButton, TMenuItem ou
TButton ont une propriété publiée nommée Action. Quand vous affectez à la
propriété Action l’une des actions de votre liste d’actions, les valeurs des
propriétés correspondantes de l’action sont copiées dans celles du contrôle.
Toutes les propriétés et événements en commun avec l’objet action (sauf Name et
Tag) sont liées dynamiquement au contrôle. Ainsi, par exemple, au lieu de
dupliquer le code désactivant des boutons et des éléments de menu, vous
pouvez centraliser ce code dans un objet action : quand l’action est désactivée,
tous les boutons et les éléments de menu correspondants sont désactivés.
Liaison de propriétés
La liaison d’action du client est le mécanisme par lequel ses propriétés sont
associées (liées) aux propriétés d’une action. Quand une action change, c’est la
liaison d’action qui est responsable de l’actualisation des propriétés du client. Pour
davantage d’informations sur les propriétés gérées par une classe donnée de liaison
d’actions, voir les diverses classes de liaison d’action dans l’aide en ligne de la VCL.
Vous pouvez surcharger de manière sélective les valeurs des propriétés
contrôlées par un objet action associé en initialisant la valeur de la propriété
dans le composant ou le contrôle client. Cela ne modifie pas la valeur de la
propriété dans l’action et seul le client est affecté.
Exécution d’actions
Quand un composant ou un contrôle client est cliqué, l’événement OnExecute se
produit pour son action associée. Par exemple, le code suivant est le gestionnaire
d’événement OnExecute pour une action qui inverse la visibilité d’une barre
d’outils quand une action est exécutée :
procedure TForm1.Action1Execute(Sender: TObject);
begin
{ Inverse la visibilité de Toolbar1 }
ToolBar1.Visible := not ToolBar1.Visible;
end;
Remarque Si vous utilisez un bouton outil ou un élément de menu, vous devez initialiser
manuellement la propriété Images de la barre d’outils ou du menu correspondant
avec la propriété Images de la liste d’actions. Cela reste vrai même si la propriété
ImageIndex est liée dynamiquement au client.
La figure suivante illustre la séquence de répartition du cycle d’exécution d’une
action nommée Couper1. Ce diagramme part de la relation illustrée par la
figure 5.9, ce qui signifie que le client Speedbutton1 est lié à l’action Couper1 via sa
liaison d’action. La propriété Action de Speedbutton1 a donc la valeur Couper1. En
conséquence, la méthode Click de Speedbutton1 appelle la méthode Execute de
Couper1.
Figure 5.10 Cycle d’exécution d’une action
Remarque Dans la description de cette séquence, l’appel d’une méthode par une autre ne
signifie pas nécessairement que l’appel apparaît explicitement dans le code de la
méthode.
Recensement d’actions
Vous pouvez recenser ou annuler le recensement de vos propres actions dans
l’EDI en utilisant les routines globales de l’unité ActnList :
procedure RegisterActions(const CategoryName: string; const AClasses: array of
TBasicActionClass);
procedure UnRegisterActions(const AClasses: array of TBasicActionClass);
Utilisez ces routines de la même manière que RegisterComponents s’utilise pour
recenser des composants. Par exemple, le code suivant recense dans l’EDI les
actions standard de l’unité StdReg :
{ recensement des actions standard }
RegisterActions('', [TAction]);
RegisterActions('Edit', [TEditCut, TEditCopy, TEditPaste]);
RegisterActions('Window', [TWindowClose, TWindowCascade, TWindowTileHorizontal,
TWindowTileVertical, TWindowMinimizeAll, TWindowArrange]);
Programmes exemple
Pour des exemples de programmes utilisant les actions et les listes d’actions, voir
le projet du répertoire Delphi\Demos\RichEdit. De plus, les experts application,
application MDI, application SDI et application logo Win95 peuvent utiliser les
objets action et liste d’actions.
Les objets glissés peuvent être déplacés entre plusieurs .DLL ainsi qu’à l’intérieur
de l’EXE principal. C’est pratique si vous n’utilisez pas des paquets, mais
souhaitez que les opérations glisser fonctionnant depuis des fiches implémentées
dans des .EXE fonctionnent dans des fiches implémentées dans des .DLL.
begin
WordWrap := not WordWrap; { active ou désactive le retour à la ligne }
if WordWrap then
ScrollBars := ssVertical { seule la barre verticale est nécessaire }
else
ScrollBars := ssBoth; { deux barres peuvent être nécessaires }
WordWrap1.Checked := WordWrap; { coche ou désactive l’élément de menu }
end;
end;
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.
Sélection de texte
Pour transférer du texte 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.
Les contrôles dessinés par le propriétaire ont un point commun : ils contiennent
tous des listes d’éléments. Par défaut, il s’agit de listes de chaînes que Windows
affiche 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 Delphi, la création d’un contrôle dessiné par le propriétaire se fait
généralement en trois étapes :
1 Choix 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
Utilisation de graphiques
Chapter 7
7
Plusieurs méthodes permettent de placer des images graphiques dans les
applications Delphi : des images prédessinées peuvent être insérées en phase de
conception, vous pouvez les créer en utilisant les contrôles graphiques en phase de
conception ou les dessiner dynamiquement à l’exécution. Ce chapitre explique
comment dessiner des graphiques à l’exécution (soit sur une fenêtre, soit sur un
contrôle personnalisé ou sur un contrôle dessiné par le propriétaire). Il fournit aussi
des informations sur la création de graphiques en mode conception en utilisant
des contrôles image (dessinés par le propriétaire).
Ce chapitre fournit des informations sur l’utilisation de graphiques dans la VCL.
Il traite des sujets suivants :
• Présentation de la programmation relative aux graphiques
• Utilisation des propriétés de l’objet canevas
• Utilisation des méthodes du canevas pour dessiner des objets graphiques
• Gestion de plusieurs objets de dessin dans une application
• Dessiner sur un bitmap
• Chargement et enregistrement des fichiers graphiques
• Utilisation du Presse-papiers avec des graphiques
• Exemple de la technique de dessin ’rubber- banding’
de périphérique. Que vous dessiniez sur des bitmaps, sur l’écran, sur
l’imprimante ou sur des métafichiers, vos programmes peuvent utiliser les
mêmes méthodes.
Les canevas sont uniquement disponibles en phase exécution. Tout le travail relatif
aux canevas se fait donc en écrivant du code. Les sections suivantes expliquent
comment utiliser les composants graphiques de la VCL pour simplifier les
opérations de programmation.
Remarque Puisque TCanvas est un gestionnaire de ressources qui enveloppe le contexte de
périphérique Windows, vous pouvez aussi utiliser toutes les fonctions GDI de
Windows sur le canevas. La propriété Handle du canevas est le Handle du
contexte de périphérique.
Rafraîchissement de l’écran
A certains moments, Windows détermine que l’apparence de certains objets
affichés à l’écran doit être rafraîchie. Il génère donc des messages WM_PAINT,
que la VCL redirige vers des gestionnaires d’événements OnPaint. Lorsque vous
utilisez la méthode Refresh, la VCL appelle n’importe quel gestionnaire
d’événement OnPaint ayant été écrit pour cet objet. Par défaut, Delphi nomme ce
gestionnaire d’événement FormPaint. La méthode Refresh est parfois utilisée pour
rafraîchir un composant sur une fiche. Par exemple, la méthode Refresh peut être
appelée dans le gestionnaire d’événement OnResize de la fiche afin de réafficher
des graphiques ou pour dessiner un fond sur la fiche.
Bien que certains systèmes d’exploitation gèrent automatiquement l’affichage des
zones clientes d’une fenêtre qui ne sont plus valides, Windows ne le fait pas.
Pour Windows, tout dessin est considéré comme permanent. Lorsqu’une fiche ou
un contrôle est temporairement masqué, par exemple lors d’un glisser-déplacer,
la fiche ou le contrôle doivent repeindre la zone masquée lorsqu’elle ne l’est
plus. Pour plus d’informations sur le message WM_PAINT, voir l’Aide en ligne
de Windows.
Lors de l’utilisation du contrôle TImage, la VCL gère automatiquement le dessin
et le rafraîchissement du graphique contenu dans le TImage. Dessiner sur un
TImage crée une image persitante. Par conséquent, il n’est pas nécessaire de
redessiner l’image contenue. Au contraire, le canevas d’un TPaintBox écrit
directement sur le pilote de l’écran, et de ce fait, tout ce qui est dessiné sur le
canevas du PaintBox est transitoire. Cela est vrai pour les contrôles similaires, y
compris la fiche elle-même. De plus, si vous dessinez ou peignez à partir du
constructeur d’un TPaintBox, vous devrez ajouter ce code dans le gestionnaire
OnPaint afin que l’image soit repeinte à chaque fois que la zone cliente est
invalidée.
Le crayon lui-même possède quatre propriétés qu’il est possible de changer : Color,
Width, Style, et Mode.
• Propriété Color: modifie la couleur du crayon
• Propriété Width: modifie la largeur du crayon
• Propriété Style: modifie le style du crayon
• Propriété Mode: modifie le mode du crayon
Les valeurs de ces propriétés déterminent la façon dont le crayon change les pixels
de la ligne. Par défaut, chaque crayon est noir, a une largeur de 1 pixel, est de style
uni, et a un mode appelé copie qui écrase tout ce qui se trouve déjà sur le canevas.
Dessin de lignes
Pour dessiner une ligne droite sur un canevas, utilisez la méthode LineTo du canevas.
La méthode LineTo dessine une ligne partant de la position en cours du crayon et
allant au point spécifié, et fait du point d’arrivée de la ligne la position en cours. Le
canevas dessine la ligne en utilisant son crayon.
Par exemple, la méthode suivante dessine des lignes diagonales qui se croisent sur
une fiche, chaque fois que la fiche est peinte :
procedure TForm1.FormPaint(Sender: TObject);
begin
with Canvas do
begin
MoveTo(0, 0);
LineTo(ClientWidth, ClientHeight);
MoveTo(0, ClientHeight);
LineTo(ClientWidth, 0);
end;
end;
Dessin de polylignes
En plus des lignes individuelles, le canevas peut dessiner des polylignes, qui
sont des groupes composés d’un nombre quelconque de segments de ligne reliés
entre eux.
Pour dessiner une polyligne sur un canevas, appelez la méthode PolyLine du
canevas.
Le paramètre passé à la méthode PolyLine est un tableau de points. Imaginez
qu’une polyligne réalise une méthode MoveTo sur le premier point et une méthode
LineTo sur chaque point successif. Si vous voulez dessiner plusieurs lignes, vous
devez savoir que Polyline est plus rapide que la méthode MoveTo et que la
méthode LineTo, car elle élimine un certain nombre d’appels supplémentaires.
La méthode suivante, par exemple, dessine un losange dans une fiche :
procedure TForm1.FormPaint(Sender: TObject);
begin
with Canvas do
PolyLine([Point(0, 0), Point(50, 0), Point(75, 50), Point(25, 50), Point(0, 0)]);
end;
Cet exemple montre bien les possibilités de Delphi de créer un paramètre tableau
ouvert à la volée. Il est possible de passer n’importe quel tableau de points, mais
une manière simple de construire un tableau facilement consiste à mettre ses
éléments entre crochets et de passer le tout en paramètre. Pour plus
d’informations, voir l’Aide en ligne.
Dessin de formes
Les canevas disposent de méthodes vous permettant de dessiner différents types
de formes. Le canevas dessine le pourtour d’une forme avec son crayon, puis
remplit l’intérieur avec son pinceau. La ligne qui définit la bordure de la forme
est déterminée par l’objet Pen en cours.
Cette section couvre :
• Dessin de rectangle et d’ellipses
• Dessin de rectangles à coins arrondis
• Dessin de polygones
Dessin de polygones
Pour dessiner, sur un canevas, un polygone ayant un nombre quelconque de côtés,
appelez la méthode Polygon du canevas.
Polygon prend un tableau de points comme seul paramètre et relie les points avec le
crayon, puis relie le dernier point au premier de façon à fermer le polygone. Après
avoir dessiné les lignes, Polygon utilise le pinceau pour remplir la zone interne au
polygone.
Le code suivant dessine un triangle rectangle dans la moitié inférieure gauche de la
fiche :
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Polygon([Point(0, 0), Point(0, ClientHeight),
Point(ClientWidth, ClientHeight)]);
end;
Dans le code suivant, un champ ajouté à une fiche fera le suivi de l’outil de
dessin de la fiche :
type
TDrawingTool = (dtLine, dtRectangle, dtEllipse, dtRoundRect);
TForm1 = class(TForm)
...{ déclarations de méthode}
public
Drawing: Boolean;
Origin, MovePt: TPoint;
DrawingTool: TDrawingTool;{ champ pour l’outil en cours }
end;
dtRoundRect: begin
Canvas.RoundRect(Origin.X, Origin.Y, X, Y,
(Origin.X - X) div 2, (Origin.Y - Y) div 2);
Canvas.RoundRect(Origin.X, Origin.Y, X, Y,
(Origin.X - X) div 2, (Origin.Y - Y) div 2);
end;
end;
MovePt := Point(X, Y);
end;
Canvas.Pen.Mode := pmCopy;
end;
En principe, tout le code répétitif de l’exemple précédent devrait être dans une
routine séparée. La section suivante présente le code relatif au dessin des formes
dans une seule routine pouvant être appelée par tous les gestionnaires
d’événements de souris.
begin
with Canvas do
begin
Pen.Mode := AMode;
case DrawingTool of
dtLine:
begin
MoveTo(TopLeft.X, TopLeft.Y);
LineTo(BottomRight.X, BottomRight.Y);
end;
dtRectangle: Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y);
dtEllipse: Ellipse(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y);
dtRoundRect: RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y,
(TopLeft.X - BottomRight.X) div 2, (TopLeft.Y - BottomRight.Y) div 2);
end;
end;
end;
Les autres gestionnaires d'événements sont modifiés pour appeler DrawShape.
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DrawShape(Origin, Point(X, Y), pmCopy);{ dessine la forme finale }
Drawing := False;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
DrawShape(Origin, MovePt, pmNotXor);{ efface la forme précédente }
MovePt := Point(X, Y);{ record the current point }
DrawShape(Origin, MovePt, pmNotXor);{ dessine la forme en cours }
end;
end;
Remarque Etant donné que vous dessinez sur une image hors écran, comme un canevas
Tbitmap, l’image n’apparaît pas tant qu’un contrôle effectue la copie d’un bitmap
sur le canevas du contrôle. En d’autres mots, lorsque vous dessinez des bitmaps
et les affectez à un contrôle image, l’image n’apparaît que si le contrôle a la
possibilité de traiter son message. En revanche, si vous dessinez directement sur
la propriété Canvas d’un contrôle, l’objet image apparaît immédiatement.
Positionnement du contrôle
Un contrôle image peut être placé n'importe où dans une fiche. Pour tirer le
meilleur parti de la capacité d’un contrôle image à ajuster sa taille sur celle de son
image, le seul point à définir est le coin supérieur gauche du contrôle. Si le contrôle
image sert d'emplacement non visible pour un bitmap, il peut être placé n'importe
où dans la fiche, comme un composant non visuel.
Si vous placez le contrôle image en le mettant à l’intérieur de la boîte de défilement
déjà installée dans la zone client de la fiche, vous serez sûr que la boîte de défilement
affichera des barres de défilement pour permettre l’accès aux parties du dessin
n’apparaissant pas à l’écran. Définissez ensuite les propriétés du contrôle image.
Dans cet exemple, l’image est dans Form1, la fiche principale de l’application. Le
code attache donc un gestionnaire à l’événement OnCreate de Form1 :
procedure TForm1.FormCreate(Sender: TObject);
var
Bitmap: TBitmap;{ variable temporaire pour contenir le bitmap }
begin
Bitmap := TBitmap.Create;{ construire l’objet bitmap }
Bitmap.Width := 200;{ affecter la largeur initiale... }
Bitmap.Height := 200;{ ...et la hauteur initiale }
Image.Picture.Graphic := Bitmap;{ affecter le bitmap au contrôle image }
end;
L'affectation du bitmap à la propriété Graphic de l’image affecte le bitmap à l'objet
Picture. Celui-ci se chargera donc de détruire le bitmap lorsqu'il ne sera plus utile :
il n'est donc pas nécessaire de détruire manuellement l'objet bitmap. Il est possible
d'affecter un bitmap différent à l’objet Picture (voir la section “Remplacement de
l’image” à la page 7-21). A ce stade, l’image libère l'ancien bitmap et devient
propriétaire du nouveau.
Si vous exécutez l’application maintenant, la zone client de la fiche apparaît
comme une zone blanche représentant le bitmap. Si vous redimensionnez la
fenêtre de sorte que la zone client ne puisse afficher toute l’image, la boîte de
défilement affiche automatiquement des barres de défilement pour permettre la
visualisation du reste de l’image. Mais si vous essayez de dessiner dans l’image,
rien n’apparaît : l’application dessine toujours dans la fiche qui est derrière
l’image et la boîte de défilement.
begin
BitMap := TBitMap.create;
try
BitMap.LoadFromFile('C:\Program Files\Borland\Delphi 4\Images\Splash\256color\
factory.bmp');
for y := 0 to BitMap.height -1 do
begin
P := BitMap.ScanLine[y];
for x := 0 to BitMap.width -1 do
P[x] := y;
end;
canvas.draw(0,0,BitMap);
finally
BitMap.free;
end;
end;
Remplacement de l’image
Il est possible à tout moment de remplacer l’image d’un contrôle image. Si un
nouveau graphique est affecté à l’image ayant déjà un graphique, le nouveau
graphique remplace l’ancien.
WidthEdit
HeightEdit
Cette boîte de dialogue particulière est créée dans l’unité BMPDlg incluse dans le
projet GraphEx (répertoire EXAMPLES\DOC\GRAPHEX).
Cette boîte de dialogue étant dans votre projet, ajoutez-la à la clause uses de
l’unité de votre fiche principale. Vous pouvez ensuite attacher un gestionnaire à
l’événement OnClick de l’élément de menu Fichier | Nouveau. Voici un exemple :
procedure TForm1.New1Click(Sender: TObject);
var
Bitmap: TBitmap;{ variable temporaire pour le nouveau bitmap }
begin
with NewBMPForm do
begin
ActiveControl := WidthEdit;{ focalisation sur le champ largeur }
WidthEdit.Text := IntToStr(Image.Picture.Graphic.Width);{ dimensions en cours... }
HeightEdit.Text := IntToStr(Image.Picture.Graphic.Height);{ ...par défaut }
if ShowModal <> idCancel then{ continuer si l’utilisateur n’annule pas la boîte de
dialogue }
begin
Bitmap := TBitmap.Create;{ créer un objet bitmap }
Bitmap.Width := StrToInt(WidthEdit.Text);{ utiliser la largeur spécifiée }
Bitmap.Height := StrToInt(HeightEdit.Text);{ utiliser la hauteur spécifiée }
Image.Picture.Graphic := Bitmap;{ remplacer le graphique par le nouveau bitmap }
CurrentFile := '';{ indique le fichier non nommé }
end;
end;
end;
Remarque L’affectation d’un nouveau bitmap à la propriété Graphic de l’objet Picture oblige
l’objet Picture à détruire le bitmap existant et à devenir propriétaire du nouveau.
Delphi gère automatiquement les détails de la libération des ressources associées à
l’ancien bitmap.
Répondre à la souris
Votre application peut répondre aux actions de la souris : enfoncement du
bouton de la souris, déplacement de la souris et relâchement du bouton de la
souris. Elle peut aussi répondre à un clic (un appui suivi d’un relâchement, sans
déplacer la souris) qui peut être généré par certaines frappes de touches (comme
l’appui sur la touche Entrée dans une boîte de dialogue modale).
Cette section traite des sujets suivants :
• Qu’y a-t’il dans un événement de souris ?
• Réponse à l’action bouton de souris enfoncé
• Réponse à l’action bouton de souris relâché
• Réponse au déplacement de la souris
Vous devez définir MovePt par le point d’arrivée de chaque ligne intermédiaire, et
utiliser MovePt et Origin pour effacer cette ligne avant de dessiner la suivante :
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
Canvas.MoveTo(X, Y);
Origin := Point(X, Y);
MovePt := Point(X, Y);
end;
procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.Pen.Mode := pmNotXor;{ utiliser le mode XOR pour dessiner/effacer }
Canvas.MoveTo(Origin.X, Origin.Y);{ déplacer le crayon à l’origine }
Canvas.LineTo(MovePt.X, MovePt.Y);{ effacer l’ancienne ligne }
Canvas.MoveTo(Origin.X, Origin.Y);{ commencer de nouveau à l’origine }
Canvas.LineTo(X, Y);{ dessiner la nouvelle ligne }
end;
MovePt := Point(X, Y);{ enregistrer le point pour le prochain déplacement }
Canvas.Pen.Mode := pmCopy;
end;
Maintenant, un effet satisfaisant est obtenu lorsque la ligne est dessinée. En
modifiant le mode du crayon en pmNotXor, il combine la ligne avec les pixels de
l’arrière-plan. Lorsque la ligne est effacée, les pixels sont en fait ramenés à leur état
antérieur. En remettant le mode du crayon à pmCopy (sa valeur par défaut) après
avoir dessiné les lignes, le crayon est prêt pour le dessin final lorsque le bouton de
la souris est relâché.
Utilisation du multimédia
Chapter 8
8
Delphi 4 vous permet d’ajouter des composants multimédia à vos applications.
Vous pouvez le faire en ajoutant le composant TAnimate de la page Win32 ou le
composant TMediaplayer de la page Système de la palette des composants.
Utilisez le composant animation pour jouer des séquences vidéo silencieuses
dans votre application. Utilisez le composant lecteur multimédia pour jouer des
séquences audio ou vidéo dans une application.
Pour davantage d’informations sur les composants TAnimate et TMediaplayer, voir
l’aide en ligne de la VCL.
Cette section aborde les sujets suivants :
• Ajout à une application de séquences vidéo silencieuses
• Ajout à une application de séquences audio et/ou vidéo
Initialisation du thread
Si vous souhaitez écrire du code d'initialisation pour la nouvelle classe de thread,
vous devez écraser la méthode Create. Ajoutez un nouveau constructeur à la
déclaration de la classe de thread et écrivez le code d'initialisation pour
l'implémenter. C’est là que vous pouvez affecter une priorité par défaut au
thread et indiquer s’il doit être libéré automatiquement à la fin de son exécution.
Remarque Comme Synchronize utilise la boucle des messages, elle ne fonctionne pas dans
les applications consoles. Vous devez utiliser d'autres mécanismes, comme les
sections critiques, pour protéger l'accès aux objets VCL dans les applications
consoles.
Il n’est pas toujours nécessaire d’utiliser le thread principal VCL. Certains objets
sont adaptés aux threads. Il est préférable de ne pas utiliser la méthode
Synchronize quand vous savez que les méthodes d’un objet sont adaptées à
l’utilisation des threads, car cela améliore les performances en évitant d’avoir à
attendre le thread principal VCL pour entrer dans la boucle de messages. Il n’est
pas nécessaire d’utiliser la méthode Synchronize dans les situations suivantes :
• Les composants d’accès aux données sont adaptés aux threads dans la mesure
où chaque thread dispose de son propre composant session de base de données.
Il n’y a qu’une seule exception : les pilotes Access. Ces pilotes sont conçus en
utilisant la bibliothèque ADO Microsoft qui n’est pas adaptée aux threads.
Lorsque vous utilisez des composants d’accès aux données, vous devez
néanmoins encadrer tous les appels aux contrôles orientés données dans la
méthode Synchronize. Ainsi, il est nécessaire de synchroniser les appels qui
relient un contrôle orienté données à un ensemble de données, mais il n’est
pas nécessaire de le faire pour accéder aux données d’un champ de l’ensemble
de données.
Pour davantage d’informations sur l’utilisation de sessions de base de données
avec les threads, voir “Gestion de plusieurs sessions” à la page 16-18.
• Les objets graphiques sont adaptés aux threads. Il n’est pas nécessaire
d’utiliser le thread principal VCL pour accéder aux objets TFont, TPen, TBrush,
TBitmap, TMetafile et TIcon. Il est possible d’accéder aux objets canevas en
dehors de la méthode Synchronize en les verrouillant (voir “Verrouillage
d’objets” à la page 9-7).
• Les listes d’objets ne sont pas adaptées aux threads, mais vous pouvez utiliser
une version adaptée aux threads, TThreadList, à la place de TList.
La section threadvar ne peut être utilisée que pour des variables globales. Les
variables Pointer et Function ne peuvent pas être des variables de thread. Les
types utilisant une sémantique de copie lors de l’écriture, comme les chaînes
longues, ne peuvent pas non plus faire office de variables de thread.
Coordination de threads
Quand vous écrivez le code exécuté lorsque le thread s’exécute, vous devez tenir
compte du comportement des autres threads qui peuvent s’exécuter
simultanément. En particulier, il faut éviter que deux threads tentent d’utiliser
simultanément le même objet ou la même variable globale. De plus, le code d’un
thread peut dépendre de tâches effectuées par d’autres threads.
Verrouillage d’objets
Certains objets disposent d’un verrouillage intégré qui empêche les autres
threads d’utiliser cette instance d’objet.
Ainsi, les objets canevas (TCanvas et ses descendants) ont une méthode Lock qui
empêche les autres threads d’accéder au canevas jusqu’à l’appel de la méthode
Unlock.
La VCL contient également un objet liste adapté aux threads, TThreadList. L’appel
deTThreadList.LockList renvoie l’objet liste tout en empêchant les autres threads
d’exécution d’utiliser la liste jusqu’à l’appel de la méthode UnlockList. Les appels
des méthodes TCanvas.Lock et TThreadList.LockList peuvent être imbriqués. Le
verrou n’est pas libéré tant que le dernier verrouillage n’est pas associé au
déverrouillage correspondant dans le même thread.
Attention Les sections critiques ne peuvent fonctionner que si tous les threads les utilisent
pour accéder à la mémoire globale associée. Les threads qui ne tiennent pas
compte des sections critiques et accèdent à la mémoire globale sans appeler
Acquire peuvent provoquer des problèmes d’accès simultanés.
Par exemple, une application a une section critique des variables globales,
LockXY, qui bloque l’accès aux variables globales X et Y. Tout thread utilisant X
ou Y doit encadrer cette utilisation d’appels à la section critique comme ci-
dessous :
LockXY.Acquire; { verrouille les autres threads }
try
Y := sin(X);
finally
LockXY.Release;
end;
Le code suivant montre comment le thread principal lance les threads de tâche et
reprend la main lorsque leur exécution est achevée :
Event1.ResetEvent; { efface l’événement avant de lancer les threads }
for i := 1 to Counter do
TaskThread.Create(False); { crée et lance les threads de tâche }
if Event1.WaitFor(20000) != wrSignaled then
raise Exception;
{ poursuite avec le thread principal. L’exécution de tous les threads de tâche est achevée
}
Remarque Si vous ne voulez pas cesser d’attendre un événement après un délai spécifié,
transmettez à la méthode WaitFor une valeur de paramètre INFINITE. Faites
attention en utilisant INFINITE, car cela peut provoquer le blocage du thread si
le signal attendu n’arrive pas.
Ecriture de bibliothèques
Lorsqu’une bibliothèque active implémente l'objet distribué, l'utilisation des
threads est généralement contrôlée par la technologie (COM, DCOM ou MTS) qui
gère les appels d'objet. Lorsque vous créez votre bibliothèque serveur avec
l'expert approprié, vous êtes invité à spécifier un modèle de thread qui détermine
l'attribution des threads aux requêtes client. Ces modèles sont les suivants :
• Modèle à thread unique. Les requêtes client sont sérialisées par le mécanisme
d'appel. Votre fichier .DLL n'est pas concerné par la gestion du thread car il
reçoit une seule requête client à un moment donné.
• Modèle multiple à thread unique. (Aussi appelé modèle multiple.) Chaque
objet instancié par un client n'est accessible que par un thread à un moment
donné. Vous devez empêcher l'accès à la mémoire globale par plusieurs
threads, mais les données d'instance (comme les propriétés d'objet) sont
adaptées aux threads. De plus, chaque client accède toujours à l'instance d'objet
à l'aide du même thread, ce qui vous permet d'utiliser des variables de thread.
• Modèle activité. Chaque instance d'objet n'est accessible que par un thread à
un moment donné mais les clients n'utilisent pas toujours le même thread
pour chaque appel. Les données d'instance sont adaptées aux threads, mais
vous devez protéger la mémoire globale, et les variables globales ne sont pas
cohérentes d'un appel client à l'autre.
• Modèle multiple. Chaque instance d'objet peut être appelée par plusieurs
threads simultanément. Vous devez protéger les données d'instance ainsi que
la mémoire globale. Les variables de thread ne sont pas cohérentes d'un appel
client à l'autre.
• Modèle à thread unique ou multiple. Il s'agit du même modèle que du
modèle multiple à la différence que les rappels émanant des clients s'exécutent
dans le même thread. Ainsi, vous n'avez pas besoin de protéger les valeurs
fournies comme paramètres de fonctions de rappel (callback).
Les systèmes basés sur COM utilisent la boucle des messages de l'application
pour synchroniser les threads dans tous les modèles (excepté le modèle multiple,
uniquement disponible sous DCOM). Vous devez donc vous assurer que tout
appel long opéré par le biais d'une interface COM sollicite la méthode
ProcessMessages de l'objet d'application. A défaut, les autres clients ne peuvent
pas accéder à votre application et font de votre bibliothèque une bibliothèque à
thread unique.
Remarque Les paquets partagent leurs données globales avec les autres modules d’une
application.
Pour davantage d’informations sur les DLL et les paquets, voir le chapitre 9,
“ibliothèques de liaison dynamique et paquets” du Guide du langage Pascal
Objet.
Paquets d’exécution
Les paquets d'exécution sont déployés avec les applications Delphi. Ils
fournissent des fonctionnalités lorsqu'un utilisateur exécute une application.
Pour exécuter une application utilisant des paquets, le fichier .EXE de
l’application et tous les fichiers paquet (fichiers .BPL) qu’elle utilise doivent se
trouver sur l'ordinateur. Les fichiers .BPL doivent être dans le chemin du
système pour qu’une application puisse les utiliser. Quand vous déployez une
application, vérifiez que les utilisateurs possèdent la version correcte de chaque
BPL nécessaire.
Remarque Lorsque vous créez une application avec des paquets, vous devez inclure les
noms originels des unités Delphi dans la clause uses des fichiers source. Par
exemple, le fichier source de la fiche principale pourrait commencer ainsi :
unit MainForm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
Chacune des unités référencée dans cet exemple est contenu dans le paquet
VCL40. Néamoins, vous devez conserver ces références dans la clause uses,
même si vous utilisez VCL40 dans votre application, ou vous aurez des erreurs
de compilation. Dans les fichiers source générés, Delphi ajoute automatiquement
ces unités à la clause uses.
Ainsi, pour créer une application de base de données client/serveur utilisant des
paquets, vous avez besoin d'au moins deux paquets d'exécution : VCL40 et
VCLDB40. Si vous voulez également utiliser dans votre application des
composants arborescence, vous avez besoin en plus de VCLX40. Pour utiliser ces
paquets, choisissez Projet|Options, sélectionnez la page Paquets et entrez la liste
suivante dans la boîte de saisie Paquets d'exécution.
VCL40;VCLDB40;VCLX40
Il n’est, en fait, pas nécessaire de préciser VCL40, car VCL40 est référencée dans
la clause Requires de VCLDB40. (Voir “La clause Requires” à la page 10-10.)
Votre application se compilera de la même façon que VCL40 figure ou non dans
la liste.
Paquets personnalisés
Un paquet personnalisé est soit une BPL que vous programmez et compilez
vous-même, soit un paquet précompilé développé par un fournisseur tiers. Pour
utiliser dans une application un paquet d'exécution personnalisé, choisissez
Projet|Options et ajoutez le nom du paquet à la boîte de saisie Paquets
d'exécution de la page Paquets. Par exemple, si vous avez créé un paquet
effectuant des statistiques, nommé STATS.BPL, la boîte de saisie Paquets
d'exécution doit avoir la forme :
VCL40;VCLDB40;STATS
Si vous créez vos propres paquets, vous pouvez les ajouter selon vos besoin à la
liste.
Paquets de conception
Des paquets de conception sont utilisés pour installer des composants dans la
palette des composants de l’IDE ou pour créer les éditeurs de propriétés
spéciaux de composants personnalisés.
Delphi est livré avec les paquets composant de conception suivants, déjà installés
dans l'EDI.
La clause Requires
La clause requires spécifie les autres paquets, externes, utilisés par le paquet en
cours. Un paquet externe inclus dans la clause requires est automatiquement lié
lors de la compilation dans toute application utilisant le paquet en cours ou
l’une des unités contenues dans le paquet externe.
Si les fichiers unité contenus dans votre paquet font référence à d’autres unités
empaquetées, les autres paquets doivent apparaître dans la clause requires de
votre paquet, sinon vous devrez les ajouter. Si les autres paquets sont omis de la
clause requires, le compilateur les importera dans votre paquet comme ‘unités
contenues implicitement’.
Remarque La plupart des paquets nécessitent VCL40. Tout paquet dépendant des unités
VCL (y compris SysUtils) doit lister VCL40 ou un autre paquet nécessitant
VCL40 dans sa clause requires.
La clause Contains
La clause contains identifie les fichiers unité à lier dans le paquet. Si vous
écrivez votre propre paquet, placez votre code source dans des fichiers PAS et
incluez-les dans la clause contains.
Compilation de paquets
Vous pouvez compiler un paquet dans l’EDI ou depuis la ligne de commande.
Pour recompiler un paquet directement dans l’EDI :
1 Choisissez Fichier|Ouvrir.
2 Sélectionnez le fichier source du paquet Delphi (*.DPK) à partir de la liste
déroulante Fichiers de type.
3 Sélectionnez un fichier .DPK dans la boîte de dialogue.
4 Lorsque l’éditeur de paquet est ouvert, cliquez sur le turbobouton Compiler.
Vous pouvez insérer des directives de compilation dans le code source du
paquet. Pour davantage d’informations, voir “Directives de compilation propres
aux paquets”, ci-dessous.
Si vous compilez à partir de la ligne de commande, de nouvelles options
d’édition de lien spécifiques aux paquets sont utilisables. Pour davantage
d’informations, voir “Utilisation du compilateur et du lieur en ligne de
commande” à la page 10-13.
Remarque Utilisez {$DENYPACKAGEUNIT ON} dans votre code pour que l’unité ne soit
pas mise dans un paquet. L’utilisation de {$G-} ou {IMPORTEDDATA OFF}
permet à un paquet de ne pas être utilisé dans la même application avec
d’autres paquets. Les paquets compilés avec la directive {$DESIGNONLY ON}
ne devrait pas être utilisés dans les applications puisque qu’ils contiennent du
code nécessaire à l’EDI. D’autres directives de compilation peuvent être utilisées
dans le code source de paquet. Voir Directives de compilation dans l’aide en
ligne pour les directives de compilation qui n’ont pas été abordées ici.
Paquets faibles
La directive $WEAKPACKAGEUNIT affecte la manière dont un fichier .DCU est
stocké dans les fichiers .DCP et .BPL d’un paquet. Pour des informations sur les
fichiers générés par le compilateur, voir “Fichiers paquets créés lors d’une
compilation réussie” à la page 10-13. Si {$WEAKPACKAGEUNIT ON} apparaît
dans un fichier unité, le compilateur omet l’unité des BPL si c’est possible, et
crée une version locale non empaquetée de l’unité quand elle est nécessaire à
une autre application ou un autre paquet. Une unité compilée avec cette
directive est dite “faiblement empaquetée”.
Si, par exemple, vous créez un paquet appelé PACK ne contenant que l’unité
UNIT1. Supposez que UNIT1 n’utilise aucune autre unité, mais fait des appels à
RARE.DLL. Si vous placez la directive {$WEAKPACKAGEUNIT ON} dans
UNIT1.PAS, lors de la compilation du paquet, UNIT1 n’est pas incluse dans
PACK.BPL ; vous n’avez donc pas à distribuer de copie de RARE.DLL avec
PACK. Néanmoins, UNIT1 sera toujours incluse dans PACK.DCP. Si UNIT1 est
référencée dans un autre paquet ou une autre application utilisant PACK, elle
sera copiée dans PACK.DCP et directement compilée dans le projet.
Supposons maintenant que vous ajoutiez à PACK une deuxième unité, UNIT2
qui utilise UNIT1. Cette fois, même si vous compilez PACK avec la directive
{$WEAKPACKAGEUNIT ON} dans UNIT1.PAS, le compilateur inclut UNIT1
dans PACK.BPL. Par contre les autres paquets ou applications faisant référence à
UNIT1 utiliseront la copie (non empaquetée) prise dans PACK.DCP.
Remarque Les fichiers unité contenant la directive {$WEAKPACKAGEUNIT ON} ne
doivent pas contenir de variables globales, de section d’initialisation ou de
sections de finalisation.
Remarque L’utilisation de l’option -$G- empêche un paquet d’être utilisé dans une même
application avec d’autres paquets. Les autres options en ligne de commande
peuvent être utilisées de manière appropriée lors de la compilation des paquets.
Voir “Le compilateur en ligne de commande” dans l’aide en ligne pour les
options en ligne de commande qui n’ont pas été abordées ici.
Le tableau suivant donne la liste des fichiers générés par une compilation réussie
d’un paquet.
Déploiement de paquets
Déploiement d’applications utilisant des paquets
Pour distribuer une application utilisant des paquets d’exécution, vérifiez que
l’utilisateur dispose du fichier .EXE de l’application, ainsi que de toutes les
bibliothèques (.BPL ou .DLL) appelées par l’application. Si les fichiers
bibliothèque sont dans un répertoire différent de celui du fichier .EXE, ils
doivent être accessibles via les chemins d’accès de l’utilisateur. Vous pouvez
suivre la convention consistant à placer les fichiers des bibliothèques dans le
répertoire Windows\System. Si vous utilisez InstallShield Express, le script
d’installation peut vérifier la présence des paquets nécessaires sur le système de
l’utilisateur avant de les réinstaller aveuglément.
5 Vous pouvez sélectionner des répertoires d’installation pour les paquets dont
la liste se trouve dans la clause requires de n’importe quel paquet de votre
collection. Lorsque vous sélectionnez un BPL dans le diagramme arborescence,
quatre nouveaux champs apparaissent sur la partie droite de l’éditeur de
collection de paquets.
• Dans la boîte liste Fichiers exécutables requis, sélectionnez le répertoire
dans lequel vous voulez installer les fichiers .BPL pour les paquets dont la
liste se trouve dans la clause requires. La liste déroulante comprend les
répertoires saisis dans Nom de répertoire à l’étape 3 ci-dessus. L’éditeur de
collection de paquets recherche ces fichiers en utilisant le chemin de la
bibliothèque Delphi et donne la liste sous Fichiers exécutables requis.
• Dans la boîte liste Répertoire des bibliothèques requises, sélectionnez le
répertoire d’installation des fichiers .DCP pour les paquets de la clause
requires. La liste déroulante comprend les répertoires spécifiés sous Nom
répertoire à l’étape 3, ci-dessus. L’éditeur de collection de paquets recherche
ces fichiers en utilisant le chemin de bibliothèque global de Delphi, et les
affiche sous Fichiers bibliothèque requis.
6 Pour enregistrer votre fichier source de collection de paquets, choisissez
Fichier|Enregistrer. Les fichiers source de collection de paquets doivent être
enregistrés avec l’extension .PCE.
7 Pour construire votre collection de paquets, cliquez sur le turbobouton
Compiler. L’éditeur de collection de paquets génère un fichier .DPC avec le
nom de votre fichier source (.PCE). Si vous n’avez pas encore enregistré le
fichier source, l’éditeur vous demande un nom de fichier avant la compilation.
Pour éditer ou recompiler un fichier .PCE existant, sélectionnez Fichier|Ouvrir
dans l’éditeur de collection de paquets.
Internationalisation et localisation
Pour créer une application distribuable sur les marchés étrangers, vous devez
accomplir deux étapes :
• Internationalisation
• Localisation
Internationalisation
L’internationalisation est le processus permettant à votre application de
fonctionner selon divers paramètres régionaux. Les paramètres régionaux sont
l’environnement de l’utilisateur qui inclut les conventions culturelles du pays
cible aussi bien que sa langue. Windows gère un grand nombre de paramètres
régionaux, chacun d’eux décrits par l’association d’une langue et d’un pays.
Localisation
La localisation est le processus de traduction d’une application pour qu’elle
fonctionne pour des paramètres régionaux spécifiques. Outre la traduction de
l’interface utilisateur, la localisation peut également consister à personnaliser les
fonctionnalités. Par exemple, une application financière peut être modifiée afin
de respecter les règles fiscales dans différents pays.
Codage de l’application
Vous vous assurerez que le code de l’application peut gérer les chaînes qu’elle
rencontrera dans les divers environnements régionaux cible.
Jeux de caractères
Les versions de Windows 95 et Windows NT diffusées aux USA utilisent le jeu
de caractères ANSI Latin-1 (1252). Mais d’autres éditions de Windows utilisent
des jeux de caractères différents. Ainsi, la version japonaise de Windows utilise
le jeu de caractères Shift-Jis (page de code 932) qui représente les caractères
japonais avec des codes sur un ou deux octets.
Lors de l’écriture de code destiné aux pays asiatiques, vous devez traiter toutes
les manipulations de chaînes avec des fonctions capables de décomposer les
chaînes en caractères de un ou deux octets. Delphi fournit un certain nombre de
fonctions de la bibliothèque d’exécution pour effectuer cela. Ces fonctions sont
les suivantes :
Caractères larges
Une autre approche des idéogrammes est de convertir tous les caractères dans
un système de caractères larges, comme Unicode. Les caractères larges utilisent
deux octets au lieu d’un, si bien qu’un jeu de ces caractères peut contenir un
nombre beaucoup plus grand d’éléments.
En outre, les caractères larges présentent un avantage sur les caractères MBCS :
ils vous permettent de conserver vos habitudes car il existe une relation directe
entre le nombre d’octets d’une chaîne et son nombre de caractères. Et, vous ne
risquez plus de couper un caractère en deux, ni de confondre la seconde moitié
d’un caractère avec la première d’un autre.
L’inconvénient majeur des caractères larges est que Windows 95 n’en reconnaît
qu’un petit nombre dans les appels aux fonctions API. C’est pourquoi, les
composants VCL représentent toutes les valeurs chaînes par des chaînes à
caractères d’un seul octet ou par des chaînes MBCS. Vous devrez passer du
système caractères larges au système MBCS à chaque fois que définir la propriété
Propriétés bi-directionnelles
Les objets dont la liste est donnée dans le tableau 11.1, “Objets de la VCL
supportant les BiDi,” à la page 11-4 ont deux nouvelles propriétés : BiDiMode et
ParentBiDiMode.
Propriété BiDiMode
La propriété BiDiMode est un nouveau type d’énuméré, TBiDiMode, qui possède
quatre états: bdLeftToRight, bdRightToLeft, bdRightToLeftNoAlign, et
bdRightToLeftReadingOnly.
bdLeftToRight
bdLeftToRight dessine le texte en utilisant le sens de lecture de gauche à droite,
l’alignement et la barre de défilement étant inchangés. Par exemple, lors de la
saisie de texte de droite à gauche, comme pour l’Arabe ou l’Hébreux, le curseur
passe en mode poussoir et le texte est saisi de droite à gauche. Pour du texte
latin, comme l’Anglais ou le Français, il est saisi de gauche à droite.
bdLeftToRight est la valeur par défaut.
Figure 11.1 Contrôles initialisés à bdLeftToRight
bdRightToLeft
bdRightToLeft dessine le texte en utilisant le sens de lecture de droite à gauche,
l’alignement étant modifié et la barre de défilement déplacée. Le texte est saisi
normalement pour les langues allant de droite à gauche comme l’Arabe ou
l’Hébreux. Lorsque le clavier est modifié pour une langue latine, le curseur passe
en mode poussoir et le texte est saisi de gauche à droite.
Figure 11.2 Contrôles initialisés à bdRightToLeft
bdRightToLeftNoAlign
bdRightToLeftNoAlign dessine le texte en utilisant le sens de lecture de droite à
gauche, l’alignement étant inchangé et la barre de défilement déplacée.
Figure 11.3 Contrôles initialisés à bdRightToLeftNoAlign
bdRightToLeftReadingOnly
bdRightToLeftReadingOnly dessine le texte en utilisant le sens de lecture de droite
à gauche, l’alignement et la barre de défilement étant inchangés.
Figure 11.4 Contrôles initialisés à bdRightToLeftReadingOnly
Propriété ParentBiDiMode
ParentBiDiMode est une propriété booléenne. Lorsqu’elle est à True (la valeur par
défaut), le contrôle regarde la propriété de son parent pour connaître la valeur à
utiliser pour BiDiMode. Si le contrôle est un objet TForm, la fiche utilise la valeur
BiDiMode de Application. Si toutes les propriétés ParentBiDiMode sont à True,
lorsque la propriété BiDiMode de Application est modifiée, toutes les fiches et tous
les contôles du projet sont initialisés avec la nouvelle valeur.
Méthode FlipChildren
La méthode FlipChildren vous permet de faire basculer la position des enfants
d’un contrôle conteneur. Les contrôles conteneur sont des contrôles qui
contiennent d’autres contrôles, comme TForm, TPanel et TGroupbox. FlipChildren
possède un seul paramètre booléen, AllLevels. Lorsqu’il est à False, seuls les
enfants directs du contrôle conteneur sont basculés de position. Lorsqu’il est à
True, tous les enfants du contrôle conteneur sont basculés de position.
Delphi fait basculer la position des contrôles en modifiant la propriété Left et
l’alignement du contrôle. Si le côté gauche d’un contrôle est à cinq pixels de la
limite gauche de son parent, le basculement provoque l’affichage du côté droit
du contrôle de saisie à cinq pixels de la limite droite de son parent. Si le contrôle
de saisie est aligné à gauche, un appel à FlipChildren provoquera un alignement à
droite.
Pour basculer la position d’un contrôle lors de la conception, il faut sélectionner
Edition|Basculer l’enfant et sélectionner Tous ou Sélectionnés suivant que vous
voulez basculer la position de tous les contrôles ou seulement les enfants du
contrôle sélectionné. Il est aussi possible de basculer la position d’un contrôle en
sélectionnant le contrôle sur la fiche, en cliquant sur le bouton droit de la souris
pour sélectionner le choix Basculer l’enfant dans le menu contextuel.
Remarque La sélection d’un contrôle de saisie suivi de la commande Basculer l’enfant|
Sélectionnés ne fait rien. Cela est du au fait que les contrôles de saisie ne sont
pas des conteneurs.
Autres méthodes
Il existe d’autres méthodes utiles afin de développer des applications pour des
utilisateurs bi-directionnels.
Méthode Description
OkToChangeFieldAlignment Utilisée avec les contrôles base de données. Vérifie si
l’alignement d’un contrôle peut être modifié.
DBUseRightToLeftAlignment Utilisée pour vérifier l’alignement des contrôles base
de données.
ChangeBiDiModeAlignment Modifie le paramètre d’alignement qui lui est
transmis. Aucune vérification n’est faite pour
l’initialisation de BiDiMode, car il y a juste
conversion de l’alignement à gauche vers
l’alignement à droite et vice-versa, en laissant centré
les contrôles seuls.
IsRightToLeft Renvoie True si une des options allant de droite à
gauche est sélectionnée. Renvoie False si le contrôle
est dans un mode allant de gauche à droite.
UseRightToLeftReading Renvoie True si le contrôle utilise le sens de lecture
allant de droite à gauche.
UseRightToLeftAlignment Renvoie True si le contrôle utilise le sens
d’alignement allant de droite à gauche. Il peut être
surchagé pour être personnalisé.
Méthode Description
UseRightToLeftScrollBar Renvoie True si le contrôle utilise une barre de
défilement à gauche.
DrawTextBiDiModeFlags Renvoie les bons paramètres pour le mode BiDi du
contrôle.
DrawTextBiDiModeFlagsReadingOnly Renvoie les bons paramètres pour le mode BiDi du
contrôle, en les limitant à la lecture.
AddBiDiModeExStyle Ajoute le paramètre ExStyle flags approprié au
contrôle créé.
Texte
Tout le texte apparaissant dans l’interface utilisateur doit être traduit. Le texte
anglais étant presque toujours plus court que les traductions, vous devez
concevoir les éléments de votre interface utilisateur qui affiche du texte en
réservant de l’espace pour l’expansion de ce texte. Concevez également les boîtes
de dialogue, les menus, les barres d’état et les autres éléments de l’interface
utilisateur affichant du texte de telle sorte qu’ils puissent facilement afficher des
chaînes plus longues. Evitez les abréviations qui ne peuvent exister dans les
langues utilisant des idéogrammes.
Les chaînes courtes grandissent plus que les phrases longues. Le tableau suivant
fournit une approximation des taux de foisonnement selon la longueur de la
chaîne initiale (en anglais):
Tableau 11.2 Estimation des longueurs de chaîne
Longueur de la chaîne anglaise (en caractères) Augmentation prévisible
1-5 100%
6-12 80%
13-20 60%
21-30 40%
31-50 20%
over 50 10%
Images graphiques
Le mieux est d’utiliser des images qui ne nécessitent pas de traduction, c’est-à-dire
des images qui ne contiennent pas de texte. Si vous devez inclure du texte dans
vos images, il est préférable d’utiliser un objet libellé avec arrière-plan transparent
par dessus l’image, plutôt que d’inclure le texte dans l’image elle-même.
Voici quelques autres considérations à prendre en compte lors de la création des
images graphiques. Essayez d’éviter les images spécifiques à une culture. Par
exemple, les boîtes à lettres sont très différentes selon les pays. Les symboles
religieux ne conviennent pas aux pays où il existe plusieurs religions
dominantes. Même les couleurs ont des connotations symboliques différentes
selon les cultures.
private
{ déclarations privées}
public
{ déclarations publiques }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function GetLocaleData(ID: LCID; Flag: DWORD): string;
var
BufSize: Integer;
begin
BufSize := GetLocaleInfo(ID, Flag, nil, 0);
SetLength(Result, BufSize);
GetLocaleinfo(ID, Flag, PChar(Result), BufSize);
SetLength(Result, BufSize - 1);
end;
{ Appelé pour chaque localisation supportée }
function LocalesCallback(Name: PChar): Bool; stdcall;
var
LCID: Integer;
begin
LCID := StrToInt('$' + Copy(Name, 5, 4));
Form1.LocaleList.Items.Add(GetLocaleData(LCID, LOCALE_SLANGUAGE));
Result := Bool(1);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
EnumSystemLocales(@LocalesCallback, LCID_SUPPORTED);
end;
end.
Les applications Delphi qui accèdent à des bases de données ou qui fonctionnent
sur le Web nécessitent des étapes complémentaires d’installation en plus de
celles s’appliquant aux applications générales. Pour davantage d’informations sur
l’installation d’applications de base de données, voir “Déploiement d’applications
de base de données” à la page 12-4. Pour davantage d’informations sur
l’installation d’applications Web, voir “Déploiement d’applications Web” à la
page 12-7. Pour davantage d’informations sur l’installation de contrôles ActiveX,
voir “Déploiement d’un contrôle ActiveX sur le Web” à la page 47-18.
Fichiers paquet
Si l’application utilise des paquets d’exécution, il faut distribuer les fichiers
paquet avec l’application. InstallShield Express gère l’installation des fichiers
paquet de la même manière que les DLL, copie ces fichiers et crée les entrées
nécessaires dans les registres Windows. Borland recommande l’installation des
fichiers paquet d’exécution d’origine Borland dans le répertoire Windows\
System. Cela sert d’emplacement commun afin que plusieurs applications
puissent accéder à une seule instance de ces fichiers. Pour des paquets
personnalisés, il est recommandé de les installer dans le répertoire de
l’application. Seuls les fichiers .BPL doivent être distribués.
Si vous distribuez des paquets à d’autres développeurs, fournissez les fichiers
.BPL et .DCP.
Contrôles ActiveX
Certains composants fournis avec Delphi sont des contrôles ActiveX. Le
conteneur du composant est lié au fichier exécutable de l’application (ou à un
paquet d’exécution), mais le fichier .OCX du composant doit également être
distribué avec l’application. Ces composants sont :
• Chart FX, copyright par SoftwareFX Inc.
• VisualSpeller Control, copyright par Visual Components, Inc.
• Formula One (tableur), copyright par Visual Components, Inc.
• First Impression (VtChart), copyright par Visual Components, Inc.
• Graph Custom Control, copyright par Bits Per Second Ltd.
Les contrôles ActiveX que vous créez doivent également être enregistrés sur
l’ordinateur cible avant d’être utilisés. Les programmes d’installation comme
InstallShield Express automatisent le processus d’enregistrement. Pour enregistrer
manuellement un contrôle ActiveX, utilisez l’application exempleTRegSvr ou
l’utilitaire Microsoft REGSERV32.EXE (qui n’est pas inclus dans toutes les
versions de Windows).
Les fichiers DLL gérant un contrôle ActiveX doivent également être distribués
avec une application.
Applications complémentaires
Les applications complémentaires sont des programmes distincts en l’absence
desquels votre application Delphi fonctionnerait de manière incomplète ou ne
fonctionnerait pas du tout. Les applications complémentaires peuvent être celles
fournies avec Windows, par Borland ou des tiers. Le programme utilitaire Server
Manager de InterBase est un exemple de programme complémentaire qui permet
de gérer les utilisateurs et la sécurité des bases de données InterBase.
Si une application dépend d’un programme complémentaire, assurez-vous de le
déployer avec votre application, si c’est possible. La distribution des programmes
complémentaires peut être limitée par des accords de licence de distribution.
Consultez la documentation d’un programme complémentaire pour des
informations spécifiques.
SQL Links
SQL Links propose les pilotes permettant de connecter une application au
logiciel client d’une base de données SQL (via le moteur de bases de données
Borland). Voir DEPLOY.TXT pour les droits et restrictions spécifiques
s’appliquant à la redistribution de SQL Links. Comme pour le moteur de bases
de données Borland, SQL Links doit être déployé en utilisant InstallShield
Express (ou tout autre programme certifié).
Remarque SQL Links connecte le BDE au logiciel client et pas directement à la base de
données SQL même. Il est donc toujours nécessaire d’installer le programme
client du système de bases de données SQL utilisé. Reportez-vous à la
documentation de votre système SQL ou consultez le vendeur pour davantage
d’informations sur l’installation et la configuration du logiciel client.
Le tableau suivant présente les noms des fichiers de pilote et de configuration
utilisés par SQL Links pour se connecter aux différents systèmes de base de
données SQL. Ces fichiers sont fournis avec SQL Links et sont redistribuables en
accord avec la licence Delphi.
Tableau 12.2 Fichiers des logiciels client des bases de données SQL
Vendeur Fichiers redistribuables
Oracle 7 SQLORA32.DLL et SQL_ORA.CNF
Oracle8 SQLORA8.DLL et SQL_ORA8.CNF
Sybase Db-Lib SQLSYB32.DLL et SQL_SYB.CNF
Sybase Ct-Lib SQLSSC32.DLL et SQL_SSC.CNF
Microsoft SQL Server SQLMSS32.DLL et SQL_MSS.CNF
Informix 7 SQLINF32.DLL et SQL_INF.CNF
Informix 9 SQLINF9.DLL et SQL_INF9.CNF
DB/2 SQLDB232.DLL et SQL_DB2.CNF
InterBase SQLINT32.DLL et SQL_INT.CNF
La liste suivante indique les fichiers devant être installés sur la machine client.
Fontes
Windows dispose d’un jeu standard de fontes TrueType et vectorielles. Quand
vous concevez une application devant être déployée sur d’autres ordinateurs,
tenez compte du fait que tous les ordinateurs n’ont pas nécessairement de fontes
en-dehors du jeu Windows standard.
Les composants texte utilisés dans l’application ne doivent utiliser que des fontes
qui sont très probablement disponibles sur les ordinateurs cible.
Quand l’utilisation d’une fonte non standard est absolument nécessaire dans une
application, vous devez distribuer cette fonte avec l’application. Soit le
programme d’installation, soit l’application même doit installer la fonte sur
l’ordinateur cible. La distribution de fontes créées par des tiers peut être sujette à
des restrictions imposées par leurs créateurs.
Windows dispose d’une protection contre l’utilisation d’une fonte inexistante sur
un système. Il lui substitue une fonte existante, la plus proche possible. Bien que
cela empêche les erreurs dues à des fontes manquantes, le résultat final peut
dégrader l’aspect visuel de l’application. Il est préférable de prévoir cette
éventualité à la conception.
Pour mettre à la disposition d’une application une fonte non standard, utilisez
les fonctions AddFontResource et DeleteFontResource de l’API Windows. Déployez
les fichiers .FOT des fontes non-standard avec l’application.
Versions de Windows
Quand vous utilisez des fonctions de l’API Windows ou si vous accédez à des
zones du système d’exploitation Windows dans une application, il y a le risque
que cette fonction, cette opération ou cette zone ne soit pas disponible sur des
ordinateurs utilisant une version différente de Windows. Par exemple, les
services n’ont de sens que pour le système d’exploitation Windows NT. Si une
application doit se comporter comme un service ou doit interagir avec un
service, elle ne fonctionnera pas si l’application est installée sous Windows 95.
Pour prendre cette possibilité en compte, vous avez différentes possibilités :
• Spécifiez dans les spécifications logicielles de l’application les versions de
Windows sous lesquelles l’application peut s’exécuter. C’est alors à l’utilisateur
de n’installer et de n’utiliser l’application que dans des versions compatibles
de Windows.
• Testez la version de Windows lors de l’installation de l’application. Si une
version incompatible de Windows est détectée, arrêtez le processus
d’installation ou prévenez l’utilisateur du problème.
DEPLOY.TXT
DEPLOY.TXT aborde certains aspects légaux de la distribution de divers
composants et utilitaires et autres produits pouvant faire partie ou être associés à
une application Delphi. DEPLOY.TXT est un fichier texte installé dans le
répertoire principal de Delphi. Il aborde les sujets suivants,
• Les fichiers .EXE, .DLL et .BPL
• Les composants et les paquets de conception
• Le moteur de bases de données Borland (BDE)
• Les contrôles ActiveX
• Les images exemple
• MIDAS
• SQL Links
README.TXT
README.TXT contient des informations de dernière minute sur Delphi ; il peut
donc contenir des informations pouvant affecter les droits de redistribution des
composants, utilitaires ou autres éléments. README.TXT est un fichier d’aide
Windows installé dans le répertoire principal de Delphi.
Contrat de licence
Le contrat de licence Delphi est un document imprimé qui traite des droits et
obligations légales concernant Delphi.
II
Développement d’applications
Part II
de base de données
Les chapitres de cette section présentent les concepts et les connaissances
nécessaires à la création d’applications de base de données Delphi.
Remarque Vous avez besoin de l’édition Professionnelle, Client/Serveur ou Entreprise de
Delphi pour développer des applications de base de données. Pour implémenter
des bases de données Client/Serveur plus évoluées, vous avez besoin des
caractéristiques de Delphi disponibles dans les éditions Client/Serveur et
Entreprise.
Lorsque vous fournissez le mot de passe par programmation, vous devez veiller
à ce que la sécurité ne soit pas violée par lecture du mot de passe à partir de
l’application.
Si vous obligez les utilisateurs à fournir un mot de passe, vous devez déterminer
à quel moment ce dernier est requis. Si vous utilisez une base de données locale
mais envisagez de passer à un serveur SQL plus important, vous pouvez inviter
l’utilisateur à fournir son mot de passe avant d’accéder à la table, même si pour
le moment cela ne s’impose pas.
Si votre application requiert plusieurs mots de passe pour la connection à
plusieurs bases de données ou systèmes protégés, vous pouvez demander aux
utilisateurs de fournir un mot de passe maître unique qui permet d’accéder à
une table de mots de passe requis par ces systèmes. L’application fournit alors
les mots de passe par programmation, sans que les utilisateurs aient besoin de
fournir plusieurs mots de passe.
Dans les applications multiniveaux, vous pouvez utiliser un modèle de sécurité
différent. Vous pouvez utiliser CORBA ou MTS pour contrôler l’accès aux
niveaux intermédiaires et laisser ces derniers gérer tous les détails relatifs à
l’accès aux serveurs de bases de données .
Transactions
Une transaction est un groupe d’actions qui doivent être menées avec succès sur
une ou plusieurs tables dans une base de données avant d’être validées (rendues
définitives). Si l’une des actions du groupe échoue, toutes les actions sont
abandonnées (annulées).
Les transactions protègent contre les défaillances matérielles qui se produisent au
milieu d’une commande de base de données ou d’un ensemble de commandes.
Elle constituent aussi la base du contrôle simultané de plusieurs utilisateurs sur
les serveurs SQL. Lorsque tous les utilisateurs interagissent avec la base de
données par le biais de transactions, les commandes d’un utilisateur ne peuvent
pas altérer l’unité d’une transaction d’un autre utilisateur ; le serveur SQL
planifie les transaction entrantes, qui réussissent ou échouent en bloc.
Bien que le support des transactions ne fasse pas partie de la plupart des bases
de données locales, les pilotes du moteur de bases de données Borland offrent
pour certaines un support des transactions limité. Pour les serveurs SQL et les
bases de données de type ODBC, le support des transactions de base de données
est fourni par la base de données même. Dans les applications multiniveau, vous
pouvez créer des transactions qui comprennent des actions autres que des
opérations de base de données ou qui englobent plusieurs bases de données.
Pour plus de détails sur l’utilisation des transactions dans les applications basées
sur le moteur de bases de données Borland, voir “Utilisation des transactions” à
la page 14-5. Pour plus de détails sur l’utilisation des transactions dans les
applications multiniveau, voir “Gestion des transactions dans les applications
multiniveaux” à la page 15-41 .
Dictionnaire de données
Quel que soit le type de base de données que vous utilisez, votre application
peut accéder au dictionnaire de données. Le dictionnaire de données offre une
zone de stockage paramétrable, indépendante de vos applications, dans laquelle
vous pouvez créer des ensembles d’attributs de champ étendus qui décrivent le
contenu et l’aspect des données.
Par exemple, si vous êtes souvent amené à développer des applications
financières, vous pouvez créer un certain nombre d’ensembles spécialisés
d’attributs de champ pour décrire les différents formats d’affichage monétaire. Si
ensuite, lors de la conception, vous créez un ensemble de données dans une
application, plutôt que d’utiliser l’inspecteur d’objets pour définir manuellement
les champs monétaires de l’ensemble de données, vous pouvez associer ces
champs à un ensemble d’attributs de champ étendus dans le dictionnaire de
données. L’utilisation du dictionnaire de données permet d’homogénéiser l’aspect
des données sur toutes les applications que vous créez.
Dans un environnement Client/Serveur, le dictionnaire de données peut se situer
sur un serveur distant afin d’offrir un meilleur partage des informations.
Pour savoir, lors de la conception, comment créer des ensembles d’attributs à
partir de l’éditeur de champs, puis associer ces attributs aux champs des
ensembles de données de votre application, voir “Création d’ensembles
d’attributs pour les composants champ” à la page 19-17. Pour savoir comment
créer un dictionnaire de données ainsi que des attributs de champ étendus en
utilisant l’explorateur SQL et l’explorateur de bases de données, reportez-vous à
leur aide en ligne respective.
Une interface de programmation pour le dictionnaire de données est disponible
dans l’unité drintf (dans le répertoire lib). Cette interface fournit les méthodes
suivantes :
Remarque La gestion des applications multiniveau est uniquement disponible dans les
versions Client/Serveur et Entreprise.
Anticipation de l’évolutivité
Le processus de développement peut s’avérer plus prenant et onéreux au fur et à
mesure que le nombre de niveaux s’accroît. C’est pourquoi vous pouvez
commencer par développer une application à niveau unique. L’augmentation de
la quantité de données, du nombre d’utilisateurs et du nombre des différentes
applications accédant aux données vous obligera peut-être à adopter une
architecture multiniveau. En anticipant l’évolutivité, vous pouvez protéger vos
investissements en développement d’applications à niveau unique ou à niveau
double par la réutilisation de votre code au fur et à mesure que votre application
s’accroît.
Les composants orientés données de la VCL facilitent l’écriture d’applications
évolutives en cernant le comportement de la base de données et des données
qu’elle stocke. Que vous écriviez une application à niveau unique, à niveau
double ou multiniveau, vous pouvez isoler votre interface utilisateur de la
couche d’accès aux données comme le montre la figure 13.1.
Figure 13.1 Interface utilisateur des connexions aux ensembles de données dans toutes applications de
base de données
Dans ce modèle, toutes les applications sont des clients de base de données. Un
client demande des informations à un serveur de bases de données et lui en
envoie. Un serveur peut traiter les requêtes de nombreux clients simultanément,
en coordonnant l’accès aux données et leur mise à jour.
Delphi peut être utilisé pour créer les applications client et les serveurs
d’applications. Comme l’illustre la figure précédente, dans une application client,
des contrôles orientés données standard connectés à une source de données par
l’intermédiaire d’un ou de plusieurs composants ensemble de données
permettent d’afficher et de modifier des données. Chaque ensemble de données
client communique avec un serveur d’applications par l’intermédiaire d’une
Les contrôles orientés données que vous ajoutez à votre interface utilisateur
dépendent du type de données que vous affichez (texte brut, texte formaté,
graphique, éléments multimédia, etc.). En outre, votre choix des contrôles est
déterminé par la façon dont vous souhaitez organiser les informations et,
éventuellement, par la façon dont vous souhaitez que les utilisateurs puissent
naviguer dans les enregistrements ou les ensembles de données pour y ajouter
ou y modifier des données.
Les sections suivantes présentent les composants que vous pouvez utiliser pour
différents types d’interface utilisateur .
Ecriture de rapports
Si vous souhaitez que les utilisateurs puissent imprimer les informations de base
de données émanant des ensembles de données de votre application, vous
pouvez utiliser les composants rapport de la page QReport de la palette des
composants. L’utilisation de ces composants vous permet de construire
visuellement des rapports à bandes pour présenter et résumer les informations
contenues dans vos tables de base de données. Vous pouvez ajouter des résumés
aux en-têtes et aux pieds de page de groupe pour analyser les données en
fonction de critères de regroupement.
Démarrez un rapport pour votre application en sélectionnant l’icône QuickReport
dans la boîte de dialogue Nouveaux éléments. Sélectionnez Fichier|Nouveau
dans le menu principal et allez à la page Affaires. Double-cliquez sur l’icône
Expert QuickReport pour lancer l’expert.
• Vous utilisez des composants base de données explicites. Les composants base
de données (TDatabase) représentent une base de données dans votre
application. Si vous n’ajoutez pas de composant base de données de façon
explicite, un composant temporaire est créé automatiquement en fonction de la
valeur de la propriété DatabaseName. Si vous utilisez des composants base de
données explicites, DatabaseName est la valeur de la propriété DatabaseName du
composant base de données. Voir “Présentation des composants base de
données persistants et temporaires” à la page 17-2 pour plus d’informations
sur l’utilisation des composants base de données.
Par exemple, dans une application bancaire, le transfert de fonds d’un compte
vers un autre est une opération qui mérite d’être protégée avec une transaction.
Si, après diminution du solde d’un compte, une erreur se produit dans
l’augmentation du solde de l’autre compte, il est souhaitable d’annuler la
transaction afin que la base de données continue de refléter le solde total correct.
Par défaut, le BDE permet de contrôler explicitement les transactions de vos
applications. Lorsqu’une application est placée sous contrôle implicite des
transactions, une transaction séparée est utilisée pour chaque enregistrement de
l’ensemble de données écrit dans la base de données sous-jacente. Les
transactions implicites réduisent au minimum les conflits de mise à jour des
enregistrements et garantissent l’homogénéité de la vue de la base de données.
D’un autre côté, comme chaque ligne de données écrite dans une base de
données occupe de la place dans sa propre transaction, le contrôle des
transactions implicites peut générer un trafic réseau excessif et ralentir la
performance de l’application. De plus, le contrôle des transactions implicites ne
protège pas les opérations logiques qui englobent plusieurs enregistrements,
comme le transfert de fonds précédemment décrit.
Si vous contrôlez les transactions de façon explicite, vous pouvez efficacement
décider à quel moment les démarrer, les valider et les annuler. Lorsque vous
développez des applications dans un environnement multi-utilisateur, notamment
lorsque vos applications utilisent un serveur SQL distant, vous devez contrôler
les transactions de façon explicite.
Remarque Vous pouvez réduire au minimum le nombre de transactions requises en mettant
les mises à jour en mémoire cache. Pour plus d’informations sur les mises à jour
mises en mémoire cache, voir chapitre 24, “Manipulation des mises à jour en
mémoire cache.”
Les applications à niveau unique ne peuvent pas utiliser SQL direct. Vous
pouvez utiliser le composant base de données pour créer des transactions
explicites pour les bases de données locales. Toutefois, il y a certains limites à
l’utilisation des transactions locales. Pour plus d’informations sur l’utilisation des
transactions locales, voir “Utilisation des transactions locales” à la page 14-10.
Lorsque vous écrivez des applications à niveau double (qui requièrent des liens
SQL, uniquement disponibles dans les versions Client/Serveur et Entreprise de
Delphi), vous pouvez utiliser un composant base de données ou SQL direct pour
gérer les transactions. Pour plus d’informations sur l’utilisation de SQL direct,
voir “Utilisation du SQL direct” à la page 14-9.
Commit est généralement tentée dans une instruction try...except. Ainsi, si une
transaction ne peut pas être correctement validée, vous pouvez utiliser le bloc
except pour traiter l’erreur et renouveler l’opération ou pour annuler la
transaction.
4 Si une erreur se produit pendant l’application des modifications faisant partie
de la transaction ou pendant la tentative de validation de la transaction, vous
pouvez supprimer toutes les modifications qui composent la transaction. Pour
supprimer ces modifications, utilisez la méthode Rollback du composant base
de données:
DatabaseInterBase.Rollback;
Rollback est généralement exécutée
• Dans un code de gestion des exceptions, lorsque vous ne pouvez pas
rétablir la situation après une erreur de base de données.
• Dans un code d’événement de bouton ou de menu, comme lorsqu’un
utilisateur clique sur un bouton Annuler.
Remarque Lorsque vous utilisez des transactions avec des tables locales Paradox, dBASE,
Access et FoxPro, mettez TransIsolation à tiDirtyRead plutôt que d’utiliser la
valeur par défaut de tiReadCommitted. Une erreur BDE est renvoyée si
TransIsolation a une valeur autre que tiDirtyRead pour les tables locales.
Lorsqu’une application utilise ODBC pour s’interfacer avec un serveur, il faut
que le pilote ODBC supporte aussi le niveau d’isolement voulu. Pour plus
d’informations, reportez-vous à la documentation de votre pilote ODBC.
4 Dans l’application client, ajoutez du code pour appliquer les mises à jour dans
le serveur d’applications. Pour plus d’informations sur l’envoi de mises à jour
à partir d’une application client vers un serveur d’applications, voir “Mise à
jour des enregistrements” à la page 15-35.
Utilisation de MTS
L’utilisation de MTS permet à votre module de données distant de tirer parti des
éléments suivants :
• Sécurité MTS. MTS offre à votre serveur d’applications une sécurité à base de
rôles. Des rôles sont attribués aux clients et déterminent si ces derniers
peuvent ou non accéder à l’interface du module de données distant. Le
module de données MTS implémente la méthode IsCallerInRole, qui vous
permet de contrôler le rôle du client en cours de connexion et d’accorder
certaines fonctions tributaires de ce rôle. Pour plus d’informations sur la
sécurité MTS, voir “Sécurité en fonction des rôles” à la page 49-12.
Utilisation de OLEnterprise
OLEnterprise vous permet d’utiliser le courtier d’objets d’entreprise au lieu du
courtage côté client. Le courtier d’objets d’entreprise offre la répartition
équilibrée de la charge, le basculement de serveur et la transparence de
localisation.
Lorsque vous utilisez OLEnterprise, vous devez installer le runtime OLEnterprise
sur les systèmes client et serveur. Le runtime OLEnterprise gère le marshalling
des appels Automation et communique entre les systèmes client et serveur à
l’aide d’appels de procédures à distances (RPC). Pour plus d’informations,
reportez-vous à la documentation OLEnterprise.
Configuration de TRemoteDataModule
Pour ajouter un composant TRemoteDataModule dans votre application, choisissez
Fichier|Nouveau et sélectionnez Module de données distant dans la page Multi-
niveaux de la boîte de dialogue des nouveaux éléments. L’expert Module de
données distant apparaît.
Vous devez fournir un nom de classe pour votre module de données distant. Il
s’agit du nom de base d’un descendant de TRemoteDataModule que votre
application crée. Il s’agit aussi du nom de base de l’interface de cette classe. Par
exemple, si vous spécifiez le nom de classe MyDataServer, l’expert crée une
nouvelle unité en déclarant TMyDataServer, un descendant de TRemoteDataModule,
qui implémente IMyDataServer, un descendant de IDataBroker.
Remarque Vous pouvez ajouter vos propres propriétés et méthodes à votre nouvelle
interface. Pour plus d’informations, voir “Extension de l’interface du serveur
d’applications” à la page 15-39.
Si vous créez une bibliothèque de liaison dynamique (Active Library), vous
devez spécifier le modèle threading dans l’expert Module de données distant.
Vous pouvez choisir Thread Unique, Thread Appartement, Thread Libre ou Les
deux.
• Si vous choisissez Thread Unique, COM fait en sorte qu’une seule requête
client soit traitée à un moment donné. Aucune requête client ne peut entrer en
conflit avec une autre.
• Si vous choisissez Thread Appartement, COM fait en sorte que toute instance
de votre module de données distant traite une seule requête à un moment
donné. Lorsque vous écrivez du code dans une bibliothèque Thread
Appartement, vous devez prévenir les conflits de thread si vous utilisez des
variables globales ou des objets non contenus dans le module de données
distant.
• Si vous choisissez Thread Libre, votre application peut recevoir des requêtes
client simultanées sur plusieurs threads. Vous devez faire en sorte que votre
application soit compatible avec les threads. Comme plusieurs clients peuvent
simultanément accéder à votre module de données distant, vous devez
protéger vos données d’instance (propriétés, objets contenus, etc.) ainsi que les
variables globales. Ce modèle n’est pas recommandé car il n’inclut pas de
support de thread pour utiliser l’interface IProvider.
• Si vous choisissez Les deux, votre bibliothèque fonctionne de la même façon
que lorsque vous choisissez Thread Libre, à la différence que tous les rappels
(appels vers les interfaces client) sont automatiquement sérialisés.
Si vous créez un fichier .EXE, vous devez spécifier le type d’instanciation à
utiliser. Vous pouvez choisir Instance unique ou Instance multiple (l’instanciation
interne ne s’applique que si le code client fait partie du même espace de
processus.)
• Si vous choisissez Instance unique, chaque connexion client lance sa propre
instance du fichier exécutable. Ce processus instancie une seule instance du
module de données distant, qui est dédié à la connexion client .
• Si vous choisissez Instance multiple, une seule instance de l’application
(processus) instancie tous les modules de données distants créés pour les
clients. Chaque module de données distant est dédié à une seule connexion
client, mais ils partagent tous le même espace de processus.
Configuration de TMTSDataModule
Pour ajouter un composant TMTSDataModule dans votre application, choisissez
Fichier|Nouveau et sélectionnez Module de données MTS dans la page Multi-
niveau de la boîte de dialogue des nouveaux éléments. L’expert Module de
données MTS apparaît.
Vous devez fournir un nom de classe pour votre module de données distant. Il
s’agit du nom de base d’un descendant de TMTSDataModule que votre
application crée. Il s’agit aussi du nom de base de l’interface de cette classe. Par
exemple, si vous spécifiez le nom de classe MyDataServer, l’expert crée une
nouvelle unité en déclarant TMyDataServer, un descendant de TMTSDataModule,
qui implémente IMyDataServer, un descendant de IDataBroker.
Remarque Vous pouvez ajouter vos propres propriétés et méthodes à votre nouvelle
interface. De fait, vous devez le faire si vous souhaitez tirer parti des
transactions MTS ou de l’activation « juste à temps ». Pour plus d’informations,
voir “Extension de l’interface du serveur d’applications” à la page 15-39.
Les applications MTS sont toujours des bibliothèques de liaison dynamique
(Active Library), vous devez spécifier le modèle threading dans l’expert Module
de données MTS. Vous pouvez choisir Unique, Appartement, Libre ou Les deux.
• Si vous choisissez Unique, MTS COM fait en sorte qu’une seule requête client
soit traitée à un moment donné. Aucune requête client ne peut entrer en
conflit avec une autre.
• Si vous choisissez Appartement ou Libre, vous obtenez la même chose : MTS
fait en sorte que toute instance de votre module de données distant traite une
seule requête à un moment donné, mais ces appels n’utilisent pas toujours le
même thread. Vous ne pouvez pas utiliser de variables de thread car rien ne
garantit que les appels successifs de l’instance du module de données distant
utilisent le même thread. Vous devez prévenir les conflits de thread si vous
utilisez des variables globales ou des objets non contenus dans le module de
données distant. Au lieu d’utiliser des variables globales, vous pouvez utiliser
le gestionnaire de propriétés partagées. Pour plus d’informations sur le
gestionnaire de propriétés partagées, voir “Gestionnaire de propriétés
partagées” à la page 49-13.
• Si vous choisissez Both, MTS appelle l’interface du module de données distant
de la même façon que lorsque vous choisissez Appartement ou Libre.
Toutefois, tous les rappels réalisés en direction des applications clients sont
automatiquement sérialisés afin qu’aucun n’entre en conflit avec un autre.
Remarque Les modèles Apartment et Free sous MTS diffèrent des modèles correspondants
sous DCOM.
Vous devez aussi spécifier les attributs des transactions MTS de votre module de
données distant. Vous pouvez choisir parmi les options suivantes :
• Requiert une transaction. Lorsque vous sélectionnez cette option, chaque fois
qu’un client utilise l’interface de votre module de données distant, l’appel est
exécuté dans le contexte d’une transaction MTS. Si l’appelant fournit une
transaction, il est inutile qu’une nouvelle transaction soit créée.
• Requiert une nouvelle transaction. Lorsque vous sélectionnez cette option,
chaque fois qu’un client utilise l’interface de votre module de données distant,
une nouvelle transaction est automatiquement créée pour l’appel.
Configuration de TCorbaDataModule
Pour ajouter un composant TCorbaDataModule dans votre application, choisissez
Fichier|Nouveau et sélectionnez Module de données CORBA dans la page
Multi-niveau de la boîte de dialogue des nouveaux éléments. L’expert Module de
données CORBA apparaît.
Vous devez fournir un nom de classe pour votre module de données distant. Il
s’agit du nom de base d’un descendant de TCorbaDataModule que votre
application crée. Il s’agit aussi du nom de base de l’interface de cette classe. Par
exemple, si vous spécifiez le nom de classe MyDataServer, l’expert crée une
nouvelle unité en déclarant TMyDataServer, un descendant de TCorbaDataModule,
qui implémente IMyDataServer, un descendant de IDataBroker.
Remarque Vous pouvez ajouter vos propres propriétés et méthodes à votre nouvelle
interface. De fait, vous devez le faire si vous souhaitez utiliser l’instance de
modèle unique décrite ci-après. Pour plus d’informations sur l’ajout d’éléments à
l’interface de votre module de données, voir “Extension de l’interface du serveur
d’applications” à la page 15-39.
L’expert module de données CORBA vous permet de spécifier comment votre
application serveur crée les instances du module de données distant. Vous
pouvez choisir entre le mode partagé ou instance par client.
• Lorsque vous choisissez le mode partagé, votre application crée une instance
unique du module de données distant qui gère toutes les requêtes client. Ce
modèle est traditionnellement utilisé dans le développement CORBA. Comme
le module de données distant unique est partagé par tous les clients, il doit
être sans état. (Cela signifie que vous ne pouvez pas utiliser l’interface
IProvider.) Pour plus d’informations sur l’écriture de modules de données
distants sans état, voir “Gestion des modules de données distants sans état” à
la page 15-43.
• Lorsque vous choisissez le mode instance par client, une nouvelle instance du
module de données distant est créée pour chaque connexion client. Tant que
la connexion est ouverte, l’instance du module de données distant demeure.
Lorsque les connexions client se ferment, l’application serveur libère leurs
instances du module de données distant. Ce modèle permet aux clients de
communiquer à l’aide des interfaces IProvider, car les informations d’état
peuvent être conservées. Pour prévenir la défaillance des systèmes client sans
libération du module de données distant, l’application envoie régulièrement
des messages pour vérifier que le client est toujours en cours d’exécution.
Vous pouvez éviter ce processus d’envoi de messages en utilisant une instance
partagée unique.
• PRIMARY KEY, pour désigner une ou plusieurs colonnes comme clé primaire
de la table à des fins d’indexation.
• FOREIGN KEY, pour désigner une ou plusieurs colonnes qui, dans une table,
référencent une autre table.
Remarque Cette liste n’est pas exclusive. Votre serveur de base de données peut supporter
en totalité ou en partie toutes ces contraintes ou un sous-ensemble seulement, et
il peut également supporter des contraintes supplémentaires. Pour plus
d’informations sur les contraintes supportées, consultez la documentation de
votre serveur.
Les contraintes des serveurs de bases de données englobent plusieurs types de
contrôles qui étaient gérés dans le passé par des applications de bases de
données monopostes traditionnelles. Vous pouvez exploiter les contraintes
serveur dans vos applications de bases de données multiliaisons sans avoir à les
spécifier en double dans le code du serveur d’applications ou dans celui de
l’application client.
La propriété Constraints du fournisseur vous permet de répliquer et d’appliquer
des contraintes serveur aux données transmises et reçues par les applications
client. Quand Constraints vaut True (la valeur par défaut), les contraintes de votre
serveur sont répliquées vers les clients et elles affectent les tentatives client de
mise à jour des données.
Remarque Il peut exister des occasions où vous ne souhaitez pas appliquer des contraintes
serveur aux données transmises à une application client. Par exemple, une
application client qui reçoit des données par paquets et autorise une mise à jour
locale des enregistrements avant de lire d’autres enregistrements peut avoir besoin
de désactiver certaines contraintes serveur qui seraient déclenchées, car les
données sur lesquelles les mises à jour sont effectuées sont temporairement
incomplètes. Pour empêcher la réplication des contraintes du serveur
d’applications vers un ensemble de données client, initialisez Constraints à False.
Notez aussi que les ensembles de données client peuvent désactiver et activer des
contraintes à l’aide des méthodes DisableConstraints et EnableConstraints methods.
Pour plus d’informations sur l’activation et la désactivation des contraintes à partir
de l’ensemble de données client, voir “Gestion des contraintes” à la page 15-34.
Remarque Même lorsque existe une entrée de registre système pour le serveur
d’applications, vous pouvez spécifier ComputerName pour écraser cette entrée.
Cela peut être particulièrement utile pendant le développement, le test et le
débogage.
Si vous fournissez le nom d’un ordinateur hôte ou d’un serveur introuvable, le
composant connexion DCOM déclenche une exception lorsque vous essayez
d’ouvrir la connexion.
Si votre application client peut choisir parmi plusieurs serveurs, vous pouvez
utiliser la propriété ObjectBroker au lieu de spécifier une valeur pour
ComputerName. Pour plus d’informations, voir “Courtage de connexions” à la
page 15-31.
Courtage de connexions
Si votre application client peut choisir parmi plusieurs serveurs, vous pouvez
utiliser un courtier d’objets pour localiser un système serveur disponible. Le
courtier d’objets gère une liste de serveurs disponibles pour le composant
connexion. Lorsque le composant connexion a besoin de se connecter à un
serveur d’applications, il demande au courtier d’objets un nom d’ordinateur (ou
une adresse IP ou un nom d’hôte). Le courtier fournit un nom d’ordinateur puis
le composant connexion établit une connexion. Si le nom fourni ne fonctionne
pas (par exemple si le serveur n’est pas opérationnel), le courtier fournit un
autre nom et répète l’opération jusqu’à ce que la connexion soit établie.
Une fois que le composant connexion a établi une connexion avec un nom fourni
par le courtier, il enregistre ce nom en tant que valeur de la propriété appropriée
(ComputerName, Address ou Host). Si le composant connexion ferme la connexion
puis a besoin de la rouvrir, il utilise cette valeur de propriété et ne demande un
nouveau nom au courtier que si la connexion échoue.
Pour utiliser un courtier d’objets, spécifiez la propriété ObjectBroker de votre
composant connexion. Lorsque la propriété ObjectBroker est initialisée, le
composant connexion n’enregistre pas la valeur de ComputerName, Address ou Host.
Remarque N’utilisez pas la propriété ObjectBroker avec des connexions OLEnterprise ou
CORBA. Ces deux protocoles possèdent leurs propres services de courtage.
Connexion au serveur
Pour localiser le serveur d’applications et vous y connecter, vous devez d’abord
initialiser les propriétés du composant connexion pour identifier le serveur
d’applications. Ce processus est décrit dans “Connexion au serveur
d’application” à la page 15-27. De plus, avant d’ouvrir la connexion, tous les
ensembles de données client qui utilisent le composant connexion pour obtenir
une interface IProvider doivent l’indiquer en initialisant leur propriété
RemoteServer. Les ensembles de données client initialisent alors leur propriété
ProviderName avant d’ouvrir la connexion de sorte que, lorsque la connexion est
ouverte, ils puissent obtenir l’interface IProvider adéquate.
La connexion est automatiquement ouverte lorsque les ensembles de données
client essaient d’accéder à l’interface IProvider. Par exemple, l’nitialisation de la
propriété Active de l’ensemble de données client à True ouvre la connexion.
Si vous ne liez pas les ensembles de données client au composant connexion
pour qu’ils puissent utiliser l’interface IProvider, vous pouvez ouvrir la connexion
en initialisant la propriété Connected du composant connexion à True.
Bien que les applications client n’aient pas besoin d’appeler l’interface
IDataBroker du module de données distant du serveur d’applications, vous
pouvez ajouter vos propres extensions à l’interface. Lorsque vous étendez
l’interface du serveur d’applications, vous devez être en mesure d’appeler ces
extensions à l’aide de la connexion créée par votre composant connexion. A cet
effet, vous pouvez utiliser la propriété AppServer du composant connexion. Pour
plus d’informations sur l’extension de l’interface du serveur d’applications, voir
“Extension de l’interface du serveur d’applications” à la page 15-39.
AppServer est un Variant qui représente l’interface du serveur d’applications.
Vous pouvez appeler une méthode d’interface à l’aide de AppServer en écrivant
une instruction telle que
MyConnection.AppServer.SpecialMethod(x,y);
Toutefois, cette technique offre une liaison tardive (dynamique) de l’appel
d’interface. En raison de cela, l’ppale de la procédure SpecialMethod n’est pas liée
avant l’exécution lorsque l’appel est exécuté. La liaison tardive est très souple
mais son utilisation vous prive de nombreux avantages tels que code insight et
la vérification de type. De plus, la liaison tardive est plus lente que la liaison
anticipée car le compilateur génère des appels supplémentaires vers le serveur
pour configurer des appels d’interface avant de les réaliser.
Lorsque vous utilisez DCOM ou CORBA comme protocole de communications,
vous pouvez utiliser la liaison anticipée d’appels AppServer. Utilisez l’opérateur
as pour affecter à la variable AppServer le descendant IDataBroker que vous avez
créé lorsque vous avez créé le module de données distant. Par exemple :
with MyConnection.AppServer as IMyAppServer do
SpecialMethod(x,y);
fournit une liaison anticipée pour une connexion DCOM tandis que
with IUnknown(MyConnection.AppServer) as IMyAppServer do
SpecialMethod(x,y);
fournit une liaison anticipée pour une connexion CORBA.
Pour utiliser la liaison anticipée sous DCOM, la bibliothèque de type du serveur
doit être recensée sur la machine client. Vous pouvez utiliser TRegsvr.exe, fourni
avec Delphi, pour recenser la bibliothèque de types.
Remarque Reportez-vous à la démo TRegSvr (qui offre le source de TRegsvr.exe) pour un
exemple de recensement de la bibliothèque de type par programmation.
Pour utiliser la liaison anticipée avec CORBA, vous devez ajouter à votre projet
l’unité _TLB générée par l’éditeur de bibliothèque de types. Pour ce faire, ajoutez
cette unité à la clause uses de votre unité.
Lorsque vous utilisez TCP/IP ou OLEnterprise, vous ne pouvez pas réellement
utiliser la liaison anticipée mais, comme le module de données distant utilise une
interface double, vous pouvez utiliser la dispinterface du serveur d’applications
pour améliorer la performance d’une simple liaison tardive. La dispinterface
Remarque Si vous utilisez des transactions MTS ou le procédé “juste à temps”, vous ne
pouvez pas utiliser l’interface IProvider pour appliquer les mises à jour. Vous
devez réaliser ce processus à l’aide de l’interface du serveur d’applications. Pour
plus d’informations, “Gestion des modules de données distants sans état” à la
page 15-43
• UpdateKind: type de mise à jour ayant généré l’erreur. UpdateKind peut être
ukModify (problème survenu lors de la mise à jour d’un enregistrement
existant modifié), ukInsert (problème survenu lors de l’insertion d’un nouvel
enregistrement) ou ukDelete (problème survenu lors de la suppression d’un
enregistrement existant).
• Action: paramètre var vous permettant d’indiquer l’action à entreprendre à la
fin de l’exécution du gestionnaire OnReconcileError. Lors de l’entrée dans le
gestionnaire, Action est initialisée à l’action entreprise par le processus de
résolution du serveur. Dans votre gestionnaire d’événement, vous initialisez ce
paramètre pour
• Ignrer l’enregistrement et le laisser dans le journal de modifications (raSkip).
• Abandonner l’opération de régularisation. (raAbort)
• Fusionner la modification infructueuse avec l’enregistrement correspondant
sur le serveur. (raMerge) Cela ne fonctionne que si le serveur n’a changé
aucun des champs modifiés par l’utilisateur.
• Remplacer la mise à jour courante dans le journal de modifications par la
valeur de l’enregistrement dans le gestionnaire d’événement (qui a
normalement été corrigé). (raCorrect)
• Retirer les modifications de l’enregistrement sur l’ensemble de données
client, en réappliquant les valeurs initialement fournies. (raCancel)
• Mettre à jour la valeur de l’enregistrement en cours en fonction de
l’enregistrement du serveur. (raRefresh)
Le code suivant montre un gestionnaire d’événement OnReconcileError qui utilise
la boîte de dialogue de régularisation de l’unité RecError présente dans le
répertoire du référentiel d’objets. (Pour utiliser cette boîte de dialogue, ajoutez
RecError à votre clause uses.)
procedure TForm1.ClientDataSetReconcileError(DataSet: TClientDataSet; E: EReconcileError;
UpdateKind: TUpdateKind, var Action TReconcileAction);
begin
Action := HandleReconcileError(DataSet, UpdateKind, E);
end;
Les applications client peuvent aussi mettre à jour les données sans toucher au
journal de modifications. Pour ce faire, appelez la méthode RefreshRecord de
l’ensemble de données client. A la différence de la méthode Refresh, RefreshRecord
ne met à jour que l’enregistrement en cours dans l’ensemble de données client.
RefreshRecord modifie la valeur d’enregistrement initialement obtenue du serveur
d’applications mais laisse intacts tous les changements contenus dans le journal
de modifications.
Attention Il n’est pas approprié d’appeler systématiquement RefreshRecord. Si les
modifications de l’utilisateur entrent en conflit avec celles apportées à l’ensemble
de données sous-jacent par d’autres utilisateurs, l’appel de RefreshRecord masque
ce conflit. Lorsque l’application client applique ses mises à jour, aucune erreur de
régularisation ne se produit et l’application ne peut pas résoudre le conflit.
Pour éviter que les erreurs de mise à jour ne soient masquées, les applications
client peuvent vérifier qu’aucune mise à jour n’est en attente avant d’appeler
RefreshRecord. Par exemple, le code suivant déclenche une exception en cas de
tentative de rafraîchissement d’un enregistrement modifié :
if ClientDataSet1.UpdateStatus <> usUnModified then
raise Exception.Create(’You must apply updates before refreshing the current record.’);
ClientDataSet1.RefreshRecord;
Vous pouvez par contre indiquer au composant fournisseur d’appliquer les mises
à jour et de résoudre les erreurs directement vers un ensemble de données du
serveur d’applications. Cette approche vous permet d’utiliser un ensemble de
données client ou un ensemble de données personnalisé sur votre serveur
d’applications et de représenter les données inacessibles par le biais de n’importe
quel pilote BDE. Pour résoudre vers un ensemble de données au lieu d’utiliser
du code SQL généré dynamiquement, initialisez la propriété ResolveToDataSet de
votre composant TProvider à True.
Si votre serveur d’applications n’utilise pas le moteur de bases de données
Borland, vous pouvez utiliser un composant TDataSetProvider au lieu d’un
composant TProvider. A la différence de TProvider, TDataSetProvider n’a pas de
dépendance sur le BDE. L’utilisation de ce composant permet à votre application
serveur de se passer du BDE le cas échéant.
Remarque Ne combinez pas les transactions MTS avec les transactions explicites créées par
un composant base de données ou à l’aide de SQL direct. Lorsque votre module
de données distant est répertorié dans une transaction MTS, il répertorie
automatiquement tous les appels de votre base de données dans la transaction.
Pour plus d’informations sur l’utilisation des transactions MTS, voir “Support
transactionnel MTS” à la page 49-7.
Pour appliquer les mises à jour, ajoutez une méthode à l’interface du serveur
d’applications telle que la méthode suivante :
function TMyRemoteDataModule.ApplyCustomerUpdates(Delta: OleVarant; MaxErrors: Integer; out
ErrorCount: Integer); OleVariant;
begin
try
Result := CustomerProvider.ApplyUpdates(Delta, MaxErrors, ErrorCount);
SetComplete;
except
SetAbort;
end;
end;
Côté client, au lieu d’appeler la méthode ApplyUpdates de l’ensemble de données
client, vous devez appeler la méthode d’interface suivante :
with ClientDataSet1 do
begin
CheckBrowseMode;
if ChangeCount > 0 then
Reconcile(MyConnectionComponent.AppServer.ApplyCustomerUpdates(Delta, MaxErrors,
ErrCount));
end;
Suivez les étapes ci-dessous pour activer la création dynamique d’un composant
session à l’exécution :
1 Déclarez un pointeur sur une variable TSession.
2 Instanciez une nouvelle session en appelant le constructeur Create. Le
constructeur définit une liste vide de composants base de données pour la
session, crée une liste de callbacks BDE pour la session, met la propriété
KeepConnections à True et ajoute la session à la liste des sessions gérée par le
composant liste de sessions.
3 Affectez à la propriété SessionName de la nouvelle session un nom unique.
Cette propriété est utilisée pour associer les composants base de données à la
session. Pour plus d’informations sur la propriété SessionName, voir
“Dénomination d’une session” à la page 16-4.
4 Activez la session et modifiez éventuellement ses propriétés.
Remarque Ne supprimez jamais la session par défaut.
La création et l’ouverture de sessions peuvent aussi être gérées au moyen de la
méthode OpenSession du composant TSessionList. L’utilisation de OpenSession
présente moins de risques que d’appeler Create, car OpenSession ne crée une
session que si celle-ci n’existe pas. Pour plus d’informations sur la méthode
OpenSession, voir “Gestion de plusieurs sessions” à la page 16-18.
Le code suivant crée un nouveau composant session, lui affecte un nom et ouvre
la session pour réaliser des opérations de base de données (non illustrées ici). A
la fin des opérations, il est détruit par un appel en direction de la méthode Free.
var
SecondSession: TSession;
begin
SecondSession := TSession.Create;
with SecondSession do
try
SessionName := 'SecondSession';
KeepConnections := False;
Open;
...
finally
SecondSession.Free;
end;
end;
Pour les composants session que vous placez dans un module de données ou
dans une fiche, le fait de mettre Active à False quand les bases de données ou les
ensembles de données sont ouverts provoque leur fermeture. Lors de l’exécution,
cette fermeture peut provoquer l’appel d’événements associés.
Remarque Vous ne pouvez pas mettre à False la propriété Active de la session par défaut au
moment de la conception. Bien que cela soit déconseillé, il est possible de fermer
la session par défaut à l’exécution.
Au moment de la conception, utilisez l’inspecteur d’objets pour mettre Active à
False afin de désactiver tous les accès de base de données d’une session par une
simple modification de propriété. Lors de la conception d’une application, cette
opération permet d’inhiber provisoirement les exceptions provoquées par
l’indisponibilité momentanée d’une base de données distante.
Vous pouvez utiliser les méthodes Open et Close d’une session pour activer ou
désactiver des sessions autres que la session par défaut au moment de
l’exécution. Par exemple, la simple ligne de code suivante ferme toutes les bases
de données et tous les ensembles de données ouverts pour une session :
Session1.Close;
Ce code affecte la valeur False à la propriété Active de Session1. Lorsque la
propriété Active d’une session est à False, toute tentative ultérieure de la part de
l’application pour ouvrir une base ou un ensemble de données a pour effet de
réinitialiser Active à True et d’appeler le gestionnaire d’événement OnStartup de
la session, s’il est défini. Il vous est également possible de coder la réactivation
de la session à l’exécution. Le code suivant réactive Session1 :
Session1.Open;
Remarque Si une session est active, vous pouvez aussi ouvrir et fermer des connexions de
base de données particulières. Pour plus d’informations, voir “Fermeture d’une
connexion de base de données” à la page 16-8.
Si cette propriété est à True (la valeur par défaut), une connexion constante ou
persistante est maintenue avec la base de données, même si aucun ensemble de
données n’est actif. A False, la connexion de base de données est interrompue
aussitôt que tous ses ensembles de données sont fermés.
Remarque La persistance de la connexion des composants base de données que vous placez
explicitement dans un module de données ou dans une fiche est contrôlée par
leur propriété KeepConnection. La valeur KeepConnection du composant base de
données prend le pas sur la valeur KeepConnections du composant session si les
deux valeurs diffèrent. Pour plus d’informations concernant le contrôle spécifique
des connexions de bases de données dans une session, voir “Création, ouverture
et fermeture des connexions de bases de données” à la page 16-7.
KeepConnections doit toujours être mise à True pour les applications qui ouvrent
et ferment fréquemment tous les ensembles de données associés à une base de
données située sur un serveur distant. Ce paramétrage a pour effet de réduire le
trafic sur le réseau et d’accélérer les accès aux données car la connexion n’est
ouverte et fermée qu’une seule fois pendant toute la durée de la session. Sans ce
paramétrage, chaque fermeture ou rétablissement de la connexion entraîne une
surcharge de travail liée au rattachement et détachement de la base de données.
Remarque Même si KeepConnections es à True, la fermeture de toutes les connexions de
bases de données actives reste à tout moment possible grâce à la méthode
DropConnections. Pour plus d’informations sur DropConnections, voir “Abandon
des connexions aux bases de données temporaires” à la page 16-9.
Par exemple, le code suivant interrompt les connexions inactives pour la session
par défaut :
Session.DropConnections;
OpenDatabase rend une session active si elle ne l’est pas déjà, puis détermine si le
nom de base de données spécifié correspond à la propriété DatabaseName d’un
composant base de données de cette session. Si le nom spécifié ne correspond à
aucun composant base de données existant, OpenDatabase crée un composant
base de données temporaire et lui donne ce nom. Chaque appel à OpenDatabase
incrémente d’une unité le nombre de références à la base de données. Tant que
ce nombre de références est supérieur à 0, la base de données est ouverte. Pour
finir, OpenDatabase appelle la méthode Open du composant base de données pour
établir la connexion au serveur.
Les instructions suivantes utilisent AddAlias pour ajouter un nouvel alias pour
accéder à un serveur InterBase dans le cadre de la session par défaut :
var
AliasParams: TStringList;
begin
AliasParams := TStringList.Create;
try
with AliasParams do begin
Add('OPEN MODE=READ');
Add('USER NAME=TOMSTOPPARD');
Add('SERVER NAME=ANIMALS:/CATS/PEDIGREE.GDB');
end;
Session.AddAlias('CATS', 'INTRBASE', AliasParams);
...
finally
AliasParams.Free;
end;
end;
L’instruction suivante utilise AddStandardAlias pour créer un nouvel alias pour
accéder à une table Paradox :
AddStandardAlias('MYDBDEMOS', 'C:\TESTING\DEMOS\', 'Paradox');
Les instructions suivantes utilisent ModifyAlias pour provoquer le changement du
paramètre OPEN MODE en READ/ WRITE pour l’alias CATS dans la session
par défaut :
var
List: TStringList;
begin
List := TStringList.Create;
with List do begin
Clear;
Add('OPEN MODE=READ/WRITE');
end;
Session.ModifyAlias('CATS', List);
List.Free;
...
DatabaseCount est une propriété Integer de type entier qui indique le nombre de
bases de données actuellement actives associées à une session. Ce nombre évolue
au fur et à mesure des ouvertures et fermetures de connexions pendant la durée
de la session. Par exemple, si la propriété KeepConnections de la session est à
False et que, lors de l’exécution, tous les composants base de données sont créés
au fur et à mesure des besoins, alors, à chaque fois qu’une nouvelle base de
données est ouverte, DatabaseCount augmente d’une unité. De même, à chaque
fois qu’une base de données est fermée, DatabaseCount diminue d’une unité. Si
DatabaseCount est de valeur nulle, c’est qu’aucun composant base de données
n’est actuellement actif pour la session.
DatabaseCount est généralement utilisée conjointement à la propriété Databases
pour effectuer des actions communes à tous les composants base de données
actifs.
Le code suivant met à True la propriété KeepConnection de chaque base de
données active dans la session par défaut :
var
MaxDbCount: Integer;
begin
with Session do
if (DatabaseCount > 0) then
for MaxDbCount := 0 to (DatabaseCount - 1) do
Databases[MaxDbCount].KeepConnection := True;
end;
var
Passwrd: String;
begin
Passwrd := InputBox('Enter password', 'Password:', '');
Session.AddPassword(Passwrd);
try
Table1.Open
except
ShowMessage('Could not open table!');
Application.Terminate;
end;
end;
La fonction InputBox ci-dessus n'est utilisée qu'à titre de démonstration. Dans une
application réelle, utilisez des utilitaires de saisie de mot de passe qui masquent
le mot de passe lorsqu'il est entré, comme la fonction PasswordDialog ou une fiche
personnalisée. Sur une fiche personnalisée de saisie de mot de passe, utilisez un
composant TEdit en affectant un astérisque ("*") au paramètre PasswordChar.
Le bouton Ajouter de la boîte de dialogue de la fonction PasswordDialog produit
le même effet que la méthode AddPassword.
if PasswordDialog(Session) then
Table1.Open
else
ShowMessage('No password given, could not open table!');
end;
Remarque Il faut appeler AddPassword pour spécifier un ou plusieurs mots de passe à utiliser
(un à la fois) lors de l’accès à des fichiers protégés par mot de passe. Sinon,
lorsque votre application tente d’ouvrir une table Paradox protégée par mot de
passe, une boîte de dialogue demande à l’utilisateur de saisir un mot de passe.
end;
except
TempDatabase.Free;
raise;
end;
end;
Le fragment de code suivant illustre comment cette fonction peut être appelée à
l’exécution afin de créer un composant base de données pour la session par
défaut :
var
MyDatabase: array [1..10] of TDatabase;
MyDbCount: Integer;
begin
{ Initialise MyDbCount ultérieurement }
MyDbCount := 1;
ƒ
{ Puis crée un composant base de données à l’exécution }
begin
MyDatabase[MyDbCount] := RunTimeDbCreate('MyDb' + IntToStr(MyDbCount), '');
Inc(MyDbCount);
end;
ƒ
end;
Utilisation de ODBC
Une application peut utiliser les sources de données ODBC telles que Btrieve.
Une connexion de pilote ODBC nécessite :
• Un pilote ODBC fourni par votre revendeur.
• Le gestionnaire Microsoft de pilote ODBC.
• L’administrateur BDE.
Pour définir un alias BDE pour une connexion de pilote ODBC, utilisez
l’administrateur BDE. Pour plus d’informations, voir le fichier d’aide en ligne de
l’administrateur BDE.
TDataSet
TNestedTable
TClientDataSet TBDEDataSet
TQuery
TDBDataSet TStoredProc
TTable
Tableau 18.1 Valeurs possibles pour la propriété State des ensembles de données
Valeur Etat Signification
dsInactive Inactif L’ensemble de données est fermé. Ses données sont indisponibles.
dsBrowse Visualisation L’ensemble de données est ouvert. Ses données sont
visualisables mais ne peuvent être modifiées. C’est l’état par
défaut d’un ensemble de données ouvert.
dsEdit Edition L’ensemble de données est ouvert. La ligne en cours peut être
modifiée.
dsInsert Insertion L’ensemble de données est ouvert. Une nouvelle ligne peut être
insérée.
dsSetKey Indexation S’applique à TTable et TClientDataSet uniquement. L’ensemble
(SetKey) de données est ouvert. Active la définition de portées et de
valeurs clé pour les opérations portant sur des portées et les
opérations GotoKey.
dsCalcFields Champs L’ensemble de données est ouvert. Indique qu’un événement
calculés OnCalcFields est en cours. Interdit toute modification de champ
(CalcFields) non calculé.
dsCurValue CurValue Utilisation interne uniquement.
dsNewValue NewValue Utilisation interne uniquement.
dsOldValue OldValue Utilisation interne uniquement.
dsFilter Filtrage L’ensemble de données est ouvert. Indique qu’une opération de
filtrage est en cours. Un ensemble de données restreint peut
être visualisé, sans qu’aucune donnée ne puisse être changée.
Cet exemple illustre aussi comment Delphi bascule automatiquement l’état d’un
ensemble de données à dsBrowse quand :
• La méthode Post écrit avec succès un enregistrement dans la base de données.
(Si Post échoue, l’état de l’ensemble de données reste inchangé.)
• La méthode Cancel est appelée.
Certains états ne peuvent être directement définis. Par exemple, pour mettre un
ensemble de données à l’état dsInactive, vous devez basculer sa propriété Active
property à False, ou bien appeler sa méthode Close. Les instructions suivantes
sont équivalentes :
CustTable.Active := False;
CustTable.Close;
Les autres états (dsCalcFields, dsCurValue, dsNewValue, dsOldValue et dsFilter) ne
peuvent être définis par votre application. Par contre, Delphi les définit en
fonction des besoins. Par exemple, dsCalcFields est défini quand l’événement
OnCalcFields d’un ensemble de données est appelé. Lorsque OnCalcFields achève
son exécution, l’ensemble de données revient à son état précédent.
Remarque A chaque fois que l’état d’un ensemble de données change, l’événement
OnStateChange est appelé pour tous les composants source de données associés.
Pour plus d’informations concernant les composants source de données et sur
OnStateChange, voir “Utilisation des sources de données” à la page 25-6.
Les sections suivantes présentent chacun de ces états en indiquant comment ils
sont définis, leurs relations et l’endroit où chercher d’éventuelles informations
complémentaires.
appelle Close, vous devez demander s’il souhaite émettre ou annuler les
modifications en suspens avant sa fermeture. Le code suivant illustre un tel
gestionnaire :
procedure CustTable.VerifyBeforeClose(DataSet: TDataSet)
begin
if (CustTable.State = dsEdit) or (CustTable.State = dsInsert) then
begin
if MessageDlg('Emettre les modifications avant de fermer ?', mtConfirmation, mbYesNo,
0) = mrYes then
CustTable.Post;
else
CustTable.Cancel;
end;
end;
Pour associer une procédure à l’événement BeforeClose d’un ensemble de données
au moment de la conception, accomplissez les étapes suivantes :
1 Sélectionnez la table dans le module de données (ou dans la fiche).
2 Cliquez sur la page Evénements dans l’inspecteur d’objets.
3 Saisissez le nom de la procédure de l’événement BeforeClose (ou choisissez-le
dans la liste déroulante).
Le diagramme suivant illustre les relations entre dsBrowse et les autres modes
que vous pouvez définir pour les ensembles de données dans votre application
ainsi que les méthodes qui définissent ces modes.
Figure 18.3 Relations entre l’état Visualisation et les autres états d’un ensemble de données
dsInactive
Open Close
Insert
Append Edit
dsInsert dsBrowse dsEdit
dsSetKey
Champs calculés
Delphi bascule un ensemble de données en mode dsCalcFields à chaque fois
qu’une application appelle le gestionnaire d’événement OnCalcFields de
l’ensemble de données. Cet état empêche les modifications et les ajouts dans les
enregistrements de l’ensemble de données sauf s’ils s’appliquent aux champs
calculés modifiés par le gestionnaire lui-même. La raison en est que OnCalcFields
utilise les valeurs des autres champs pour dériver celles des champs calculés.
Sinon, les changements des autres champs pourraient invalider les valeurs
affectées aux champs calculés.
Quand ce gestionnaire achève son exécution, l’ensemble de données revient à
l’état dsBrowse.
Pour plus d’informations concernant la création de champs calculés et le
gestionnaire OnCalcFields, voir “Utilisation de l’événement OnCalcFields” à la
page 18-30.
Filtrage d’enregistrements
Delphi met un ensemble de données en mode dsFilter à chaque fois qu’une
application appelle le gestionnaire d’événement OnFilterRecord de l’ensemble de
données. Cet état empêche toute modification ou ajout dans les enregistrements
de l’ensemble de données durant le processus de filtrage afin de ne pas
l’invalider. Pour plus d’informations sur le filtrage, voir “Affichage et édition
d’ensembles de données en utilisant des filtres” à la page 18-19.
Quand le gestionnaire OnFilterRecord, achève son exécution, l’ensemble de
données revient à l’état dsBrowse.
Eof
La valeur True de Eof indique que le curseur se trouve sans équivoque sur la
dernière ligne de l’ensemble de données. EOF passe à True quand une
application :
• Ouvre un ensemble de données vide.
• Appelle la méthode Last de l’ensemble de données.
• Appelle la méthode Next de l’ensemble de données et que son exécution
échoue (car le curseur se trouve déjà sur la dernière ligne de l’ensemble de
données).
• Appelle SetRange sur une portée ou un ensemble de données vide.
Eof vaut False dans tout autre cas ; vous devez supposer que Eof vaut False sauf
si l’une des conditions ci-dessus est vérifiée et que vous avez testé directement la
valeur de la propriété.
Le test sur Eof se fait généralement dans une condition de boucle pour contrôler
le processus itératif sur des enregistrements d’un ensemble de données. Eof vaut
False. si vous ouvrez un ensemble de données contenant plusieurs
enregistrements (ou si vous appelez First). Pour parcourir un à un les
enregistrements d’un ensemble de données, vous devez créer une boucle qui se
termine quand Eof vaut True. A l’intérieur de la boucle, vous devez appeler Next
pour chaque enregistrement de l’ensemble de données. Eof reste à True jusqu’à ce
que Next soit appelée alors que le curseur se trouve déjà sur le dernier
enregistrement.
L’exemple suivant montre l’une des façons de programmer une boucle de
traitement d’enregistrements pour un ensemble de données appelé CustTable :
CustTable.DisableControls;
try
CustTable.First; { Accède au premier enregistrement, ce qui met Eof à False }
while not CustTable.EOF do { Boucle jusqu’à ce qu’Eof soit à True }
begin
{ Le traitement de chaque enregistrement se fait ici }
ƒ
CustTable.Next; { Eof vaut False en cas de réussite et True quand Next échoue sur le
dernier enregistrement }
end;
finally
CustTable.EnableControls;
end;
Astuce Cet exemple montre aussi comment désactiver puis réactiver des contrôles
visuels, orientés données, rattachés à l’ensemble de données. Si vous désactivez
les contrôles visuels pendant la durée de l’itération sur l’ensemble de données, le
traitement sera accéléré car Delphi n’a pas à mettre à jour le contenu des
contrôles au fur et à mesure de l’évolution de l’enregistrement en cours. Une fois
l’itération achevée, les contrôles doivent être réactivés pour être mis à jour en
fonction de la nouvelle ligne en cours. Notez que l’activation de contrôles visuels
a lieu dans la clause finally d’une instruction try...finally. Ceci permet d’être
certain que les contrôles ne resteront pas désactivés, même si une exception
termine le traitement de la boucle de façon prématurée.
Bof
La valeur True de la propriété Bof indique que le curseur se trouve sans
équivoque sur la première ligne de l’ensemble de données. Bof est mis à True
lorsqu’une application :
• Ouvre l’ensemble de données.
• Appelle la méthode First de l’ensemble de données.
• Appelle la méthode Prior de l’ensemble de données et que son exécution
échoue (car le curseur se trouve déjà sur la première ligne de l’ensemble de
données).
• Appelle SetRange sur une portée ou un ensemble de données vide.
Bof vaut False dans tout autre cas ; vous devez supposer que Bof vaut False sauf
si l’une des conditions ci-dessus est vérifiée et que vous avez testé directement la
valeur de la propriété.
Comme Eof , Bof peut se trouver dans une condition de boucle pour contrôler un
processus itératif sur des enregistrements d’un ensemble de données. L’exemple
suivant montre l’une des façons de programmer une boucle de traitement
d’enregistrements pour un ensemble de données appelé CustTable:
CustTable.DisableControls; { accélère le traitement et empêche les rafraîchissements écran
}
try
while not CustTable.BOF do { boucle jusqu’à ce que Bof devienne True }
begin
{ Le traitement de l’enregistrement se fait ici }
ƒ
CustTable.Prior; { Bof vaut False en cas de réussite ;
// Bof vaut True si Prior échoue sur le premier enregistrement }
end;
finally
CustTable.EnableControls; { affiche la ligne courante dans les contrôles }
end;
Marquage d’enregistrements
Outre la possibilité de se déplacer d’un enregistrement à un autre dans un
ensemble de données (ou de se déplacer selon un nombre déterminé
d’enregistrements), il est possible de marquer un emplacement particulier dans
un ensemble de données de façon à y revenir rapidement le moment voulu.
TDataSet et ses descendants implémentent une fonction de définition de signets
qui permet de repérer un enregistrement dans un ensemble de données pour
pouvoir y revenir ultérieurement. Cette fonction se présente sous la forme de la
propriété Bookmark et de cinq méthodes de définition de signets.
La propriété Bookmark indique quel est le signet en cours dans votre application.
Bookmark est une chaîne qui identifie le signet en cours. Tout nouveau signet
ajouté devient le signet en cours.
TDataSet implémente des méthodes virtuelles de gestion des signets. Alors que
ces méthodes garantissent que chaque objet ensemble de données dérivé de
TDataSet renvoie une valeur si une méthode de signet est appelée, les valeurs
renvoyées sont simplement des valeurs par défaut qui n’indiquent pas la
position en cours. Les descendants de TDataSet, comme TBDEDataSet,
réimplémentent les méthodes de signets de façon à ce qu’elles renvoient des
valeurs significatives :
• BookmarkValid permet de déterminer si un signet donné est en cours
d’utilisation.
• CompareBookmarks est utilisée pour tester deux signets et vérifier s’ils sont
identiques.
• GetBookmark alloue un signet en l’associant à la position en cours dans
l’ensemble de données.
• GotoBookmark se positionne sur un signet précédemment créé par GetBookmark
• FreeBookmark restitue un signet qui a été alloué par GetBookmark.
Pour créer un signet, déclarez une variable de type TBookmark dans votre
application, puis appelez GetBookmark pour allouer l’espace de stockage associé
à la variable et définir sa valeur par un emplacement particulier dans l’ensemble
de données. La variable TBookmark est un pointeur (void *).
Avant d’appeler GotoBookmark pour accéder à un enregistrement donné, vous
pouvez appeler BookmarkValid pour déterminer si le signet pointe sur un
enregistrement. BookmarkValid renvoie True si le signet pointe sur un
enregistrement. Dans TDataSet, BookmarkValid est une méthode virtuelle qui
renvoie toujours False pour indiquer que le signet n’est pas correct. Les
descendants de TDataSet réimplémentent cette méthode pour renvoyer une
valeur significative.
CompareBookmarks peut être appelée pour voir si un signet sur lequel vous
voulez vous déplacer est différent d’un autre signet ou du signet en cours.
TDataSet.CompareBookmarks renvoie toujours 0 ; ce qui signifie que les signets ne
sont pas identiques. Les descendants de TDataSet réimplémentent cette méthode
pour renvoyer une valeur significative.
Création de filtres
Les deux méthodes suivantes permettent de créer un filtre pour un ensemble de
données :
• Spécifiez des conditions de filtre dans la propriété Filter. Filter est
particulièrement utile pour créer et appliquer des filtres à l’exécution.
Les valeurs des champs peuvent aussi être comparées à des littérales et à des
constantes en utilisant les opérateurs logiques et les opérateurs de comparaison
suivants :
Tableau 18.4 Opérateurs de comparaison et opérateurs logiques pouvant apparaître dans un filtre
Opérateur Signification
< Inférieur
> Supérieur
>= Supérieur ou égal
<= Inférieur ou égal
= Egal
<> Différent
AND Teste deux instructions qui sont à True
NOT Vérifie que l’instruction suivante n’est pas à True
OR Vérifie qu’au moins une des deux instructions est à True
Par exemple, les instructions suivantes définissent un filtre qui ignore les
différences majuscules/minuscules lors de la comparaison des valeurs d’un
champ State :
FilterOptions := [foCaseInsensitive];
Filter := '''State'' = ''CA''';
Tableau 18.7 Méthodes des ensembles de données pour éditer des données
Méthode Description
Edit Met l’ensemble de données à l’état dsEdit s’il n’est pas déjà à l’état dsEdit ou
dsInsert.
Append Emet les données en suspens, déplace le curseur à la fin de l’ensemble de
données, puis met ce dernier à l’état dsInsert.
Insert Emet les données en suspens, puis met l’ensemble de données à l’état dsInsert.
Post Tente d’émettre l’enregistrement nouveau ou modifié vers la base de données. Si
l’opération réussit, l’ensemble de données est mis à l’état dsBrowse ; dans le cas
contraire, son état en cours reste inchangé.
Cancel Annule l’opération en cours et met l’ensemble de données à l’état dsBrowse.
Delete Supprime l’enregistrement en cours et met l’ensemble de données à l’état
dsBrowse.
Modification d’enregistrements
Un ensemble de données doit être en mode dsEdit pour que l’application puisse
modifier des enregistrements. Dans votre code, vous pouvez utiliser la méthode
Edit pour mettre un ensemble de données en mode dsEdit si la propriété
CanModify de l’ensemble de données, accessible seulement en lecture, est à True.
C’est le cas si les tables sous-jacentes à l’ensemble de données reconnaissent les
droits d’accès en lecture et écriture.
Dans les fiches de votre application, certains contrôles orientés données pourront
mettre automatiquement votre ensemble de données à l’état dsEdit si les
conditions suivantes sont réunies :
• La propriété ReadOnly du contrôle est à False (la valeur par défaut).
• La propriété AutoEdit de la source de données du contrôle est à True.
• La propriété CanModify de l’ensemble de données est à True .
Important Pour les composants TTable dont la propriété ReadOnly vaut True et les
composants TQuery dont la propriété RequestLive vaut False, CanModify est à False
et empêche l’édition des enregistrements.
Remarque Même si un ensemble de données est à l’état dsEdit, la modification
d’enregistrements peut échouer dans le cas d’une base de données SQL si
l’utilisateur de votre application ne dispose pas des droits d’accès SQL appropriés.
Quand un ensemble de données se trouve en mode dsEdit, l’utilisateur peut
modifier toutes les valeurs de champ de l’enregistrement qui apparaît dans les
contrôles orientés données d’une fiche. Les contrôles orientés données, pour
lesquels la modification est activée automatiquement, appellent Post quand
l’utilisateur accomplit une action qui change la position du curseur (comme le
déplacement vers un autre enregistrement dans une grille).
Si vous avez fourni un composant navigateur dans vos fiches, l’utilisateur peut
annuler les modifications en cliquant sur le bouton Annuler du navigateur.
L’annulation des modifications renvoie l’ensemble de données à l’état dsBrowse.
Dans votre code, vous devez valider ou annuler les modifications en appelant les
méthodes appropriées. Les modifications sont validées en appelant Post. Vous
les annulez en appelant Cancel. Les méthodes Edit et Post sont souvent utilisées
conjointement. Considérons l’exemple suivant :
with CustTable do
begin
Edit;
FieldValues['CustNo'] := 1234;
Post;
end;
Dans cet exemple, la première ligne du fragment de code place l’ensemble de
données en mode dsEdit. La ligne suivante affecte la chaîne 1234 au champ
CustNo de l’enregistrement en cours. Pour finir, la dernière ligne écrit (émet)
l’enregistrement vers la base de données.
Remarque Si la propriété CachedUpdates d’un ensemble de données est à True, les
modifications émises sont écrites dans un tampon temporaire. Pour écrire les
modifications en mémoire cache dans la base de données, appelez la méthode
ApplyUpdates de l’ensemble de données. Pour plus d’informations concernant les
mises à jour en mémoire cache, voir chapitre 24, “Manipulation des mises à jour
en mémoire cache.”
Insertion d’enregistrements
Insert ouvre un nouvel enregistrement vide avant l’enregistrement en cours, puis
positionne le curseur sur ce nouvel enregistrement de façon à que les valeurs de
champ puissent être entrées par l’utilisateur ou par le code de votre application.
Quand une application appelle Post (ou ApplyUpdates si les mises à jour en
mémoire cache sont activées), le nouvel enregistrement inséré peut être écrit de
trois façons dans la base de données :
• Pour les tables Paradox ou dBASE indexées, l’enregistrement est inséré dans
l’ensemble de données à une position déterminée par l’index.
• Pour les tables non indexées, l’enregistrement est inséré dans l’ensemble de
données à sa position actuelle.
• Pour les bases de données SQL, l’emplacement physique où a lieu l’insertion
dépend de l’implémentation. Si la table est indexée, l’index est mis à jour avec
les informations du nouvel enregistrement.
Ajout d’enregistrements
Append ouvre un nouvel enregistrement vide à la fin de l’ensemble de données,
en faisant en sorte que l’enregistrement vide devienne l’enregistrement en cours
afin que les valeurs de champ de l’enregistrement puissent être entrées par
l’utilisateur ou par le code de votre application.
Quand une application appelle Post (ou ApplyUpdates si les mises à jour en
mémoire cache sont activées), le nouvel enregistrement ajouté peut être écrit de
trois façons dans la base de données :
• Pour les tables Paradox ou dBASE indexées, l’enregistrement est inséré dans
l’ensemble de données à une position déterminée par l’index.
• Pour les tables non indexées, l’enregistrement est ajouté à la fin de l’ensemble
de données.
• Pour les bases de données SQL, l’emplacement physique où a lieu l’ajout
dépend de l’implémentation. Si la table est indexée, l’index est mis à jour avec
les données du nouvel enregistrement.
Suppression d’enregistrements
Un ensemble de données doit être actif pour que l’application puisse supprimer
des enregistrements. Delete supprime l’enregistrement en cours dans l’ensemble
de données en mettant ce dernier en mode dsBrowse. L’enregistrement qui suit
celui supprimé devient l’enregistrement en cours. Si les mises à jour en mémoire
cache sont activées pour l’ensemble de données, l’enregistrement n’est réellement
supprimé qu’après l’appel de ApplyUpdates.
Si vous avez doté vos fiches d’un composant navigateur, les utilisateurs pourront
supprimer l’enregistrement en cours en cliquant sur le bouton d’effacement.
Dans votre code, vous devez appeler explicitement Delete pour supprimer
l’enregistrement en cours.
Pour une fiche, vous pouvez permettre à l’utilisateur d’annuler les opérations de
modification, d’insertion, et d’ajout en incluant le bouton Annuler dans un
composant navigateur associé à l’ensemble de données, ou bien le code de votre
propre bouton d’annulation.
Si vous utilisez SetFields pour modifier certains champs, et non tous les champs
d’un enregistrement existant, vous pouvez transmettre des valeurs NULL pour
les champs que vous ne voulez pas changer. Si vous ne fournissez pas un
nombre de valeurs correspondant au nombre de champs d’un enregistrement,
SetFields leur affecte la valeur NULL. Les valeurs NULL écrasent les valeurs
existantes de ces champs.
Par exemple, supposons qu’une base de données dispose d’une table COUNTRY
avec les colonnes Name, Capital, Continent, Area et Population. Si un composant
TTable appelé CountryTable, est lié à la table COUNTRY, l’instruction suivante
insère un enregistrement dans la table COUNTRY :
CountryTable.InsertRecord(['Japan', 'Tokyo', 'Asia']);
Cette instruction ne spécifie aucune valeur pour Area et Population, des valeurs
NULL leur sont donc affectées. La table est indexée sur Name, l’enregistrement
est donc inséré à la position alphabétique de “Japan”.
Pour mettre à jour l’enregistrement, l’application peut utiliser le code suivant :
with CountryTable do
begin
if Locate('Name', 'Japan', loCaseInsensitive) then;
begin
Edit;
SetFields(nil, nil, nil, 344567, 164700000);
Post;
end;
end;
Ce code affecte des valeurs aux champs Area et Population, avant de les émettre
dans la base de données. Les trois valeurs NULL agissent comme marqueurs de
remplissage des trois premières colonnes pour indiquer que leur contenu actuel
doit être préservé.
Attention Quand vous utilisez des pointeurs NULL avec SetFields afin de laisser intacte la
valeur de certains champs, il faut transtyper les NULL en void *. Si vous utilisez
un NULL comme paramètre sans effectuer le transtypage, vous affectez une
valeur vierge au champ.
Si AutoCalcFields vaut False, OnCalcFields n’est pas appelé lorsque des champs
individuels sont modifiés dans un enregistrement.
Pendant la durée de l’exécution de OnCalcFields, l’ensemble de données est en
mode dsCalcFields, et vous ne pouvez donc affecter de valeur à un champ que
s’il s’agit d’un champ calculé. L’exécution de OnCalcFields achevée, l’ensemble de
données revient à l’état dsBrowse.
TDataSet
TNestedTable
TClientDataSet TBDEDataSet
TQuery
TDBDataSet TStoredProc
TTable
Tableau 18.10 Propriétés et fonction de TDBDataSet relatives à l’utilisation des bases de données et
des sessions
Fonction ou propriété Utilisation
fonction CheckOpen Détermine si une base de données est ouverte. Renvoie true si la
connexion est active, false sinon.
Database Identifie le composant base de données auquel est associée
l’ensemble de données.
DBHandle Spécifie le handle de base de données BDE du composant base de
données spécifié dans la propriété Database. Utilisé uniquement en
cas d’appel API direct au BDE.
DBLocale Spécifie les informations BDE locales sur le composant base de
données spécifié dans la propriété Database Utilisé uniquement en
cas d’appel API direct au BDE.
DBSession Spécifie le handle de session BDE du composant session spécifié par
la propriété SessionName. Utilisé uniquement en cas d’appel API
direct au BDE.
DatabaseName Spécifie l’alias BDE ou le nom du composant base de données de la
base de données utilisée par cet ensemble de données. Si l’ensemble
de données est une table Paradox ou dBASE, DatabaseName peut
être la spécification complète du chemin d’accès menant au
répertoire de la base de données.
Tableau 18.10 Propriétés et fonction de TDBDataSet relatives à l’utilisation des bases de données et
des sessions (suite)
Fonction ou propriété Utilisation
SessionName Spécifie la session à laquelle est associé ce composant ensemble de
données. Si vous utilisez à la fois des composants base de données
et session avec un ensemble de données, la valeur de SessionName
doit être la même que celle de la propriété SessionName du
composant base de données.
Tableau 18.11 Propriétés, événements et méthodes des mises à jour en mémoire cache
Propriété, événement
ou méthode Utilisation
CachedUpdates (propriété) Détermine si les mises à jour en mémoire cache prennent effet
pour l’ensemble de données. Si la propriété vaut true, la mise à
jour à partir de la mémoire cache est activée. Si elle vaut false,
la mise à jour n’est pas activée.
UpdateObject (propriété) Indique le nom du composant TUpdateSQL utilisé pour mettre
à jour les ensembles de données en fonction de requêtes.
UpdatesPending (propriété) Indique si la mémoire cache locale contient des enregistrements
mis à jour qui doivent être appliqués à la base de données. true
indique que certains enregistrements sont à mettre à jour. false
indique que la mémoire cache est vide.
Tableau 18.11 Propriétés, événements et méthodes des mises à jour en mémoire cache (suite)
Propriété, événement
ou méthode Utilisation
UpdateRecordTypes Indique le type d’enregistrements mis à jour qu’il faut rendre
(propriété) visible à l’application pendant l’application des mises à jour
placées en mémoire cache.
UpdateStatus (méthode) Indique si un enregistrement est inchangé, modifié, inséré ou
supprimé.
OnUpdateError (événement) Procédure créée par le développeur qui gère les erreurs de
mise à jour enregistrement par enregistrement.
OnUpdateRecord Procédure créée par le développeur qui traite les mises à jour
(événement) enregistrement par enregistrement.
ApplyUpdates (méthode) Applique à la base de données les enregistrements contenus
dans la mémoire cache locale.
CancelUpdates (méthode) Supprime de la mémoire cache locale toutes les mises à jour en
suspens sans les appliquer à la base de données.
CommitUpdates (méthode) Efface le contenu de la mémoire cache après application réussie
des mises à jour.
FetchAll (méthode) Copie tous les enregistrements de la base de données dans la
mémoire cache locale pour modification et mise à jour.
RevertRecord (méthode) Annule la mise à jour de l’enregistrement en cours si elle n’a
pas été appliquée côté serveur.
Champs dynamiques
Les composants champ générés dynamiquement correspondent au comportement
par défaut. En fait, tous les composants champ d’un ensemble de données sont
créés dynamiquement à chaque fois que vous placez un ensemble de données
dans un module de données, puis l’associez à une base de données et l’ouvrez.
Un composant champ est dynamique s’il est créé automatiquement. Les
composants champ dynamiques sont créés par Delphi en fonction de la structure
physique sous-jacente des colonnes d’une ou de plusieurs tables connectées à un
ensemble de données. Delphi génère un composant champ pour chaque colonne
des requêtes ou des tables sous-jacentes. Le descendant TField créé pour chaque
colonne d’une table de base de données sous-jacente est déterminé par les
informations de type de champ envoyées par le BDE (Borland Database Engine)
ou par le composant fournisseur (pour les applications multiniveaux).
Le type d’un composant champ détermine ses propriétés et la façon dont les
données qui lui sont associées apparaissent dans les contrôles orientés données
d’une fiche. Les champs dynamiques sont temporaires, leur durée est limitée au
moment où l’ensemble de données est ouvert.
Champs persistants
Par défaut, les champs des ensembles de données sont des champs dynamiques.
Leurs propriétés et leur disponibilité sont automatiquement définies et ne
peuvent pas être modifiées. Pour contrôler les propriétés et les événements d’un
champ de façon à pouvoir définir ou modifier la visibilité du champ ou ses
caractéristiques d’affichage (que ce soit à la conception ou à l’exécution), créer de
nouveaux champs à partir des champs existants dans un ensemble de données
ou valider la saisie des données, vous devez créer des champs persistants.
La boîte de dialogue Ajout de champs se referme et les champs que vous avez
sélectionnés apparaissent dans la boîte liste de l’éditeur de champs ; ce sont les
champs persistants. Si l’ensemble de données est actif, vous remarquerez
également que les boutons de navigation Suivant et Dernier au-dessus de la boîte
liste sont activés.
Désormais, à chaque fois que vous ouvrirez l’ensemble de données, Delphi ne
créera plus de composant champ dynamique pour chaque colonne de la base de
données sous-jacente. Au lieu de cela, il ne créera des composants persistants
que pour les champs spécifiés.
A chaque fois que vous ouvrirez l’ensemble de données, Delphi vérifiera que
chacun des champs persistants non calculés est présent ou qu’il peut être créé à
partir des données de la base. Sinon, il provoquera une exception vous
avertissant que le champ n’est pas valide et n’ouvrira pas l’ensemble de données.
Ces types de champs persistants ne servent que pour l’affichage. Les données
qu’ils contiennent au moment de l’exécution ne sont pas conservées, soit parce
qu’elles existent déjà ailleurs dans la base de données, soit parce qu’elles sont
temporaires. La structure physique de la table et des données sous-jacentes de
l’ensemble de données reste de toute façon inchangée.
Pour créer un nouveau composant champ persistant, cliquez avec le bouton droit
de la souris sur la boîte liste de l’éditeur de champs et choisissez Nouveau
champ. La boîte de dialogue Nouveau champ apparaît.
La boîte de dialogue Nouveau champ contient trois boîtes groupe : Propriétés du
champ, Type de champ et Définition de la référence.
La boîte groupe “Type de champ” vous permet de spécifier le type du nouveau
composant champ à créer. Son type par défaut est Données. Si vous choisissez
Référence, les boîtes de saisie Dataset et Champs clé de la boîte groupe
Définition de la référence sont activées. Il est aussi possible de créer des champs
calculés, et si vous travaillez avec un composant TClientDataSet, vous pouvez
même créer des champs CalcInterne.
La boîte groupe Propriétés du champ vous permet d’entrer des informations
générales sur le composant champ. Tapez le nom de champ du composant dans
la boîte de saisie Nom. Le nom que vous saisissez correspond à la propriété
FieldName du composant champ. C’est ce nom que Delphi utilise pour construire
un nom de composant dans la boîte de saisie Composant. Le nom qui s’y affiche
correspond à la propriété Name du composant champ ; il est fourni uniquement à
titre d’information (Name contient l’identificateur vous permettant de faire
référence au composant champ dans le code source). Delphi ne tient pas compte
de ce que vous entrez directement dans la boîte de saisie Composant.
La boîte à options “Type” vous permet de spécifier le type de données du
composant champ. Vous devez obligatoirement indiquer un type de données
pour chaque nouveau composant champ créé. Par exemple, pour afficher une
valeur monétaire à virgule flottante dans un champ, sélectionnez Currency dans
la liste déroulante. La boîte de saisie Taille vous permet de spécifier le nombre
maximum de caractères pouvant être affichés ou entrés dans un champ chaîne ,
ou bien la taille des champs Bytes et VarBytes. Taille ne s’utilise pour aucun autre
type de données.
La boîte groupe Définition de la référence ne s’utilise que pour créer des champs
de référence. Pour plus de détails, reportez-vous à “Définition d’un champ de
référence” à la page 19-11.
4 Sélectionnez Référence dans la boîte groupe Type de champ pour activer les
boîtes à options Dataset et Champs clé.
5 Choisissez dans la liste déroulante de la boîte à options “Dataset” l’ensemble
de données sur lequel doit porter la recherche des valeurs de champ.
L’ensemble de référence doit être différent de celui du composant champ lui-
même, sinon une exception de référence circulaire sera provoquée au moment
de l’exécution. En spécifiant un ensemble de données de référence, vous
activez les boîtes à options Clés de référence et Champ résultat.
6 Dans la liste déroulante Champs clé, choisissez dans l’ensemble de données
actif le champ dont les valeurs doivent se correspondre. Pour faire
correspondre plusieurs champs, entrez leur nom directement au lieu de les
choisir dans la liste déroulante. Séparez leur nom par des points-virgules. Si
vous utilisez plusieurs champs, il faut employer des composants champ
persistants.
7 Dans la liste déroulante Clés de référence, choisissez un champ de l’ensemble
de données de référence devant correspondre au champ source spécifié à
l’étape 6. Si vous avez spécifié plusieurs champs clé, il faut spécifier le même
nombre de clés de référence. Pour spécifier plusieurs champs, entrez leur nom
directement. Séparez leur nom par des points-virgules.
8 Dans la liste déroulante Champ résultat, choisissez un champ de l’ensemble
de données de référence à renvoyer comme valeur du champ de référence que
vous êtes en train de créer.
Lorsque vous concevez et exécutez votre application, les valeurs des champs de
référence sont déterminées avant celles des champs calculés. Il est possible de
créer des champs calculés basés sur des champs de référence mais il est
impossible de créer des champs de référence basés sur des champs calculés. Ce
comportement peut être affiné avec la propriété LookupCache Cette propriété
détermine si les valeurs d’un champ de référence sont placées en mémoire cache
lors de la première ouverture d’un ensemble de données ou si elles sont
référencées dynamiquement à chaque modification de l’enregistrement en cours
dans l’ensemble de données.
Mettez LookupCache à true pour cacher les valeurs d’un champ de référence
lorsque la propriété LookupDataSet ne risque aucune modification et que le
nombre de valeurs de référence est faible. La mise en mémoire cache des valeurs
de référence permet d’accélérer les performances, car les valeurs de référence
relatives à chaque ensemble de valeurs de la propriété LookupKeyFields sont
préchargées à l’ouverture de l’ensemble de données. En cas de modification de
l’enregistrement en cours dans l’ensemble de données, l’objet champ peut
localiser sa valeur (Value) dans la mémoire cache, plutôt que d’accéder à
LookupDataSet. Cette amélioration des performances est appréciable si l’ensemble
de données de référence (LookupDataSet) est sur un réseau présentant des temps
d’accès lents.
Astuce Vous pouvez utiliser une mémoire cache de référence pour proposer les valeurs
de référence par programme au lieu d’utiliser un ensemble de données
secondaire. Créez un objet TLookupList à l’exécution et utilisez sa méthode Add
pour le remplir avec les valeurs de référence. Affectez cet objet TLookupList à la
propriété LookupList du champ de référence et affectez la valeur true à sa
propriété LookupCache. Si les autres propriétés de référence du champ ne sont pas
initialisées, le champ utilise la liste de référence spécifiée sans redéfinir ses
valeurs avec celles d’un ensemble de données de référence.
Si chaque enregistrement de l’ensemble de données (DataSet) comporte des
valeurs différentes pour KeyFields, le temps nécessaire à la localisation des
valeurs dans le cache peut être supérieur aux gains de temps obtenus grâce au
placement en mémoire cache. Plus le nombre de valeurs distinctes dans KeyFields
est élevé, plus le temps de traitement passé à localiser des valeurs dans la
mémoire cache augmente.
Si LookupDataSet risque de changer, le fait de placer des valeurs de référence en
mémoire cache peut provoquer des résultats erronés. Appelez RefreshLookupList
pour mettre à jour les valeurs dans la mémoire cache. RefreshLookupList régénère
la propriété LookupList qui contient la valeur de la propriété LookupResultField de
chaque ensemble de valeurs LookupKeyFields.
Si LookupCache est définie à l’exécution, appelez RefreshLookupList pour initialiser
la mémoire cache.
Toutes les propriétés ne sont pas disponibles pour l’ensemble des composants
champ. Par exemple, un composant champ de type TStringField ne peut pas
avoir les propriétés Currency, MaxValue ou DisplayFormat et un composant de
type TFloatField ne peut pas avoir de propriété Size.
Alors que le rôle de la plupart des propriétés est évident, certaines comme
Calculated nécessitent des étapes de programmation supplémentaires. D’autres,
comme DisplayFormat, EditFormat et EditMask sont reliées entre elles ; leur
configuration doit être coordonnée. Pour plus de détails sur l’utilisation des
propriétés DisplayFormat, EditFormat et EditMask, voir “Contrôle ou dissimulation
de la saisie utilisateur” à la page 19-18.
Pour contrôler la focalisation des composants orientés données d’un champ, vous
devez recourir à la méthode FocusControl. Celle-ci place la focalisation sur le
premier contrôle orienté données d’une fiche associé à un champ. Un
gestionnaire d’événement doit faire appel à la méthode FocusControl d’un champ
avant de le valider. Le code ci-dessous montre comment faire appel à la méthode
FocusControl pour le champ Company de la table Customers :
CustomersCompany.FocusControl;
Le tableau suivant dresse la liste des autres méthodes des composants champ et
présente leur utilisation. Pour une liste complète des méthodes et des
informations détaillées sur leur utilisation, voir les entrées relatives à TField et
ses descendants dans le Guide de référence de la bibliothèque de composants visuels.
Tableau 19.7 Méthodes des composants champ
Méthode Utilisation
AssignValue Affecte à une valeur de champ une valeur spécifiée en utilisant une
fonction de conversion basée sur le type du champ.
Clear Efface le champ et met sa valeur à NULL.
GetData Extrait du champ des données non formatées.
IsValidChar Détermine si un caractère saisi par un utilisateur dans un contrôle orienté
données dans le but de définir une valeur est autorisé.
SetData Affecte des données “brutes” au champ.
Cette méthode fonctionne bien pour les valeurs chaîne, mais elle peut nécessiter
un surcroît de programmation pour pouvoir gérer les conversions d’autres types
de données. Heureusement, les composants champ ont des fonctions intégrées
leur permettant de le faire.
Remarque Vous pouvez également utiliser des variants pour accéder aux valeurs des
champs et les définir. Les variants sont un nouveau type de données d’une
grande souplesse. Pour plus de détails sur leur utilisation pour accéder aux
valeurs de champ et les définir, reportez-vous à “Accès à des valeurs par la
propriété d’ensemble de données par défaut” à la page 19-23.
TVarBytesField
TSmallintField
TGraphicField
TBooleanField
TIntegerField
TStringField
TMemoField
TBytesField
TWordField
TFloatField
TTimeField
TBlobField
TDateField
TBCDField
Fonction
AsVariant ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
AsString ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓ ✓
AsInteger ✓ ✓ ✓ ✓
AsFloat ✓ ✓ ✓ ✓ ✓ ✓ ✓
AsCurrency ✓ ✓ ✓ ✓ ✓ ✓ ✓
AsDateTime ✓
AsBoolean ✓
Dans les autres cas, la conversion est totalement impossible, toute tentative
provoquant une exception.
Vous pouvez utiliser une fonction de conversion comme n’importe quelle
méthode appartenant à un composant : ajoutez le nom de la fonction à la fin du
nom du composant lorsqu’elle apparaît dans une instruction d’affectation. La
conversion a toujours lieu avant l’affectation. Par exemple, l’instruction ci-
dessous convertit la valeur de CustomersCustNo en chaîne et affecte celle-ci au
texte d’un contrôle de saisie :
Edit1.Text := CustomersCustNo.AsString;
A l’inverse, l’instruction suivante affecte le texte d’un contrôle de saisie au
champ CustomersCustNo en tant qu’entier :
MyTableMyField.AsInteger := StrToInt(Edit1.Text);
Si une conversion non supportée est effectuée lors de l’exécution, cela a pour
effet de provoquer une exception.
Utilisation de contraintes
Les composants champ peuvent utiliser des contraintes de serveur SQL. De plus,
vos applications peuvent créer et utiliser des contraintes personnalisées locales à
l’application. Toutes les contraintes sont des règles ou des conditions qui
définissent et imposent des limites sur un intervalle ou une portée de valeurs
stockées dans un champ. Les sections suivantes décrivent comment les
contraintes peuvent être utilisées avec les composants champ.
20
Manipulation des tables
Chapter 20
Astuce Si votre application utilise des composants base de données pour contrôler les
transactions, attribuez à DatabaseName un alias local défini pour le composant
base de données. Pour obtenir de plus amples informations sur les composants
base de données, reportez-vous au chapitre 17, “Connexion aux bases de
données.”
Tableau 20.1 Types de tables reconnus par le BDE à partir des extensions de fichiers
Extension Type de table
Aucune extension Paradox
.DB Paradox
.DBF dBASE
.TXT texte ASCII
Si vos tables Paradox, dBASE et texte ASCII locales utilisent les extensions
décrites dans le tableau 20.1, vous pouvez laisser la propriété TableType à
ttDefault. Sinon, votre application devra définir TableType de façon à ce qu’elle
indique le type de table approprié. Le tableau 20.2 indique les valeurs pouvant
être affectées à TableType :
Recherche d’enregistrements
Delphi fournit différentes méthodes permettant de rechercher des
enregistrements spécifiques dans une table. Le moyen le plus souple consiste à
utiliser les méthodes génériques Locate et Lookup. Ces méthodes vous permettent
de lancer une recherche sur n’importe quel type de colonne dans n’importe
quelle table, qu’elle soit ou non indexée.
GotoKeyet FindKey sont des fonctions booléennes qui, en cas de réussite, déplacent
le curseur sur un enregistrement correspondant et renvoient True. Si la recherche
n’aboutit pas, le curseur n’est pas déplacé et ces fonctions renvoient False.
GotoNearest et FindNearest provoquent toujours le repositionnement du curseur sur la
première correspondance exacte trouvée ou, si aucune correspondance n’est
trouvée, sur le premier enregistrement supérieur au critère de recherche spécifié.
En ce qui concerne les tables avec des clés multicolonnes, vous ne pouvez
rechercher les valeurs que dans des colonnes contiguës, en commençant par la
première. Par exemple, pour une clé portant sur trois colonnes, vous pouvez
rechercher des valeurs dans la première colonne, puis dans la première et la
seconde, ou bien dans la première, la seconde et la troisième, mais pas seulement
dans la première et la troisième.
Tri d’enregistrements
Un index définit l’ordre d’affichage des enregistrements d’une table. En général,
Delphi les affiche par ordre croissant en fonction d’un index primaire (pour les
tables dBASE sans index primaire, l’ordre de tri dépend de l’ordre physique des
enregistrements). Ce comportement par défaut ne nécessite aucune intervention
de l’application. En revanche, si vous voulez obtenir un ordre de tri différent,
vous devez spécifier :
• Un index alternatif ou secondaire.
• Une liste de colonnes sur lesquelles doit s’opérer le tri (SQL seulement).
Pour spécifier un ordre de tri différent, procédez comme suit :
1 Déterminez les index disponibles.
2 Spécifiez l’index secondaire ou la liste de colonnes à utiliser.
appliquer une portée pour afficher tous les employés dont le nom de famille est
supérieur à “Jones” et inférieur à “Smith”. Du fait que les portées dépendent des
index, elles ne peuvent être appliquées qu’à des champs indexés de tables
Paradox et dBASE (en ce qui concerne les tables SQL, les portées peuvent être
appliquées à tout champ spécifié dans la propriété IndexFieldNames ). Les portées
ne peuvent être définies qu’à partir d’index existants.
Un filtre est composé d’un ensemble d’enregistrements contigus et non contigus
qui partagent les valeurs spécifiées. Supposons que vous souhaitiez appliquer un
filtre sur une base de données d’employés vivant en Californie et ayant travaillé
depuis au moins cinq ans dans l’entreprise. Bien qu’ils utilisent les index lors de
leur application, les filtres ne dépendent pas d’eux. Les filtres sont appliqués
enregistrement par enregistrement au fur et à mesure qu’une application
parcourt un ensemble de données.
En principe, les filtres sont plus souples que les portées. Toutefois, les portées
peuvent être plus efficaces lorsque les ensembles de données sont très grands et
que les enregistrements susceptibles d’intéresser l’application se trouvent déjà
dans des groupes d’index contigus. Pour les très grands ensembles de données, il
est souvent plus efficace d’utiliser une requête pour sélectionner les données à
visualiser et à éditer. Pour plus d’informations sur l’utilisation des filtres, voir
chapitre 18, “Présentation des ensembles de données.” Pour plus d’informations
sur l’utilisation des requêtes, voir chapitre 21, “Manipulation des requêtes.”
d’indiquer les valeurs de début et de fin d’une portée. Dans un tel cas, le code
ci-dessous peut être utilisé pour créer une portée et l’appliquer :
with Customers do
begin
SetRangeStart;
FieldByName('CustNo') := StartVal.Text;
SetRangeEnd;
if EndVal.Text <> '' then
FieldByName('CustNo') := EndVal.Text;
ApplyRange;
end
Ce code vérifie que le texte saisi dans EndVal n’est pas NULL avant d’affecter
des valeurs à Fields. S’il est NULL, tous les enregistrements à partir du début de
la table seront inclus, puisque toutes les valeurs sont supérieures à une valeur
NULL. Par contre, si le texte entré dans EndVal a une valeur NULL, aucun
enregistrement ne sera inclus, puisqu’aucun ne peut être inférieur à cette valeur.
Pour un index à plusieurs colonnes, vous pouvez spécifier une valeur de départ
pour tous les champs de l’index ou pour certains de ces champs. Si aucune
valeur n’est fournie pour l’un des champs utilisé dans l’index, une valeur NULL
est affectée au champ lors de l’application de la portée. Si le nombre de valeurs
défini est supérieur au nombre de champs dans l’index, les champs
supplémentaires sont ignorés lors du calcul de la portée.
Pour mettre fin à la spécification du début de la portée, appelez SetRangeEnd ou
ApplyRange. Ces méthodes sont présentées dans les sections suivantes.
Astuce Pour commencer au début de l’ensemble de données, n’appelez pas
SetRangeStart.
Il est aussi possible de définir les valeurs de début (et de fin) d’une portée en
appelant la procédure SetRange. Pour plus d’informations sur SetRange, voir
“Définition des valeurs de début et de fin de portée” à la page 20-15.
La façon la plus simple d’affecter des valeurs de fin de portée est d’appeler la
méthode FieldByName. Par exemple :
with Table1 do
begin
SetRangeStart;
FieldByName('LastName') := Edit1.Text;
SetRangeEnd;
FieldByName('LastName') := Edit2.Text;
ApplyRange;
end;
Pour un index à plusieurs colonnes, vous pouvez spécifier une valeur de départ
pour tous les champs de l’index ou pour certains de ces champs. Si aucune
valeur n’est fournie pour l’un des champs utilisés dans l’index, une valeur NULL
est affectée au champ lors de l’application de la portée. Si le nombre de valeurs
défini est supérieur au nombre de champs dans l’index, une exception est
provoquée.
Pour mettre fin à la spécification de fin de la portée, appelez ApplyRange. Pour
plus d’informations sur l’application d’une portée, voir “Application d’une
portée” à la page 20-16.
Remarque Il est aussi possible de définir les valeurs de fin (et de début) d’une portée en
appelant la procédure SetRange. Pour plus d’informations sur SetRange, voir la
section suivante.
dialogue demande si vous voulez renommer la table. Vous pouvez alors choisir
de renommer la table ou d’annuler l’opération ce qui modifie la propriété
TableName (par exemple pour créer une nouvelle table) sans modifier le nom de
la table représentée par l’ancienne valeur de TableName.
Pour renommer une table Paradox ou dBASE à l’exécution, appelez la méthode
RenameTable du composant table. Ainsi, l’instruction suivante change le nom de
la table Customer en CustInfo :
Customer.RenameTable(‘CustInfo’);
Par exemple, le code suivant met à jour les enregistrements de la table en cours
à partir des enregistrements de la table Customer :
Table1.BatchMove('CUSTOMER.DB', batUpdate);
BatchMove renvoie le nombre d’enregistrements importés.
Attention L’importation d’enregistrements en utilisant le mode batCopy écrase les
enregistrements existants. Pour préserver ces enregistrements, vous devez plutôt
utiliser batAppend.
Seules quelques fonctions disponibles pour votre application sont directement
effectuées par BatMove par l’intermédiaire du composant TBatchMove. Si vous
devez déplacer une grande quantité de données entre des tables, utilisez le
composant action groupée (TBatchMove) au lieu d’appeler la fonction BatchMove
de la table. Pour plus d’informations sur l’utilisation de TBatchMove, voir la
rubrique suivante, “Utilisation de TBatchMove.”
Utilisation de TBatchMove
TBatchMove encapsule des fonctionnalités du moteur de bases de données
Borland (BDE) qui vous permettent du dupliquer un ensemble de données,
d’ajouter des enregistrements d’un ensemble de données à un autre, de mettre à
jour les enregistrements d’un ensemble de données à partir de ceux d’un autre et
de supprimer dans un ensemble de données les enregistrements existant dans un
autre ensemble de données. TBatchMove est souvent utilisé pour :
• Charger les données d’un serveur dans une source de données locale afin de
les analyser ou d’effectuer d’autres opérations.
• Transférer, dans le cadre d’une opération d’upsizing, une base de données
dans des tables stockées sur un serveur distant.
Le composant action groupée peut créer sur la destination des tables
correspondant aux tables source, en établissant une correspondance automatique
entre les noms de colonne et les types de données.
Si vous créez une table entièrement nouvelle en copiant une table existante, la
table obtenue possède le nom spécifié dans la propriété Name du composant
table vers lequel vous copiez les informations. Le type de table obtenu
présente une structure appropriée au le serveur spécifié par la propriété
DatabaseName.
6 Définissez la propriété Mode pour indiquer le type d’opération à réaliser. Les
opérations possibles sont batAppend (opération par défaut), batUpdate,
batAppendUpdate, batCopy et batDelete. Pour plus d’informations sur ces modes,
voir “Spécification d’un mode d’action groupée” à la page 20-23
7 Facultatif : définissez la propriété Transliterate. Lorsqu’elle est à true (valeur
par défaut), les données caractère sont transcrites du jeu de caractères de
l’ensemble de données Source vers le jeu de caractères de l’ensemble de
données Destination, en cas de différence.
8 Facultatif : définissez une association entre les colonnes à l’aide de la propriété
Mappings. Vous n’avez pas à utiliser cette propriété si vous voulez que l’action
groupée associe chaque colonne en fonction de sa position dans les tables
source et destination. Pour plus d’informations sur les correspondances de
colonnes voir “Etablissement d’une correspondance entre les types de
données” à la page 20-25.
9 Facultatif : définissez les propriétés ChangedTableName, KeyViolTableName et
ProblemTableName. L’action groupée stocke les enregistrements posant
problème dans la table spécifiée par ProblemTableName. Si vous mettez à jour
une table Paradox par une opération action groupée, les violations de clés
seront signalées dans la table spécifiée par KeyViolTableName.
ChangedTableName liste tous les enregistrements modifiés dans la table
destination lors de l’action groupée. Si vous ne spécifiez pas ces propriétés, les
tables d’erreur ne sont ni créées, ni utilisées. Pour plus d’informations sur la
gestion des erreurs, voir “Gestion des erreurs relatives aux actions groupées”
à la page 20-26.
Ajout
Pour ajouter des données, l’ensemble de données destination doit déjà exister. Si
nécessaire le BDE convertit les données à des tailles et des types de donnéess
appropriés à l’ensemble de données destination. Si la conversion n’est pas
possible, une exception est provoquée et les données ne sont pas ajoutées.
Mise à jour
Pour mettre à jour les données, l’ensemble de données destination doit déjà
exister et avoir un index qui permet d’établir la correspondance entre les
enregistrements. Si les champs de l’index primaire sont utilisés pour établir les
correspondances, les enregistrements pour lesquels des champs indexés dans
l’ensemble de données destination correspondent à des champs indexés dans
l’ensemble de données source sont écrasés avec les données source. Si nécessaire,
le BDE convertit les données à des tailles et des types de données appropriés à
l’ensemble de données destination.
Copie
Pour faire une copie de l’ensemble de données source, l’ensemble de données
destination ne doit pas exister. Si c’est le cas, l’opération action groupée
provoque l’écrasement de l’ensemble de données destination par une copie de
l’ensemble de données source.
Si les ensembles de données source et destination sont gérés par des moteurs de
bases de données de types différents, comme, par exemple Paradox et InterBase, le
BDE crée un ensemble de données destination avec une structure aussi proche que
possible de celle de l’ensemble de données source et effectue automatiquement les
conversions de taille et de type de données en cas de besoin.
Remarque TBatchMove ne copie pas les structures de métadonnées comme les index, les
contraintes et les procédures stockées. Vous devez recréer ces objets métadonnées
sur votre serveur de bases de données ou utiliser l’explorateur SQL Explorer.
Suppression
Pour supprimer des données, l’ensemble de données destination doit déjà exister
et avoir un index qui permet d’établir la correspondance entre les
enregistrements. Si les champs de l’index primaire sont utilisés pour établir les
correspondances, les enregistrements pour lesquels des champs indexés dans
l’ensemble de données destination correspondent à des champs indexés dans
l’ensemble de données source sont supprimés dans la table destination.
Remarque Pour exécuter une action groupée sur des données en direction d’une base de
données sur serveur SQL, vous devez avoir installé ce serveur de bases de
données et le logiciel Delphi Suite Client/Serveur ou Entreprise avec le pilote
SQL Link approprié ou utiliser ODBC si les pilotes ODBC des tierces parties sont
installés.
Généralement, les requêtes sont utilisées pour sélectionner les données visibles
par l’utilisateur dans l’application. Elles permettent d’effectuer des opérations de
mise à jour, d’insertion et de suppression. Lorsque vous utilisez une requête
pour effectuer de telles opérations, elle ne renvoie pas les enregistrements à
l’écran (ce qui n’est pas le cas avec les tables).
Pour plus d’informations sur l’utilisation de la propriété SQL et l’écriture
d’instructions SQL, voir “Spécification de l’instruction SQL à exécuter” à la
page 21-6. Pour plus d’informations sur l’utilisation de paramètres dans les
instructions SQL, voir “Définition de paramètres” à la page 21-9. Pour plus
d’informations sur l’exécution d’une requête, voir “Exécution d’une requête” à la
page 21-13.
Pour en savoir plus sur la propriété SQL et l’écriture d’instructions SQL, voir
“Spécification de l’instruction SQL à exécuter” à la page 21-6. Pour plus
d’informations sur l’utilisation de paramètres dans les instructions SQL, voir
“Définition de paramètres” à la page 21-9. Pour plus d’informations sur la
préparation d’une requête, voir “Préparation d’une requête” à la page 21-15, et
pour plus d’informations sur son exécution, voir “Exécution d’une requête” à la
page 21-13.
Remarque Si l’instruction SQL contenue dans le fichier est une requête paramétrée,
définissez les valeurs initiales des paramètres et appelez la méthode Prepare
avant d’ouvrir ou d’exécuter la requête. L’appel explicite de Prepare se justifie si
la même instruction SQL est fréquemment utilisée ; sinon elle est
automatiquement appelée par le composant requête.
Définition de paramètres
Une instruction SQL paramétrée contient des paramètres, ou variables,
susceptibles de changer pendant la conception ou l’exécution. Ils peuvent
remplacer des valeurs de données, comme celles utilisées dans les clauses WHERE
pour les comparaisons. En règle générale, les paramètres sont utilisés pour
représenter des valeurs transmises à l’instruction. Par exemple, dans l’instruction
INSERT ci-dessous, les valeurs à insérer sont transmises en tant que paramètres :
INSERT INTO Country (Name, Capital, Population)
VALUES (:Name, :Capital, :Population)
Dans cette instruction SQL, :name, :capital et :population représentent les valeurs
réelles fournies à l’instruction par votre application au moment de l’exécution.
Pour la première exécution d’une requête paramétrée, votre application doit
appeler la méthode Prepare pour lier les valeurs en cours des paramètres dans
l’instruction SQL. Cette liaison permet au BDE et au serveur d’allouer des
ressources à l’instruction et à ses paramètres afin d’accélérer la vitesse
d’exécution de la requête.
with Query1 do begin
Close;
Unprepare;
ParamByName(‘Name’).AsString := ‘Belize’;
ParamByName(‘Capital’).AsString := ‘Belmopan’;
ParamByName(‘Population’).AsInteger := ‘240000’;
Prepare;
Open;
end;
Cet ensemble de données de recherche doit être créé et défini avant de créer le
composant requête qui l’utilisera. S’il trouve des correspondances, le composant
requête lie les valeurs des paramètres à celles des champs de l’enregistrement en
cours indiqué par la source de données.
La création d’une application simple peut vous permettre de comprendre
comment la propriété DataSource permet de lier une requête dans une fiche
maître-détail. Supposons l’existence d’un module de données appelé LinkModule
et contenant un composant requête appelé OrdersQuery dont la propriété SQL est
définie comme suit :
SELECT CustNo, OrderNo, SaleDate
FROM Orders
WHERE CustNo = :CustNo
Le module de données LinkModule contient également :
• Un composant ensemble de données TTable appelé CustomersTable lié à la table
CUSTOMER.DB.
• Un composant TDataSource appelé OrdersSource. La propriété DataSet de
OrdersSource pointe sur OrdersQuery.
• Un composant TDataSource appelé CustomersSource lié à CustomersTable. La
propriété DataSource du composant OrdersQuery a également la valeur
CustomersSource. C’est elle qui fait d’OrdersQuery une requête liée.
Supposons également que cette application comporte une fiche appelée Requête
liée qui contient deux grilles de données, une grille Customers Table liée à
CustomersSource et une grille Order Query liée à OrdersSource.
La figure suivante montre comment se présente cette application au moment de
la conception.
Figure 21.1 Fiche requête maître-détail et module de données en phase de conception
Manipulation Chapter 22
22
des procédures stockées
Ce chapitre décrit comment utiliser les procédures stockées dans vos applications
de base de données. Une procédure stockée est un programme autonome écrit
dans le langage de la procédure et du déclencheur propre au système de base de
données utilisé. Il existe fondamentalement deux types de procédures stockées.
Le premier type extrait des données (comme dans le cas d’une requête SELECT).
Les données extraites peuvent se présenter sous la forme d’un ensemble de
données composé d’une ou plusieurs lignes de données, elles-mêmes composées
d’une ou plusieurs colonnes. Autre possibilité, les données extraites se présentent
sous la forme d’unités d’information. Le second type ne renvoie pas de données
mais réalise une action sur les données stockées dans la base de données
(comme dans le cas d’une instruction DELETE). Certains serveurs de base de
données gèrent les deux types d’opération dans une même procédure.
Les procédures stockées qui renvoient des données le font de différentes façons,
en fonction de leur composition et de l’utilisation du système de base de
données. Certaines, comme InterBase, renvoient toutes les données (ensembles de
données et unités d’information) uniquement avec des paramètres de sortie.
D’autres peuvent renvoyer un curseur vers les données. D’autres encore, comme
Microsoft SQL Server et Sybase, peuvent renvoyer un ensemble de données et
des unités.
Dans les applications Delphi, l’accès aux procédures stockées est fourni par les
composants TStoredProc et TQuery. Le choix du composant à utiliser dépend du
codage de la procédure stockée, de la façon dont les données éventuelles sont
renvoyées et de l’utilisation du système de base de données. Les composants
TStoredProc et TQuery sont tous les deux des descendants de TDataSet et héritent
leurs comportements de TDataSet. Pour plus d’informations sur TDataSet, voir
chapitre 18, “Présentation des ensembles de données.”
Prenez par exemple le cas d’une application devant calculer une valeur unique,
comme l’écart-type entre des valeurs pour un grand nombre d’enregistrements.
Pour effectuer ce calcul dans votre application, toutes les valeurs utilisées
doivent être extraites du serveur, d’où un accroissement du trafic réseau. Votre
application doit ensuite effectuer les calculs. Comme ce qui vous intéresse, c’est
le résultat final, c’est-à-dire une valeur représentant l’écart-type ; il sera beaucoup
plus efficace qu’une procédure stockée lise les données sur le serveur, effectue
les calculs puis transmette la valeur recherchée à votre application.
Pour plus de détails sur le support des procédures stockées, reportez-vous à la
documentation de votre serveur de base de données.
Remarque Si votre application change les informations relatives aux paramètres lors de
l’exécution (comme lorsque des procédures surchargées Oracle sont utilisées),
vous devez la préparer à nouveau.
Pour exécuter une procédure stockée préparée, faites appel à la méthode
ExecProc du composant procédure stockée. Le code suivant prépare et exécute
une procédure stockée :
StoredProc1.Params[0].AsString := Edit1.Text;
StoredProc1.Prepare;
StoredProc1.ExecProc;
Remarque Si vous tentez d’exécuter une procédure stockée avant qu’elle n’ait été préparée,
le composant procédure stockée le fait automatiquement à votre place, puis
annule sa préparation après son exécution. Si vous envisagez d’exécuter
plusieurs fois une procédure stockée, il est plus efficace d’appeler Prepare vous-
même, puis d’appeler UnPrepare une seule fois, lorsque vous n’avez plus besoin
d’exécuter la procédure.
Lorsque vous exécutez une procédure stockée, elle peut renvoyer une partie ou
l’ensemble des éléments suivants :
• Un ensemble de données composé d’un ou de plusieurs enregistrements
pouvant être visualisés dans des contrôles orientés données associés à la
procédure stockée par l’intermédiaire d’un composant source de données.
• Des paramètres de sortie.
• Un paramètre résultat contenant des informations d’état sur l’exécution de la
procédure stockée.
Pour déterminer les éléments susceptibles d’être renvoyés par une procédure
stockée sur votre serveur, voir la documentation du serveur.
L’accès aux paramètres de procédure stockée est fourni par les objets TParam de
la propriété TStoredProc.Params. Si le nom de la procédure stockée est spécifié à
la conception dans la propriété StoredProcName, un objet TParam est
automatiquement créé pour chaque paramètre et ajouté à la propriété Params. Si
le nom de la procédure stockée n’est spécifié qu’à l’exécution, les objets TParam
doivent être créés par programmation à ce moment là. La non spécification de la
procédure stockée et la création manuelle des objets TParam permet l’utilisation
d’un seul composant TStoredProc avec un nombre quelconque de procédures
stockées disponibles.
Remarque Certaines procédures stockées renvoient un ensemble de données en plus des
paramètres de sortie et du paramètre résultat. Les applications peuvent afficher
des enregistrements d’ensemble de données dans des contrôles orientés données,
mais doivent traiter séparément les paramètres résultat et de sortie. Pour plus
d’informations sur l’affichage des enregistrements dans des contrôles orientés
données, voir “Utilisation de procédures stockées qui renvoient des ensembles de
résultats” à la page 22-6.
Liaison de paramètres
Lorsque vous préparez et exécutez une procédure stockée, ses paramètres
d’entrée sont automatiquement liés aux paramètres du serveur.
La propriété ParamBindMode permet de déterminer la façon dont les paramètres
de votre composant procédure stockée doivent être liés aux paramètres du
serveur. Par défaut la propriété ParamBindMode vaut pbByName, ce qui signifie
que les paramètres du composant procédure stockée sont mis en correspondance
avec ceux du serveur d’après leur nom. C’est la méthode la plus simple pour lier
des paramètres.
Certains serveurs supportent également la liaison de paramètres d’après leur
valeur ordinale, l’ordre dans lequel les paramètres apparaissent dans la
procédure stockée. Dans ce cas, l’ordre dans lequel les paramètres sont spécifiés
dans l’éditeur de collection de paramètres est important. Le premier paramètre
spécifié est mis en correspondance avec le premier paramètre d’entrée sur le
serveur, le deuxième paramètre est mis en correspondance avec le deuxième
paramètre sur le serveur, et ainsi de suite. Si votre serveur supporte la liaison de
paramètres d’après leur valeur ordinale, vous pouvez attribuer la valeur
pbmByNumber à la propriété ParamBindMode.
Astuce Si vous attribuez la valeur pbByNumber à la propriété ParamBindMode, vous devez
spécifier les bons types de paramètres dans un ordre correct. Il est possible de
visualiser le code source de la procédure stockée d’un serveur dans l’explorateur
SQL afin de déterminer si l’ordre et le type des paramètres sont corrects.
Remarque Les serveurs Informix ne renvoient pas d’informations sur les types de données.
Utilisez l’explorateur SQL pour déterminer ces informations. Utilisez
l’explorateur SQL ou les utilitaires du constructeur du serveur pour déterminer
ces informations.
Pour plus d’informations sur la définition des valeurs des paramètres, voir
“Définition des informations sur les paramètres à la conception” à la page 22-15.
Remarque Il n’est pas possible de définir les valeurs des paramètres de sortie et des
paramètres résultat. Les valeurs de ces types de paramètres sont définies par
l’exécution de la procédure stockée.
Ces mécanismes peuvent être combinés dans une même application qui utilise le
modèle “briefcase”. Les utilisateurs prennent un cliché des données en les
enregistrant dans un fichier linéaire afin de pouvoir les manipuler “off-line”.
Ultérieurement, l’application client applique les modifications depuis la copie
locale des données vers le serveur d’applications. Ce dernier applique ensuite les
modifications dans la base de données réelle et renvoie les erreurs à l’ensemble
de données client afin qu’elles soient traitées. Pour plus d’informations sur la
construction d’une application avec le modèle “briefcase”, voir “Utilisation du
modèle “briefcase”” à la page 14-17.
Tri et indexation
L’utilisation d’index présente plusieurs avantages pour vos applications :
• Ils permettent aux ensembles de données client de localiser les données
rapidement.
• Ils permettent à votre application de définir des relations entre les ensembles
de données clients, telles que des tables de référence ou des fiches maître/
détail.
• Ils spécifient l’ordre dans lequel les enregistrements apparaissent.
Si un ensemble de données client est utilisé dans une application multiniveau, il
hérite d’un index par défaut et d’un ordre de tri basés sur les données qu’il
reçoit du serveur d’applications. L’index par défaut s’appelle DEFAULT_ORDER.
Il est possible d’utiliser ce classement, mais il est impossible de modifier ou de
supprimer l’index.
En plus de l’index par défaut, l’ensemble de données client gère un deuxième
index, appelé CHANGEINDEX, à partir des enregistrements stockés dans le
journal de modifications (propriété Delta). CHANGEINDEX classe tous les
enregistrements de l’ensemble de données tels qu’ils apparaîtraient si les
modifications de Delta étaient appliquées. CHANGEINDEX est basé sur l’ordre
qu’il a hérité de DEFAULT_ORDER. Comme pour DEFAULT_ORDER, il est
impossible de modifier ou de supprimer l’index CHANGEINDEX.
Vous pouvez utiliser d’autres index existants d’un ensemble de données ou créer
vos propres index. Les sections suivantes décrivent comment créer et utiliser des
index avec des ensembles de données client.
Indexation à la volée
Au lieu de créer un index faisant partie de l’ensemble de données client, vous
pouvez créer à la volée un index temporaire en spécifiant les champs à utiliser
dans la propriété IndexFieldNames. Les noms de champs à utiliser doivent être
séparés par des points virgules. La position des champs dans la liste est
déterminante.
Remarque Quand l’indexation est effectuée à la volée, il n’est pas possible de spécifier un
index en ordre décroissant ou ne tenant pas compte des différences majuscule/
minuscule.
Note Les index créés à la volée ne supportent pas le regroupement.
Spécification d’agrégats
Pour spécifier que vous voulez opérer des calculs synthétiques à partir des
enregistrements d’un ensemble de données client, utilisez la propriété Aggregates.
Aggregates est un ensemble de spécifications d’agrégat (TAggregate). Vous pouvez
ajouter des spécifications d’agrégat à votre ensemble de données client à l’aide
de l’éditeur de collection lors de la conception ou de la méthode Add de
Aggregates à l’exécution. Si vous souhaitez créer des composants champ pour les
agrégats, créez des champs persistants pour les valeurs synthétisées dans
l’éditeur de champs.
Remarque Lorsque vous créez des champs synthétisés, les objets agrégat appropriés sont
automatiquement ajoutés à la propriété Aggregates de l’ensemble de données
client. Ne les ajoutez-pas de façon explicite lors de la création des champs
persistants synthétisés.
Pour chaque agrégat, la propriété Expression indique le calcul synthétique qu’elle
représente. Expression peut contenir une simple expression synthétique telle que
Sum(Field1)
ou une expression complexe qui combine les informations de plusieurs champs,
telle que
Sum(Qty * Price) - Sum(AmountPaid)
Les expressions d’agrégat incluent un ou plusieurs opérateurs de synthèse du
tableau 23.1
Les opérateurs de synthèse portent sur des valeurs de champ ou sur des
expressions conçues à partir de valeurs de champ à l’aide des mêmes opérateurs
que ceux utilisés pour la création de filtres. (vous ne pouvez pas, toutefois,
imbriquer des opérateurs de synthèse.) Vous pouvez créer des expressions avec
des opérateurs à partir de valeurs synthétisées ou de valeurs synthétisées et de
constantes. Toutefois, vous ne pouvez pas combiner des valeurs synthétisées et
des valeurs de champ, car de telles expressions sont ambiguës (rien n’indique
quel enregistrement doit fournir la valeur de champ.) Ces règles sont illustrées
dans les expressions suivantes :
Le code suivant définit un agrégat maintenu qui indique le montant total des
ventes réalisé par chaque représentant :
Agg.Expression := ’Sum(Amount)’;
Agg.IndexName := ’SalesCust’;
Agg.GroupingLevel := 1;
Agg.AggregateName := ’Total for Rep’;
Pour ajouter un agrégat qui synthétise chaque client pour un représentant donné,
créez un agrégat maintenu de niveau 2.
Les agrégats maintenus qui synthétisent un groupe d’enregistrements sont
associés à un index spécifique. La propriété Aggregates peut inclure des agrégats
qui utilisent différents index. Toutefois, seuls les agrégats qui synthétisent la
totalité de l’ensemble de données client et ceux qui utilisent l’index en cours sont
valides. La modification de l’index en cours détermine les agrégats qui sont
valides. Pour déterminer les agrégats valides à un moment donné, utilisez la
propriété ActiveAggs.
Remarque Vous pouvez initialiser les valeurs de paramètre à partir des paramètres en cours
sur le serveur d’applications. Pour ce faire, lors de la conception, cliquez avec le
bouton droit sur l’ensemble de données client et choisissez Analyser Params ou,
à l’exécution, appelez la méthode FetchParams.
Tableau 23.2 Propriétés et méthodes des ensembles de données client pour la gestion des extractions
de données
Propriété ou méthode Utilisation
FetchOnDemand Détermine si un ensemble de données client extrait
(propriété) automatiquement les données au fur et à mesure des besoins,
ou s’il compte sur l’application pour appeler la fonction
GetNextPacket, FetchBlobs et FetchDetails de l’ensemble de
données client afin d’extraire des données supplémentaires.
PacketRecords (propriété) Spécifie le type ou le nombre d’enregistrements à renvoyer dans
chaque paquet de données.
Tableau 23.2 Propriétés et méthodes des ensembles de données client pour la gestion des extractions
de données (suite)
Propriété ou méthode Utilisation
GetNextPacket (méthode) Extrait le paquet de données suivant du serveur d’applications.
FetchBlobs (méthode) Extrait tous les champs BLOB de l’enregistrement en cours
lorsque le serveur d’applications n’inclut pas de données BLOB
automatiquement.
FetchDetails (méthode) Extrait les ensembles de données détail imbriqués de
l’enregistrement en cours lorsque le serveur d’applications ne
les inclut pas automatiquement dans des paquets de données.
SaveToFile accepte un paramètre : une chaîne qui spécifie le fichier dans lequel les
données sont écrites (le cas échéant, le nom de fichier peut être un nom de
chemin d’accès qualifié). Si le fichier existe déjà, son contenu actuel est écrasé.
Si vous sauvegardez toujours les données dans le même fichier, vous pouvez
utiliser la propriété FileName . Si FileName est initialisée, les données sont
automatiquement sauvegardées dans le fichier nommé à la fermeture de
l’ensemble de données client.
Vous pouvez aussi sauvegarder les données dans un flux à l’aide de la méthode
SaveToStream. SaveToStream accepte un paramètre : un objet flux qui reçoit les
données.
Remarque Si vous sauvegardez un ensemble de données client alors que des modifications
existent encore dans le journal de modifications, ces modifications ne sont pas
fusionnées avec les données. Lorsque vous rechargez les données à l’aide de la
méthode LoadFromFile ou LoadFromStream, Ce point est important pour les
applications qui supportent le modèle “briefcase”, dans lequel les modifications
finissent par être appliquées à un composant fournisseur sur le serveur
d’applications.
Remarque SaveToFile ne conserve aucun index ajouté à l’ensemble de données client.
Alors que les mises à jour en mémoire cache peuvent minimiser la durée des
transactions et réduire considérablement le trafic réseau, elles ne sont pas
appropriées à toutes les applications client de bases de données Delphi
fonctionnant sur des serveurs distants. Les trois considérations suivantes doivent
être prises en compte avant de décider d’utiliser les mises à jour en mémoire
cache :
• Les données en mémoire cache sont locales à votre application et ne sont
pas sous contrôle transactionnel. Dans un environnement client/serveur à fort
trafic, cela implique les situations suivantes :
• les autres applications peuvent modifier les données réelles sur le serveur
pendant que vos utilisateurs éditent leur version locale des données ;
• les autres applications ne peuvent pas voir les modifications effectuées par
la vôtre tant qu’elles n’ont pas été appliquées.
• Dans une relation maître/détail, il peut être compliqué de gérer l’ordre
d’application des mises à jour en mémoire cache. C’est surtout le cas pour
les relations maître/détail imbriquées dans lesquelles une table détail est la
table maître d’une autre table détail et ainsi de suite.
• L’application des mises à jour en mémoire cache à des ensembles de
données en lecture seule basés sur des requêtes nécessite l’utilisation
d’objets mise à jour.
Delphi fournit des méthodes de mise à jour en mémoire cache et de contrôle des
transactions que vous pouvez introduire dans le code de votre application afin
de gérer ces situations ; toutefois, vous devez veiller à couvrir tous les scénarios
que votre application est susceptible de rencontrer dans votre environnement de
travail.
Pour utiliser les mises à jour en mémoire cache, CachedUpdates doit avoir la
valeur True, soit au moment de la conception (via l’inspecteur d’objets), soit à
l’exécution. Lorsque vous mettez CachedUpdates à True, l’événement
OnUpdateRecord de l’ensemble de données est déclenché s’il existe. Pour plus
d’informations sur l’événement OnUpdateRecord, voir “Création d’un gestionnaire
d’événement OnUpdateRecord” à la page 24-26.
Par exemple, le code ci-dessous active les mises à jour en mémoire cache pour
un ensemble de données :
CustomersTable.CachedUpdates := True;
Lorsque vous activez les mises à jour en mémoire cache, une copie de tous les
enregistrements est placée (ou cachée) dans la mémoire locale. C’est cette copie
des données que les utilisateurs voient et éditent. Les modifications, les
insertions et les suppressions sont aussi placées en mémoire cache. Elles
s’accumulent en mémoire jusqu’à ce que la mémoire cache en cours des
modifications soit appliquée à la base de données. Si les enregistrements
modifiés sont appliqués avec succès dans la base de données, l’enregistrement
contenant ces modifications dans la mémoire cache est libéré.
Remarque L’application des mises à jour en mémoire cache ne provoque pas la
désactivation des mises à jour suivantes. Elle ne fait qu’écrire les modifications
en cours et entraîne leur effacement de la mémoire.
Pour désactiver les mises à jour en mémoire cache pour un ensemble de
données, donnez à CachedUpdates la valeur False. Si vous désactivez les mises à
jour en mémoire cache avant d’appliquer les modifications en suspens, ces
dernières sont supprimées sans notification. Votre application peut tester la
propriété UpdatesPending avant de désactiver les mises à jour en mémoire cache.
Par exemple, le code ci-dessous demande confirmation avant de désactiver les
mises à jour en mémoire cache pour un ensemble de données :
if (CustomersTable.UpdatesPending)
if (Application.MessageBox(“Annuler mises à jour en suspens?”,
“Modifications non validées”,
MB_YES + MB_NO) = IDYES) then
CustomersTable.CachedUpdates = False;
Extraction d’enregistrements
Si les mises à jour en mémoire cache sont activées, les ensembles de données
BDE gèrent par défaut l’extraction automatique des données d’une base de
données en fonction des besoins. Delphi extrait suffisamment d’enregistrements
pour l’affichage. Lors du traitement, de nouvelles extractions peuvent se
produire. Si votre application a des besoins spécifiques, elle peut extraire tous les
enregistrements à la fois en appelant la méthode FetchAll de l’ensemble de
données. FetchAll crée en mémoire une copie locale de tous les enregistrements
de l’ensemble de données. Si un ensemble de données contient beaucoup
d’enregistrements ou des enregistrements comportant des champs BLOB
volumineux, il n’est pas recommandé d’utiliser FetchAll.
Remarque L’appel à CancelUpdates ne désactive pas les mises à jour en mémoire cache. Il ne
fait que désactiver les mises à jour en suspens. Pour désactiver les futures mises
à jour en mémoire cache, mettez la propriété CachedUpdates à False.
de données. La propriété DataSet des objets mise à jour n’est pas disponible lors
de conception dans l’inspecteur d’objets. Vous pouvez uniquement définir cette
propriété à l’exécution.
UpdateSQL1.DataSet := Query1;
Les instructions SQL de mise à jour contenues dans l’objet mise à jour ne sont
pas automatiquement exécutées lorsque la méthode ApplyUpdates de l’ensemble
de données de mise à jour est appelée. Pour mettre à jour les enregistrements,
vous devez fournir un gestionnaire pour l’événement OnUpdateRecord du
composant ensemble de données et appeler la méthode ExecSQL ou Apply de
l’objet mise à jour. Cela appelle l’objet mise à jour pour chaque enregistrement
qui doit être mis à jour.
Dans le gestionnaire d’événement OnUpdateRecord de l’ensemble de données, les
actions minimales que vous devez réaliser sont les suivantes :
• Appeler la méthode SetParams de l’objet mise à jour (si vous appelez
ultérieure ExecSQL).
• Exécuter l’objet mise à jour pour l’enregistrement en cours avec ExecSQL ou
Apply.
• Attribuer au paramètre UpdateAction du gestionnaire d’événement la valeur
uaApplied.
Vous pouvez, si vous le souhaitez, procéder à la validation de données, à la
modification de données ou à la réalisation d’autres tâches liées à la mise à jour
de chaque enregistrement.
Remarque Vous pouvez aussi associer un objet mise à jour à l’ensemble de données à l’aide
de la propriété UpdateObject du composant ensemble de données et les suivants à
l’aide de leur propriété DataSet. Le premier objet mise à jour est
automatiquement exécuté lors de l’appel de la méthode ApplyUpdates du
composant ensemble de données. Les autres doivent être exécutés manuellement.
Important N’oubliez pas que les instructions SQL générées ne sont qu’un point de départ
pour créer les instructions de mise à jour. Il est parfois nécessaire de les modifier
pour qu’elles s’exécutent correctement. Ainsi, pour travailler avec des données
contenant des valeurs NULL, il peut être nécessaire de modifier la clause
WHERE pour obtenir :
WHERE field IS NULL
au lieu d’utiliser la variable champ générée. Testez chaque instruction générée
avant de la valider.
Pour passer d’un type d’instruction SQL généré à un autre et l’éditer, utilisez les
boutons radio Type d’instruction.
Pour accepter les instructions et les associer aux propriétés SQL du composant
mise à jour, cliquez sur OK.
Utilisez une valeur entière comme index pour référencer une ligne donnée dans
la propriété. Les propriétés DeleteSQL, InsertSQL et ModifySQL sont accessibles
lors de la conception et à l’exécution.
with UpdateSQL1.DeleteSQL do begin
Clear;
Add(‘DELETE FROM Inventory I’);
Add(‘WHERE (I.ItemNo = :OLD_ItemNo)’);
end;
Ci-après, la troisième ligne d’une instruction SQL est modifiée à l’aide d’un
index de valeur 2 pour la propriété ModifySQL.
UpdateSQL1.ModifySQL[2] := ‘WHERE ItemNo = :ItemNo’;
Remarque Cet exemple part du principe que la propriété ModifySQL du composant mise à
jour se présente comme suit :
UPDATE EmpAudit
SET EmpNo = :EmpNo, Salary = :Salary, Changed = :DateChanged
WHERE EmpNo = :OLD_EmpNo
Dans cet exemple, l’appel à SetParams fournit des valeurs aux paramètres EmpNo
et Salary. Le paramètre DateChanged n’est pas défini parce que son nom ne
correspond pas à celui d’un champ de l’ensemble de données ; de ce fait, la ligne
de code suivante définit cette valeur explicitement.
Les contrôles de données doivent être placés sur les fiches de votre application
de base de données après avoir été sélectionnés sur la page ContrôleBD de la
palette des composants. Les contrôles orientés données vous permettent
généralement d’afficher et d’éditer des champs associés à l’enregistrement en
cours d’un ensemble de données. Le tableau 25.1 dresse la liste des contrôles de
données apparaissant sur la page ContrôleBD de la palette des composants.
Propriété DataSet
La propriété DataSet spécifie l’ensemble de données qui fournit les données au
composant source de données. Généralement, les ensembles de données sont
sélectionnés lors de la conception à partir de la liste déroulante de l’inspecteur
d’objets. A l’exécution, vous pouvez changer l’ensemble de données d’un
composant source de données en fonction des besoins. Le code suivant fait
permuter l’ensemble de données entre Customers et Orders pour le composant
source de données CustSource :
with CustSource do
begin
if DataSet = 'Customers' then
DataSet := 'Orders'
else
DataSet := 'Customers';
end;
Vous pouvez aussi définir la propriété DataSet avec un ensemble de données se
trouvant sur une autre fiche afin de synchroniser les contrôles de données des
deux fiches. Par exemple :
procedure TForm2.FormCreate (Sender : TObject);
begin
DataSource1.Dataset := Form1.Table1;
end;
Propriété Name
La propriété Name sert à donner un nom à un composant source de données de
façon à le distinguer des autres sources de données dans votre application. Dans
un module de données, le nom attribué au composant source de données
s’affiche sous son icône.
Généralement, le nom affecté au composant source de données doit donner une
indication sur l’ensemble de données auquel il est associé. Supposons un
ensemble de données, appelé Clients, auquel vous rattachez un composant source
de données en affectant “Clients” à la propriété DataSet du composant source de
données. Pour mettre en évidence la connexion entre l’ensemble de données et la
source dans le module de données, il est souhaitable de définir la propriété Name
de la source avec une valeur comme “SourceClients”.
Propriété Enabled
La propriété Enabled détermine si le composant source de données est connecté
à l’ensemble de données qui lui est associé. La source de données est
effectivement connectée quand Enabled est à True.
Vous pouvez temporairement déconnecter une source de données unique de son
ensemble de données en basculant Enabled à False. Si la valeur de la propriété
Enabled vaut False, tous les contrôles orientés données rattachés au composant
source sont vidés et deviennent inactifs jusqu’à ce que Enabled bascule une
nouvelle fois à True. Toutefois, il est recommandé de contrôler l’accès à un
ensemble de données via ses méthodes DisableControls et EnableControls car elles
agissent sur toutes les sources de données rattachées.
Propriété AutoEdit
La propriété AutoEdit de TDataSource indique si les ensembles de données
connectés à la source de données passent automatiquement en mode édition
quand l’utilisateur débute une frappe de touches dans un contrôle orienté
données lié à l’ensemble de données. Si AutoEdit est à True (la valeur par
défaut), Delphi bascule automatiquement l’ensemble de données en mode édition
quand l’utilisateur commence une frappe de touches dans un contrôle orienté
données lié. Sinon, l’ensemble de données ne passe en mode édition que si
l’application appelle explicitement sa méthode Edit. Pour plus d’informations
concernant les états d’un ensemble de données, voir “Détermination et définition
des états d’un ensemble de données” au chapitre 18, “Présentation des ensembles
de données.”
Evénement OnDataChange
OnDataChange est appelé quand le curseur se déplace sur un nouvel
enregistrement. Quand l’application appelle Next, Previous, Insert ou toute autre
méthode qui provoque le changement de position du curseur, un événement
OnDataChange est déclenché.
Cet événement est utile si une application synchronise manuellement des
composants.
Evénement OnUpdateData
OnUpdateData est appelé quand les données dans l’enregistrement en cours
sont sur le point d’être mises à jour. Par exemple, un événement OnUpdateData
se produit après un appel à Post , mais aussi avant que les données ne soient
effectivement émises dans la base de données.
Cet événement est utile si une application utilise un contrôle standard (non
orienté données) et qu’elle doit assurer sa synchronisation avec un ensemble de
données.
Evénement OnStateChange
OnStateChange est appelé quand l’état d’un ensemble de données associé à la
source de données change. La propriété State d’un ensemble de données sert à
mémoriser son état actuel. OnStateChange peut servir pour accomplir des actions
au fur et à mesure qu’évolue l’état d’un composant TDataSource.
Par exemple, l’état d’un ensemble de données change fréquemment dans le cadre
habituel d’une session de base de données. Pour suivre ces changements, vous
pourriez écrire un gestionnaire d’événement OnStateChange qui affiche l’état en
cours de l’ensemble de données dans le libellé d’une fiche. Le code suivant
illustre l’une des manières possibles de programmer une telle routine. A
l’exécution, ce code affiche le paramétrage en cours de la propriété State de
l’ensemble de données en mettant à jour l’affichage à chaque fois qu’il change :
procedure TForm1.DataSource1.StateChange(Sender:TObject);
var
S:String;
begin
case CustTable.State of
dsInactive: S := 'Inactive';
dsBrowse: S := 'Browse';
dsEdit: S := 'Edit'; dsInsert: S := 'Insert';
dsSetKey: S := 'SetKey';
end;
CustTableStateLabel.Caption := S;
end;
De façon similaire, OnStateChange peut être utilisé pour activer ou désactiver des
boutons ou des éléments de menu selon l’état en cours :
procedure Form1.DataSource1.StateChange(Sender: TObject);
begin
CustTableEditBtn.Enabled := (CustTable.State = dsBrowse);
CustTableCancelBtn.Enabled := CustTable.State in [dsInsert, dsEdit, dsSetKey];
...
end;
les informations sur la rue, la ville et le département dans la fiche, vous utilisiez
une référence dynamique pour déterminer automatiquement le contenu du
champ code postal depuis une table distincte. Un composant TDBText relié à la
table des codes postaux permettra d’afficher le champ code postal correspondant
à l’adresse entrée par l’utilisateur.
TDBText extrait le texte affiché du champ spécifié dans l’enregistrement en cours
d’un ensemble de données. De ce fait, le texte affiché est dynamique, c’est-à-dire
qu’il change au fur et à mesure que l’utilisateur navigue dans la table. Pour cette
raison, il ne vous est pas possible de spécifier le texte d’affichage de TDBText
gets au moment de la conception comme c’est le cas pour les composants TLabel
et TStaticText
Remarque Lorsque vous placez un composant TDBText sur une fiche, vérifiez que sa
propriété AutoSize est à True (la valeur par défaut) ; vous garantissez ainsi que
le contrôle se redimensionne automatiquement pour afficher des données de
largeur variable. Si AutoSize est à False et le contrôle trop étroit, les données
affichées seront tronquées.
Tableau 25.3 Contrôles boîte à options et boîte liste orientés données (suite)
Contrôle de données Description
TDBLookupComboBox Combine une boîte de saisie et une boîte liste. L’utilisateur peut
mettre à jour un champ de l’enregistrement en cours en choisissant
une valeur dans la liste déroulante ou en la saisissant. La liste des
éléments affichés est référencée dans un autre ensemble de données.
Indicateur
d’enregistrement
Par exemple, la source par défaut d’un libellé de colonne est la propriété
DisplayLabel du champ associé. Si vous modifiez la propriété DisplayLabel, le titre
de colonne reflète immédiatement ce changement.
Dès que vous affectez une valeur à une propriété de colonne, elle ne change plus
même si sa source par défaut change. Par exemple, si vous affectez une chaîne
au libellé de la colonne, le titre de la colonne est indépendant de la propriété
DisplayLabel du champ associé. Les modifications de la propriété DisplayLabel du
champ ne sont plus reportées dans le titre de la colonne.
Les colonnes persistantes sont indépendantes des composants champ qui leur
sont associés. De plus, il n’est pas nécessaire d’associer les colonnes persistantes
à des objets champ. Si la propriété FieldName d’une colonne persistante est vide,
ou si le nom du champ ne correspond à aucun champ dans l’ensemble de
données actif dans la grille, la propriété Field de la colonne est NULL et la
colonne est dessinée avec des cellules vides. Vous pouvez utiliser une colonne
vide pour afficher des bitmaps ou des histogrammes représentant les données
d’un enregistrement dans une cellule spécifique, par exemple. Pour ce faire, vous
devez surcharger la méthode de dessin par défaut de la cellule.
Il est possible d’associer une ou plusieurs colonnes persistantes au même champ
d’un ensemble de données. Par exemple, vous pouvez afficher un champ
contenant une référence d’article à droite et à gauche d’une large grille pour
faciliter la recherche d’une référence en évitant à l’utilisateur de faire défiler la
grille.
Remarque Etant donné que les colonnes persistantes n’ont pas besoin d’être associées à un
champ d’un ensemble de données, et étant donné que plusieurs colonnes
peuvent référencer le même champ, la valeur de la propriété FieldCount d’une
grille personnalisée peut être inférieure ou égale au nombre de colonnes d’une
grille. Notez également que si la colonne sélectionnée dans la grille personnalisée
n’est pas associée à un champ, la propriété SelectedField de la grille est NULL et
la propriété SelectedIndex est à –1.
Les colonnes persistantes peuvent être configurées pour afficher des cellules de
grille sous forme de liste déroulante dans une boîte à options de valeurs de
référence provenant d’un autre ensemble de données ou d’une liste de choix
statique, ou sous forme d’un bouton à points de suspension (…) dans une
cellule, sur laquelle l’utilisateur peut cliquer pour lancer des visionneurs de
données spéciaux ou des boîtes de dialogue en relation avec la cellule en cours.
Pour définir les propriétés d’une colonne, sélectionnez la colonne dans l’éditeur
de colonnes et définissez ses propriétés dans l’inspecteur d’objets. Le tableau
suivant dresse la liste des propriétés de colonne pouvant être définies.
Tableau 25.7 Propriétés relatives à l’affichage des champs ADT et tableau dans un composant TDBGrid
Propriété Objet Fonction
Expandable TColumn Spécifie si la colonne peut être étendue pour afficher les
champs enfants dans des colonnes séparées et modifiables.
Expanded TColumn Spécifie si la colonne est étendue.
MaxTitleRows TDBGrid Spécifie le nombre maximum de lignes de titre pouvant
apparaître dans la grille.
ObjectView TDataSet Spécifie si les champs apparaissent aplanis, ou dans un mode
objet, où chaque champ objet peut être développé et réduit.
ParentColumn TColumn Fait référence à l’objet TColumn auquel appartient la
colonne du champ enfant.
Les figures 25.3 et 25.4 montrent la grille avec un champ ADT et un champ
tableau. La figure 25.3 montre les champs réduits, état dans lequel ils ne peuvent
pas être modifiés. La figure 25.4 montre les champs développés. Les champs sont
développés et réduits en cliquant sur la flèche dans leur barre de titre.
Figure 25.3 Contrôle TDBGrid avec Expanded valant False
Tableau 25.8 Options détaillées des propriétés Options du composant TDBGrid (suite)
Option Effet
dgTitles True : (valeur par défaut) affiche les noms de champs en haut de la
grille.
False : l’affichage des noms de champs est désactivé.
dgIndicator True : (valeur par défaut) la colonne d’indicateur est affichée sur la
gauche de la grille et l’indicateur d’enregistrement en cours (une
flèche à gauche de la grille) est activé. A l’insertion, la flèche se
transforme en astérisque et se transforme en I à la modification.
False : la colonne d’indicateur n’apparaît pas.
dgColumnResize True : (valeur par défaut) les colonnes peuvent être
redimensionnées en faisant glisser les lignes de colonnes dans la
zone de titre. Le redimensionnement modifie la largeur
correspondante du composant TField sous-jacent.
False : les colonnes de la grille ne peuvent être redimensionnées.
dgColLines True : (valeur par défaut) affiche une ligne verticale de séparation
entre les colonnes.
False : n’affiche pas de ligne verticale de séparation entre les
colonnes.
dgRowLines True : (valeur par défaut) affiche une ligne horizontale de
séparation entre les enregistrements.
False : n’affiche pas de ligne horizontale de séparation entre les
enregistrements.
dgTabs True : (valeur par défaut) autorise la tabulation entre les champs
des enregistrements.
False : la tabulation fait sortir du contrôle grille.
dgRowSelect True : la barre de sélection occupe toute la largeur de la grille.
False : (valeur par défaut) la sélection d’un champ d’un
enregistrement ne sélectionne que ce champ.
dgAlwaysShowSelection True : (valeur par défaut) la barre de sélection de la grille est
toujours visible, même si un autre contrôle a la focalisation.
False : la barre de sélection n’apparaît dans la grille que si la grille
a la focalisation.
dgConfirmDelete True : (valeur par défaut) demande la confirmation de la
suppression d’enregistrements (Ctrl+Suppr).
False : supprime les enregistrements sans confirmation.
dgCancelOnExit True : (valeur par défaut) annule une insertion en attente lorsque la
focalisation quitte la grille. Cela permet d’éviter des validations
involontaires d’enregistrements vierges ou partiellement vierges.
False : permet à une insertion en attente d’être validée.
dgMultiSelect True : permet aux utilisateurs de sélectionner des lignes non
contiguës en utilisant les touches Ctrl+Maj ou Maj+flèche.
False : (valeur par défaut) ne permet pas à l’utilisateur de
sélectionner plusieurs lignes.
Pour plus d’informations sur les propriétés et les méthodes des grilles de
contrôle de base de données, voir le référence VCL en ligne.
Présentation
Les composants d’aide à la décision apparaissent sur la page Decision Cube de
la palette des composants :
• Le cube de décision, TDecisionCube, est un lieu de stockage de données
multidimensionnelles.
• La source de décision, TDecisionSource, définit l’état actuel du pivot d’une
grille ou d’un graphe de décision.
• La requête de décision, TDecisionQuery, est une forme spécialisée de TQuery
utilisée pour définir les données d’un cube de décision.
• Le pivot de décision, TDecisionPivot, vous permet d’ouvrir et de fermer les
dimensions, ou champs, d’un cube de décision, en appuyant sur des boutons.
• La grille de décision, TDecisionGrid, affiche des données unidimensionnelles ou
multidimensionnelles sous forme d’un tableau.
• Le graphe de décision, TDecisionGraph, affiche les champs en provenance
d’une grille de décision sous forme d’un graphe dynamique, qui change
lorsque les dimensions des données sont modifiées.
La figure 26.1 montre tous les composants d’aide à la décision placés dans une
fiche au moment de la conception.
Figure 26.1 Composants d’aide à la décision au moment de la conception
Requête de décision
Cube de décision
Souce de décision
Pivot de décision
Grille de décision
Graphe de décision
Pour créer une fiche avec des tableaux et des graphes de données
multidimensionnelles, suivez ces étapes :
1 Créez une fiche.
2 Ajoutez ces composants à la fiche et utilisez l’inspecteur d’objets pour les lier
comme indiqué :
• un ensemble de données, habituellement TDecisionQuery (pour plus de
détails, reportez-vous à “Création d’ensembles de données de décision avec
l’éditeur de requête de décision” à la page 26-6) ou TQuery ;
• un cube de décision, TDecisionCube, lié à l’ensemble de données en
définissant la propriété DataSet du cube de décision par le nom de
l’ensemble de données ;
• une source de décision, TDecisionSource, liée au cube de décision en
définissant la propriété DecisionCube de la source de décision par le nom du
cube de décision.
3 Ajoutez un pivot de décision, TDecisionPivot, et liez-le à la source de décision
dans l’inspecteur d’objets en définissant la propriété DecisionSource du pivot
par le nom de la source de décision. Le pivot de décision est facultatif mais
utile ; il permet au développeur de fiches et à l’utilisateur final de changer les
dimensions affichées dans les grilles ou les graphes de décision en appuyant
sur des boutons.
Dans son orientation par défaut (horizontale), les boutons de gauche du pivot
de décision correspondent aux champs de gauche de la grille de décision (les
lignes) ; les boutons de droite correspondent aux champs du haut de la grille
de décision (les colonnes).
Vous pouvez déterminer l’endroit où apparaissent les boutons du pivot de
décision en définissant sa propriété GroupLayout par xtVertical, xtLeftTop ou
xtHorizontal (la valeur par défaut). Pour plus d’informations sur les propriétés
du pivot de décision, reportez-vous à “Utilisation de pivots de décision” à la
page 26-11.
4 Ajoutez un ou plusieurs graphes et/ou grilles de décision, liés à la source de
décision. Pour plus de détails, reportez-vous à “Création et utilisation de
grilles de décision” à la page 26-12 et “Création et utilisation de graphes de
décision” à la page 26-15.
5 Utilisez l’éditeur de requête de décision ou la propriété SQL de
TDecisionQuery (ou TQuery) pour spécifier les tables, les champs et les calculs
récapitulatifs à afficher dans la grille ou dans le graphe. Le dernier champ de
SQL SELECT peut être un champ récapitulatif. Les autres champs de SELECT
doivent être des champs GROUP BY. Pour en savoir plus, reportez-vous à
“Création d’ensembles de données de décision avec l’éditeur de requête de
décision” à la page 26-6.
6 Définissez la propriété Active de la requête de décision (ou d’un autre
composant ensemble de données) à true.
Propriétés et événements
Voici les propriétés et les événements spéciaux qui contrôlent l’aspect et le
comportement des sources de décision :
• La propriété ControlType de TDecisionSource indique si les boutons du pivot de
décision doivent agir comme des cases à cocher (sélections multiples) ou des
boutons radio (sélections mutuellement exclusives).
• Les propriétés SparseCols et SparseRows de TDecisionSource indiquent si les
colonnes ou des lignes sans valeur doivent être affichées ; si true, les colonnes
ou les lignes vides sont affichées.
• TDecisionSource possède les événements suivants :
• OnLayoutChange se produit lorsque l’utilisateur effectue des pivotements ou
des perforations qui réorganisent les données.
• OnNewDimensions se produit lorsque les données elles-mêmes sont
modifiées, par exemple lorsque les champs récapitulatifs ou les dimensions
sont modifiés.
• OnSummaryChange se produit lorsque la valeur récapitulative en cours est
modifiée.
• OnStateChange se produit quand le cube de décision est activé ou désactivé.
• OnBeforePivot se produit lorsque les modifications sont validées mais pas
encore reflétées par l’interface utilisateur. Les développeurs ont la
possibilité d’effectuer les changements, par exemple de capacité ou de l’état
du pivot, avant que l’utilisateur de l’application ne puisse voir le résultat
de son action.
• OnAfterPivot est déclenché après une modification de l’état du pivot. Les
développeurs peuvent intercepter des informations à ce moment.
Vous pouvez utiliser les graphes de décision à la place, ou en plus, des grilles de
décision (qui elles, présentent les références croisées sous forme de tableaux). Les
grilles ou les graphes de décision qui sont liés à la même source de décision
représentent les mêmes dimensions de données. Pour montrer différentes
données récapitulatives pour les mêmes dimensions, vous pouvez lier plusieurs
graphes de décision à la même source de décision. Pour montrer différentes
dimensions, liez les graphes de décision à différentes sources de décision.
Par exemple, dans la figure 26.4, le premier pivot de décision et le premier
graphe sont liés à la première source de décision alors que le second pivot de
décision et le second graphe sont liés à la seconde source de décision. Chaque
graphe peut donc représenter des dimensions différentes.
Figure 26.4 Graphes de décision liés à différentes sources de décision
Pour plus d’informations sur ce qui apparaît dans un graphe de décision, voir la
section suivante, “Affichage du graphe de décision.”
Pour créer un graphe de décision, voir la section précédente, “Création de
graphes de décision.”
Pour connaître les propriétés des graphes de décision et savoir comment changer
l’aspect et le comportement des graphes de décision, voir “Personnalisation du
graphe de décision” à la page 26-17.
• Cliquer avec le bouton gauche sur un bouton de dimension, après avoir choisi
la commande Forer et sélectionner :
• ouvrir dimension, pour revenir au niveau supérieur de cette dimension ;
• toutes les valeurs, pour basculer entre l’affichage dans les grilles de
décision des récapitulations seulement ou des récapitulations plus les autres
valeurs.
• à partir de la liste des catégories disponibles, une catégorie à “forer” pour
connaître les valeurs détail.
• Cliquer avec le bouton gauche sur un bouton de dimension pour ouvrir ou
fermer cette dimension.
• Faire glisser les boutons de dimension depuis la partie lignes vers la partie
colonnes et réciproquement ; ils peuvent ensuite les placer à côté des boutons
existant dans cette partie ou sur l’icône de lignes ou de colonnes.
III
Ecriture d’applications distribuées
Part III
Sur les clients CORBA, le stub agit comme proxy pour un objet qui est en fait
installé sur la machine serveur. Le client interagit avec le stub comme si l’interface
était mise en oeuvre par n’importe quel autre objet. Pour plus d’informations sur
l’utilisation d’interfaces, voir “Utilisation des interfaces” à la page 4-15.
Toutefois, à la différence de la plupart des objets qui mettent en œuvre des
interfaces, le stub gère les appels d’interfaces en appelant le logiciel ORB installé
sur la machine client. L’ORB utilise un Smart Agent (osagent) qui s’exécute
quelque part dans le réseau local. Le Smart Agent est un service d’annuaire
distribué dynamique qui localise un serveur disponible fournissant la mise en
oeuvre réelle de l’objet.
Sur le serveur CORBA, le logiciel ORB transmet les appels d’interfaces à un
squelette généré automatiquement. Le squelette communique avec le logiciel ORB
par l’intermédiaire du Basic Object Adaptor (BOA). Il utilise le BOA pour
recenser l’objet auprès du Smart Agent, indique la portée de l’objet (s’il peut être
utilisé sur des machines distantes) et indique quand les objets sont instanciés et
prêts à répondre aux clients.
Stubs et squelettes
Les stubs et les squelettes fournissent le mécanisme qui permet aux applications
CORBA d’effectuer le marshaling des appels d’interfaces. Le Marshaling
• Accueille un pointeur d’interface dans le processus du serveur et met ce
pointeur à la disposition du code du processus client.
• Transfère les arguments d’un appel d’interface tels qu’ils sont transmis par le
client et les place dans l’espace du processus de l’objet distant.
Pour tout appel d’interface, l’appelant empile les arguments et effectue un appel
de fonction par l’intermédiaire du pointeur d’interface. Si l’objet n’est pas dans le
même espace de processus que le code qui appelle son interface, l’appel est
transmis à un stub qui se trouve dans le même espace de processus. Le stub
écrit les arguments dans un tampon de marshaling et transmet l’appel à l’objet
distant dans une structure. Le squelette serveur dépouille cette structure, empile
les arguments et appelle l’implémentation de l’objet. Fondamentalement, le
squelette recrée l’appel du client dans son propre espace d’adressage.
Les stubs et les squelettes sont créés automatiquement lors de la définition de
l’interface de l’objet. Leurs définitions sont créées dans l’unité _TLB créée lors de
la définition de l’interface. Vous pouvez visualiser cette unité en la sélectionnant
dans la clause uses de votre unité d’implémentation puis en appuyant sur Ctrl-
Entrée. Pour plus d’informations sur la définition de l’interface de l’objet, voir
“Définition d’interfaces d’objets” à la page 27-6.
Les entrées d’un référentiel d’interfaces ne peuvent pas être supprimées tant que
le serveur du référentiel d’interfaces fonctionne. Pour supprimer un élément,
vous devez arrêter le serveur du référentiel d’interfaces, générer un nouveau
fichier .IDL puis démarrer le serveur du référentiel d’interfaces en spécifiant le
fichier .IDL mis à jour.
Une fois l’OAD en fonctionnement, vous pouvez recenser vos interfaces d’objets
en utilisant le programme en ligne de commande oadutil. Vous devez tout
d’abord exporter le fichier .IDL pour vos interfaces. Pour cela, cliquez sur le
bouton Exporter dans l’éditeur de bibliothèque de types et enregistrez la
définition des interfaces en tant que fichier .IDL CORBA.
Ensuite, recensez les interfaces en utilisant le programme oadutil avec la syntaxe
suivante :
oadutil reg [options]
Les arguments disponibles lors du recensement d’interfaces à l’aide d’oadutil
sont les suivants :
Par exemple, la ligne suivante recense une interface d’après son id référentiel :
oadutil reg -r IDL:MyServer/MyObjectFactory:1.0 -o TMyObjectFactory -cpp MyServer.exe -p
unshared
Remarque Vous pouvez obtenir l’ID référentiel de votre interface en examinant le code
ajouté à la section d’initialisation de votre unité d’implémentation. Il s’agit du
troisième argument de l’appel à TCorbaFactory.Create.
Lorsqu’une interface devient indisponible, vous devez annuler son recensement.
Un objet dont le recensement est annulé ne peut plus être activé
automatiquement par l’OAD si un client demande l’objet. Seuls les objets qui ont
été préalablement recensés à l’aide d’oadutil reg peuvent voir leur recensement
annulé.
Il est toutefois des cas où vous ne savez pas jusqu’à l’exécution quel objet
(interface) vous souhaitez utiliser. Pour ces cas, vous pouvez utiliser la liaison
dynamique. La liaison dynamique ne requiert pas d’unité stub, mais elle requiert
que toutes les interfaces d’objets distants utilisées soit recensées avec un
référentiel d’interfaces fonctionnant dans le réseau local.
Conseil Vous pouvez utiliser la liaison dynamique pour écrire des clients CORBA pour
des serveurs qui ne sont pas écrits en Delphi. Ainsi, vous n’avez pas à écrire
votre propre classe stub pour le marshaling des appels d’interfaces.
Utilisation de stubs
Les classes de stubs sont générées automatiquement lorsque vous définissez une
interface CORBA. Elles sont définies dans une unité stub-et-squelette dont le
nom est de la forme BaseName_TLB (dans un fichier avec un nom de la forme
BaseName_TLB.pas).
Lors de l’écriture d’un client CORBA, vous ne modifiez pas le code de l’unité
stub-et-squelette. Ajoutez l’unité stub-et-squelette à la clause uses de l’unité qui a
besoin d’une interface pour un objet sur le serveur CORBA.
Pour chaque objet serveur, l’unité stub-et-squelette contient une définition
d’interface et une définition de classe pour une classe de stub correspondante.
Par exemple, si le serveur définit une classe d’objets TServerObj, l’unité stub-et-
squelette inclut une définition pour l’interface IServerObj et pour une classe de
stub TServerObjStub. La classe de stub est un descendant de TCorbaDispatchStub
et met en oeuvre son interface correspondante en effectuant le marshaling des
appels au serveur CORBA. En plus de la classe de stub, l’unité stub-et-squelette
définit une classe fabrique de stubs pour chaque interface. Cette classe fabrique
de stubs n’est jamais instanciée : elle définit une méthode de classe unique.
Dans votre application client, vous ne créez pas directement d’instances de la
classe de stub lorsque vous avez besoin d’une interface pour l’objet sur le
serveur CORBA. Appelez à la place la méthode CreateInstance de la classe
fabrique de stubs. Cette méthode accepte un argument, un nom d’instance
facultatif, et renvoie une interface sur l’instance de l’objet sur le serveur. Par
exemple :
var
ObjInterface : IServerObj;
begin
ObjInterface := TServerObjFactory.CreateInstance('');
...
end;
Lorsque vous appelez CreateInstance, cette méthode
1 Obtient une instance d’interface auprès de l’ORB.
2 Utilise cette interface pour créer une instance de la classe de stub.
3 Renvoie l’interface résultante.
Remarque Si vous écrivez un client pour un serveur CORBA qui n’a pas été écrit avec
Delphi, vous devez écrire votre propre descendant de TCorbaStub pour fournir
une prise en charge du marshaling pour votre client. Vous devez ensuite
recenser cette classe de stub avec le CORBAStubManager global. Enfin, pour
instancier la classe de stub et obtenir l’interface serveur, vous pouvez appeler la
procédure globale BindStub pour obtenir une interface que vous pourrez
transmettre ensuite à la méthode CreateStub du gestionnaire de stubs CORBA.
Obtention de l’interface
Pour obtenir une interface pour des appels DII avec une liaison retardée, utilisez
la fonction globale CorbaBind . CorbaBind accepte l’ID référentiel de l’objet serveur
ou un type d’interface. Elle utilise ces informations pour demander une interface
à l’ORB, et utilise cette dernière pour créer un objet stub.
Remarque Pour pouvoir appeler CorbaBind, il faut recenser l’association entre le type
d’interface et son ID référentiel avec le CorbaInterfaceIDManager global.
Si votre application possède une classe de stub recensée pour le type d’interface,
CorbaBind crée un stub de cette classe. Dans ce cas, l’interface renvoyée par
CorbaBind peut être utilisée pour une liaison à l’avance (par un transtypage avec
l’opérateur as) ou une liaison retardée (DII). S’il n’existe pas de classe de stub
recensée pour le type d’interface, CorbaBind renvoie l’interface sur un objet stub
générique. Un objet stub générique ne peut être utilisé que pour les appels
retardés (DII).
Pour utiliser l’interface renvoyée par CorbaBind pour des appels DII, affectez-la à
une variable de type TAny :
var
IntToCall: TAny;
begin
IntToCall := CorbaBind('IDL:MyServer/MyServerObject:1.0');
...
begin
with ORB do
begin
HR := Bind('IDL:CompanyInfo/HR:1.0');
Name := MakeStructure(FindTypeCode('IDL:CompanyInfo/EmployeeName:1.0',
[Edit1.Text,Edit2,Text]);
Emp := HR.LookupEmployee(Name);
Payroll := Bind('IDL:CompanyInfo/Payroll:1.0');
end;
Salary := Payroll.GetEmployeeSalary(Emp);
Payroll.SetEmployeeSalary(Emp, Salary + (Salary * StrToInt(Edit3.Text) / 100));
end;
En laissant l’ORB créer des chaînes pour vos objets, vous pouvez utiliser la
méthode StringToObject pour inverser cette procédure :
var
Dept: IDepartment;
begin
Dept := ORB.StringToObject(ListBox1.Items[ListBox1.ItemIndex]);
... { traitement quelconque avec le département sélectionné }
• Si votre client utilise l’interface d’appel dynamique (DII), vous devez exécuter
un serveur de référentiel d’interfaces sur au moins un système hôte dans le
réseau local, le terme “réseau local” désignant un réseau dans lequel il est
possible d’envoyer un message de diffusion. Voir “Recensement d’interfaces
avec le référentiel d’interfaces” à la page 27-9 pour des détails sur la manière
d’exécuter le serveur de référentiel d’interfaces et de recenser les interfaces
appropriées.
• Si votre serveur doit être démarré à la demande, il est nécessaire que l’Object
Activation Daemon (OAD) soit exécuté sur au moins un système hôte dans le
réseau local. Voir “Recensement d’interfaces avec l’Object Activation Daemon”
à la page 27-10 pour des détails sur la manière d’exécuter l’OAD et de
recenser les interfaces appropriées.
• Un Smart Agent (osagent) doit être installé sur au moins un système hôte
dans le réseau local. Vous pouvez déployer le Smart Agent sur plusieurs
ordinateurs.
En outre, il peut être nécessaire d’initialiser les variables d’environnement
suivantes lors du déploiement de votre application CORBA.
Par exemple, tapez la commande suivante dans une boîte DOS ou choisissez
Exécuter à partir du bouton Démarrer :
osagent -p 11000
Cette commande lance le Smart Agent afin qu’il écoute le port UDP 11000 au
lieu d’écouter le port par défaut (14000). Le changement du port utilisé par le
Smart Agent pour écouter les messages de diffusion vous permet de créer
plusieurs domaines ORB.
Figure 27.3 Deux Smart Agents dans des réseaux locaux séparés
Terminologie et standard
La majorité des protocoles contrôlant l’activité Internet sont définis dans des
documents Request for Comment (RFC) gérés par le comité IETF (Internet
Engineering Task Force), comité chargé de l’ingénierie et du développement des
protocoles Internet. Plusieurs documents RFC vous apporteront d’utiles
précisions pour le développement d’applications Internet :
• Le RFC822, “Standard for the format of ARPA Internet text messages,” décrit
la structure et le contenu des en-têtes de messages.
URI et URL
L’URL est un sous-ensemble d’un URI (Uniform Resource Identifier) défini dans
le document RFC1945. Les applications serveur Web génèrent fréquemment un
contenu à partir de plusieurs sources ; le résultat final ne réside pas à un
emplacement précis, mais est créé si nécessaire. Les URI peuvent décrire des
ressources n’ayant pas d’emplacement défini.
ISAPI et NSAPI
Une application serveur Web ISAPI ou NSAPI est une DLL qui est chargée par
le serveur Web. Les informations de requête client sont transmises à la DLL sous
forme de structure et évaluées par les objets TISAPIApplication, qui créent les
objets TISAPIRequest et TISAPIResponse. Chaque message de requête est
automatiquement traité dans un thread distinct.
CGI autonome
Une application serveur Web CGI autonome est une application console qui
reçoit les informations de requête client sur l’entrée standard et transmet les
résultats au serveur sur la sortie standard. Les données sont évaluées par l’objet
TCGIApplication, qui crée le répartiteur, et par les objets TCGIRequest et
TCGIResponse. Chaque message de requête est traité dans une instance distincte
de l’application.
Win-CGI autonome
Une application serveur Web Win-CGI autonome est une application Windows
qui reçoit les informations de requête client depuis un fichier de configuration
(INI) créé par le serveur et écrit les résultats dans un fichier que le serveur
transmet au client. Le fichier INI est évalué par l’objet TCGIApplication, qui crée
le répartiteur, et par les objets TWinCGIRequest et TWinCGIResponse. Chaque
message de requête est traité dans une instance distincte de l’application.
Le module Web
Le module Web (TWebModule) est un descendant de TDataModule ; il s’utilise de
la même façon pour offrir un contrôle centralisé pour les règles de gestion et les
composants non visuels dans l’application Web.
Ajoutez tout générateur de contenu que votre application utilisera pour générer
les messages de réponse. Il peut s’agir de générateurs de contenu intégrés, tels
que TPageProducer, TDataSetTableProducer et TQueryTableProducer ou de
descendants de TCustomContentProducer que vous avez créés vous-même. Si votre
application génère des messages de réponse incluant des données extraites d’une
base de données, ajoutez des composants d’accès aux données tels que TSession,
TDatabase, TTable, TQuery, TStoredProc ou TBatchMove.
Le module Web ne se contente pas de stocker les composants non visuels et des
règles de gestion : il fait aussi office de répartiteur en associant les messages de
requête HTTP reçus aux éléments d’action qui génèrent les réponses à ces
requêtes.
Vous avez peut-être déjà un module de données paramétré avec les composants
non visuels et les règles de gestion que vous souhaitez utiliser dans votre
application Web. Vous pouvez alors remplacer le module Web par ce module de
données : il suffit de supprimer le module Web généré automatiquement et de le
remplacer par votre module de données. Ajoutez ensuite un composant
d’événement des éléments d’action pour qu’ils lancent les opérations demandées
ou formulent un message de réponse. Le répartiteur est décrit plus en détail
dans la section “Le répartiteur Web” à la page 28-8.
Figure 28.2 Structure d’une application serveur
Le répartiteur Web
Si vous utilisez un module Web, il agit comme un répartiteur Web. Si vous
utilisez un module de données existant, vous devez lui ajouter un composant
(TWebDispatcher). Le répartiteur gère un ensemble d’éléments d’action qui savent
comment répondre à certains types de messages de requête. Lorsque l’application
Web transmet un objet requête et un objet réponse au répartiteur, il choisit un
ou plusieurs éléments d’action pour répondre à la requête.
Eléments d’action
Chaque élément d’action (TWebActionItem) effectue une tâche précise en réponse
à un type spécifique de message de requête. Les éléments d’action peuvent
répondre entièrement à une requête ou n’y répondre que partiellement et laisser
d’autres éléments d’action finir le travail. Les éléments d’action peuvent envoyer
le message de réponse HTTP pour la requête, ou simplement préparer une partie
de la réponse, que d’autres éléments d’action termineront. Si une réponse est
complétée par les éléments d’action mais non envoyée, l’application serveur Web
envoie le message de réponse.
URL de destination
Le répartiteur compare la valeur de la propriété PathInfo d’un élément d’action à
celle de la propriété PathInfo du message de requête. La valeur de cette propriété
doit être le chemin d’accès à l’URL pour toutes les requêtes que l’élément
d’action est prêt à gérer. Par exemple dans cet URL
http://www.TSite.com/art/gallery.dll/mammals?animal=dog&color=black
si la partie /gallery.dll indique l’application serveur Web, le chemin d’accès est
/mammals
Utilisez les informations de chemin d’accès pour indiquer où votre application
Web doit rechercher des informations au moment de traiter des requêtes ou pour
subdiviser votre serveur Web en sous-services logiques.
Attention Si vous modifiez la propriété Default d’une action lors de l’exécution, vous
risquez d’obtenir des résultats imprévisibles pour la requête active. Si la
propriété Default d’une action ayant déjà été déclenchée passe à True, cette action
ne sera pas réévaluée et le répartiteur ne la déclenchera pas lorsqu’il atteindra la
fin de la liste d’actions.
Envoi de la réponse
L’élément d’action peut renvoyer la réponse au client Web à l’aide des méthodes
de l’objet TWebResponse. Cependant, si aucun élément d’action n’envoie la
réponse au client, elle sera envoyée par l’application serveur Web si le dernier
élément d’action ayant analysé la requête indique que la requête a été traitée.
La propriété Method peut indiquer toute autre méthode que le client Web
demande au serveur.
Il n’est pas nécessaire que l’application serveur Web fournisse une réponse pour
toutes les valeurs possibles de la propriété Method. Le standard HTTP exige
cependant qu’elle sache répondre aux requêtes GET et HEAD.
La propriété MethodType indique si la valeur de Method est GET (mtGet), HEAD
(mtHead), POST (mtPost), PUT (mtPut) ou une autre chaîne (mtAny). Le
répartiteur fait correspondre la valeur de la propriété MethodType avec celle de la
propriété MethodType de tous les éléments d’action.
Description du contenu
Plusieurs propriétés décrivent le contenu de la réponse. ContentType fournit le
type de support de la réponse, ContentVersion le numéro de version de ce
support. ContentLength indique la longueur de la réponse. Si le contenu est codé
(par compression des données, par exemple), indiquez-le dans la propriété
ContentEncoding. Si le contenu provient d’un autre URI, indiquez-le dans la
propriété DerivedFrom. Si la valeur du contenu tient compte de la date, utilisez les
propriétés LastModified et Expires pour indiquer si le contenu est toujours valide.
La propriété Title peut fournir des informations descriptives sur le contenu.
La propriété Content est une chaîne. Les chaînes Delphi ne sont pas limitées à des
valeurs littérales, aussi la valeur de la propriété Content peut-elle être une série de
commandes HTML, un contenu graphique ou tout type de contenu MIME.
Utilisez la propriété ContentStream si le contenu du message de réponse peut être
lu dans un flux. Par exemple, si le message de réponse doit envoyer le contenu
d’un fichier, utilisez un objet TFileStream pour la propriété ContentStream. Comme
avec la propriété Content, ContentStream doit fournir une chaîne de commandes
HTML ou un autre contenu de type MIME. Si vous utilisez la propriété
ContentStream, ne libérez pas le flux vous-même : l’objet réponse Web le libérera
automatiquement.
Remarque Si la valeur de la propriété ContentStream n’est pas nil, la propriété Content est
ignorée.
Envoi de la réponse
Si vous êtes sûr que le traitement du message de requête est terminé, vous
pouvez envoyer la réponse directement depuis le gestionnaire
d’événementOnAction. L’objet réponse offre deux méthodes d’envoi de réponses :
SendResponse et SendRedirect. Appelez SendResponse pour envoyer une réponse
avec le contenu et les propriétés d’en-tête de l’objet TWebResponse. Si votre action
doit se limiter à orienter le client Web vers un autre URI, utilisez la méthode
SendRedirect, plus efficace.
Si aucun des gestionnaires d’événements n’envoie de réponse, l’application Web
l’envoie lorsque le répartiteur se referme. Cependant, si aucun élément d’action
n’indique qu’il a traité la réponse, l’application ferme la connexion au client Web
sans envoyer de réponse.
Modèles HTML
Un modèle HTML est une suite de commandes HTML et de balises HTML
transparentes. Une balise HTML transparente est au format :
<#Nom_de_balise Param1=Valeur1 Param2=Valeur2 ...>
Les crochets (< et >) définissent la portée de la balise. Le signe “#” vient
immédiatement après le crochet ouvrant, sans espace entre les deux. Il indique
au générateur de page que la chaîne qui suit est une balise HTML transparente.
Le nom de la balise suit immédiatement le signe dièse, sans espace entre les
deux. Le nom de la balise peut être tout identificateur valide ; il identifie le type
de conversion représenté par la balise.
Après un nom de balise, une balise HTML transparente peut parfois comporter
des paramètres fournissant des informations sur la conversion à effectuer.
Chaque paramètre est au format Paramètre=Valeur. Aucun espace ne doit figurer
entre le nom du paramètre, le signe égal et la valeur. Les paramètres sont
séparés par des espaces.
Les crochets (< et >) rendent la balise transparente pour les navigateurs HTML
qui ne reconnaissent pas la syntaxe “#Nom_de_balise”.
Bien que vous puissiez créer vos propres balises HTML transparentes pour
représenter tout type d'informations traitées par votre générateur de page, Delphi
met à votre disposition plusieurs noms de balises associés à des valeurs du type
de données TTag. Ces noms de balise prédéfinis corrrespondent aux commandes
HTML susceptibles de varier d'un message de réponse à l'autre. Ils sont décrits
dans le tableau suivant :
Tout autre nom de balise est associé à tgCustom. Le générateur de page n’offre
aucun traitement spécifique des noms de balises prédéfinis. Ils sont simplement
fournis pour aider vos applications à structurer le processus de conversion des
tâches les plus fréquentes.
Remarque Les noms de balises prédéfinis tiennent compte de la différence entre majuscules
et minuscules.
placés entre des images des mois précédent et suivant, puis du calendrier lui-
même. L’image finale aurait l’aspect suivant :
Cependant, lorsque vous créez une application NSAPI ou ISAPI, chaque message
de requête est géré dans un thread distinct d’une instance d’application. Pour
empêcher que les connexions aux bases de données d’autres threads ne se
parasitent, vous devez donner une session distincte à chaque thread.
Chaque message de requête dans une application ISAPI ou NSAPI génère un
nouveau thread. Le module Web de ce thread est dynamiquement généré lors de
l’exécution. Ajoutez un objet TSession au module Web pour gérer les connexions
aux bases de données pour le thread qui contient le module Web.
A l’exécution, une instance distincte du module Web est générée pour chacun
des threads. Chacun de ces modules contient l’objet session. Chaque session doit
avoir un nom distinct pour que les threads qui gèrent les messages de requête
ne parasitent pas leur connexion aux bases de données respectives. Pour que les
objets session de chaque module s’attribuent dynamiquement un nom unique,
définissez la propriété AutoSessionName de l’objet session. Chaque session
s’attribuera dynamiquement un nom unique et définira la propriété SessionName
de tous les ensembles de données du module de façon à ce qu’elle fasse
référence à ce nom unique. Ceci permet l’interaction des threads de requête avec
la base de données, sans interférences avec les autres messages de requête. Pour
plus d’informations sur les sessions, voir chapitre 16, “Gestion de sessions de
bases de données.”
Simulation du serveur
Pour les applications Win-CGI, vous pouvez simuler le serveur en créant le
fichier de configuration contenant les informations de requête. Lancez ensuite
l’application Win-CGI en lui passant l’emplacement du fichier contenant les
informations sur le client et l’emplacement du fichier que le programme Win-CGI
doit utiliser pour créer le contenu. Vous pouvez ensuite déboguer l’application.
29
Utilisation des sockets
Chapter 29
Services et ports
La plupart des services standard sont associés, par convention, à des numéros de
ports précis. Nous étudierons plus tard ces numéros de ports. Pour l’instant,
considérez le numéro de port comme un code numérique pour ce service.
Si vous implémentez un service standard, les objets socket Windows fournissent
des méthodes de recherche de numéro de port pour le service. Si vous offrez un
service nouveau, vous pouvez spécifier son numéro de port dans un fichier
SERVICES sur les systèmes sous Windows 95 ou NT. Consultez la
documentation Microsoft traitant des sockets Windows pour de plus amples
informations sur le contenu du fichier SERVICES.
Connexions client
Les connexions client connectent un socket client sur le système local à un socket
serveur sur un système distant. Les connexions client sont lancées par le socket
client. En premier lieu, le socket client doit décrire le socket serveur auquel il
souhaite se connecter. Le socket client recherche ensuite le socket serveur et,
lorsqu’il l’a trouvé, demande une connexion. Le socket serveur peut ne pas
établir immédiatement la connexion. Les sockets serveur gèrent une file d’attente
des demandes de clients et établissent la connexion lorsqu’ils le peuvent. Lorsque
le socket serveur accepte la connexion du client, il envoie au socket client une
description complète du socket serveur auquel il se connecte et la connexion est
finalisée par le client.
Connexions d’écoute
Les sockets serveur ne localisent pas les clients : ils génèrent des “demi-
connexions” passives qui restent à l’écoute des requêtes des clients. Les sockets
serveur associent une file d’attente à leurs connexions d’écoute ; la file d’attente
enregistre les requêtes de connexion lorsqu’elles lui parviennent. Lorsque le
socket serveur accepte une demande de connexion client, il forme un nouveau
socket pour se connecter au client pour que la connexion d’écoute reste ouverte
afin d’accepter d’autres requêtes de clients.
Connexions serveur
Les connexions serveur sont formées par des sockets serveur lorsque le socket
d’écoute accepte une requête du client. La description du socket serveur ayant
effectué la connexion au client est envoyée au client lorsque le serveur accepte la
connexion. La connexion est établie lorsque le socket client reçoit cette
description et effectue véritablement la connexion.
Une description complète d’une connexion par socket inclut les adresses du socket
à chaque extrémité de la connexion. Vous pouvez décrire l’adresse de chaque
extrémité du socket en fournissant l’hôte ou l’adresse IP et le numéro de port.
Avant de faire une connexion par socket, vous devez décrire complètement les
sockets formant ses extrémités. Certaines informations sont disponibles sur le
système exécutant votre application. Par exemple, il n’est pas nécessaire de
décrire l’adresse IP locale d’un socket client car elle est dans le système
d’exploitation.
Les informations à fournir dépendent du type de socket implémenté. Les sockets
client doivent décrire le serveur auquel ils souhaitent se connecter. Les sockets
serveur d’écoute doivent décrire le port représentant le service qu’ils offrent.
Si le nom de l’hôte vous est inconnu, le socket client doit spécifier le système
serveur par son adresse IP. Ce processus donne des recherches plus rapides car,
lorsque vous spécifiez un nom d’hôte, le socket doit rechercher l’adresse IP
associée à ce nom pour localiser le système serveur.
Formation de la connexion
Lorsque les propriétés de votre composant socket client décrivent le serveur
auquel vous souhaitez vous connecter, vous pouvez former la connexion à
l’exécution en appelant la méthode Open. Si vous souhaitez que votre application
forme automatiquement la connexion à son ouverture, mettez la propriété Active
à True lors de la conception, à l’aide de l’inspecteur d’objets.
Fermeture de la connexion
Lorsque vous avez fini de communiquer avec une application serveur sur la
connexion socket, vous pouvez fermer la connexion en appelant la méthode
Close. La connexion peut également être fermée depuis le serveur. Si c’est le cas,
vous en êtes informé par un événement OnDisconnect.
Désignation du port
Pour que votre socket serveur puisse écouter les requêtes de connexion client,
vous devez spécifier un port d’écoute. Vous pouvez spécifier ce port à l’aide de
la propriété Port. Si votre application serveur offre un service standard associé
par convention à un numéro de port précis, vous pouvez spécifier ce numéro de
port indirectement, à l’aide de la propriété Service. Il est recommandé d’utiliser la
propriété Service car il est possible de faire des fautes de saisie en entrant le
numéro de port. Si vous précisez à la fois les propriétés Port et Service, le socket
serveur utilisera le nom du service.
Evénements d’erreurs
Les sockets client génèrent un événement OnError lorsqu’ils reçoivent un
message d’erreur émis par la connexion. Les sockets serveur génèrent un
événement OnClientError. Vous pouvez écrire un gestionnaire d’événement
OnError ou OnClientError pour répondre à ces messages d’erreur. Le gestionnaire
d’événement reçoit des informations sur :
• l’objet socket Windows ayant reçu la notification d’erreur ;
• ce que le socket tentait de faire lorsque l’erreur s’est produite ;
• le code d’erreur fourni par le message d’erreur.
Vous pouvez répondre à l’erreur dans le gestionnaire d’événement et mettre le
code d’erreur à 0 pour empêcher le socket d’afficher une erreur.
Evénements client
Lorsqu’un socket client ouvre une connexion, les événements suivants se
produisent :
1 Un événement OnLookup se produit avant une tentative de localisation du
socket serveur. A ce moment-là, vous ne pouvez pas modifier les propriétés
Host, Address, Port ou Service pour changer le socket serveur qui est localisé.
Vous pouvez utiliser la propriété Socket pour accéder à l’objet socket
Windows client et utiliser sa propriété SocketHandle pour faire des appels
d’API Windows qui affectent les propriétés client du socket. Par exemple, si
vous souhaitez définir le numéro de port sur l’application client, faites-le
avant que le serveur client ne soit contacté.
2 Le socket Windows est paramétré et initialisé pour la notification
d’événements.
3 Un événement OnConnecting se produit après que le serveur socket soit
localisé. A ce moment, l’objet Windows Socket accessible par la propriété
Socket peut fournir des informations sur le serveur socket qui sera à l’autre
extrémité de la connexion. Ceci est la première possibilité d’obtenir le numéro
de port et l’adresse IP utilisés pour la connexion, qui peuvent différer du
numéro de port de l’adresse IP du socket d’écoute qui a accepté la connexion.
4 La demande de connexion est acceptée par le serveur et gérée par le socket
client.
5 Un événement OnConnect se produit après l’établissement de la connexion. Si
votre socket doit immédiatement lancer la lecture ou l’écriture sur la
connexion, créez un gestionnaire d’événement OnConnect.
Evénements serveur
Les composants socket serveur forment deux types de connexions : les
connexions d’écoute et les connexions aux applications client. Le socket serveur
reçoit des événements lors de la formation de ces deux types de connexions.
Evénements d’écoute
Juste avant que la connexion d’écoute soit formée, l’événement OnListen se
produit. Vous pouvez alors obtenir l’objet socket serveur Windows par le biais
de la propriété Socket. Vous pouvez utiliser sa propriété SocketHandle pour
modifier le socket avant qu’il ne soit ouvert pour l’écoute. Par exemple, si vous
souhaitez restreindre les adresses IP que le serveur utilise pour les écoutes, vous
pouvez le faire dans un gestionnaire d’événement OnListen.
Connexions bloquantes
Lorsque la connexion est bloquante, votre socket doit initier la lecture ou
l’écriture sur la connexion, plutôt qu’attendre la notification émanant de la
connexion socket. Utilisez un socket bloquant lorsque votre côté de la connexion
décide du moment où doivent s’effectuer les lectures et les écritures.
Pour les sockets client, mettez la propriété ClientType à ctBlocking pour former
une connexion bloquante. En fonction de ce dont est capable votre application
client, il peut être recommandé de créer un nouveau thread d’exécution pour les
lectures ou les écritures, de telle sorte que votre application puisse continuer
l’exécution du code dans d’autres threads tout en attendant la fin des lectures ou
des écritures sur la connexion.
Pour les sockets serveur, mettez la propriété ServerType à stThreadBlocking pour
former une connexion bloquante. Etant donné que les connexions bloquantes
interrompent l’exécution de tout autre code lorsque le socket attend que des
informations soient écrites ou lues sur la connexion, les composants de socket
serveur génèrent toujours un nouveau thread d’exécution pour chaque connexion
client lorsque le ServerType est à stThreadBlocking.
Utilisation de TWinSocketStream
Quand vous implémentez le thread d’une connexion bloquante, déterminez le
moment où le socket à l’autre extrémité de la connexion est prêt à lire ou écrire.
Les connexions bloquantes n’informent pas le socket du moment où il faut lire ou
écrire. Pour savoir si la connexion est prête, utilisez un objet TWinSocketStream.
TWinSocketStream dispose de méthodes permettant d’aider à coordonner la
chronologie des lectures et écritures. Appelez la méthode WaitForData pour
attendre jusqu’à ce que le socket à l’autre extrémité soit prêt à écrire.
Si vous lisez ou écrivez en utilisant TWinSocketStream, le flux fait un timeout si la
lecture ou l’écriture n’est pas terminée au bout d’un laps de temps spécifié.
Ainsi, l’application socket ne se bloque pas indéfiniment en essayant de lire ou
d’écrire via une connexion perdue.
Remarque Vous ne pouvez pas utiliser TWinSocketStream avec une connexion non
bloquante.
Attention Les sockets serveur placent dans un cache les threads qu’ils utilisent. Assurez-
vous que la méthode ClientExecute effectue les initialisations nécessaires afin qu’il
n’y ait pas de problème quand le thread s’exécute pour la dernière fois.
Pour utiliser votre thread, créez-le dans un gestionnaire d’événements
OnGetThread. Lors de la création du thread, affectez la valeur False au paramètre
CreateSuspended.
IV
Création de composants
Part IV
personnalisés
Les chapitres de cette partie présentent les concepts et connaissances nécessaires
à la conception et à l’implémentation de composants personnalisés dans Delphi.
Composants et classes
Comme les composants sont des classes, les créateurs de composants manipulent
les objets à un niveau différent de celui des développeurs d’applications. La
création de nouveaux composants nécessite de dériver de nouvelles classes.
Brièvement, il existe deux différences principales entre la création des composants
et leur utilisation dans des applications. Pour la création de composants,
• Vous avez accès à des parties de la classe qui sont inaccessibles aux
programmeurs d’applications.
• Vous ajoutez de nouvelles parties (des propriétés, par exemple) aux composants.
A cause de ces différences, il faut prendre en compte un plus grand nombre de
conventions, et réfléchir à la manière dont les développeurs d’applications vont
utiliser les composants.
Vous pouvez aussi dériver des classes qui ne sont pas des composants et ne
peuvent pas être manipulées dans une fiche. Delphi inclut de nombreuses classes
de ce type, telles que TRegIniFile et TFont.
En les libérant des tâches d’arrière-plan telles que la création des fenêtres, les
composants Delphi permettent aux développeurs de se concentrer sur ce qu’ils
veulent vraiment réaliser. Pour transmettre un handle de fenêtre à une fonction
API, il n’est pas nécessaire de vérifier que le handle existe ni de créer la fenêtre.
Le programmeur est certain que les opérations vont se dérouler correctement et
n’a pas besoin de le contrôler sans cesse.
Bien que la création de composants sans dépendances soit un peu plus longue, le
temps qui y est consacré est généralement très utile. Non seulement cela évite aux
développeurs répétitions et travail fastidieux, mais cela réduit la quantité de
documentation et de support.
Propriétés
Les propriétés donnent au développeur d’applications l’illusion de définir ou de
lire la valeur d’une variable, tout en permettant au concepteur de composants de
dissimuler la structure de données sous-jacente ou de définir un traitement
spécial lorsque la valeur est accédée.
L’utilisation des propriétés présente plusieurs avantages :
• Les propriétés sont disponibles au moment de la conception. Le développeur
d’applications peut définir ou modifier les valeurs initiales des propriétés sans
écrire de code.
• Les propriétés peuvent contrôler les valeurs ou les formats au moment où le
développeur les définit. La validation de la saisie pendant la conception empêche
de commettre des erreurs.
• Le composant peut construire les valeurs appropriées à la demande. L’erreur de
programmation la plus fréquente est de référencer une variable qui n’a été
initialisée. En représentant les données par une propriété, vous êtes sûr qu’une
valeur leur est toujours disponible sur demande.
• Les propriétés vous permettent de cacher les données sous une interface
simple et cohérente. Vous pouvez modifier la façon dont les informations sont
structurées dans une propriété sans que ce changement ne soit perçu par les
développeurs d’applications.
Le chapitre 32, “Création de propriétés,” explique comment ajouter des
propriétés à vos composants.
Evénements
Un événement est une propriété spéciale qui appelle du code, pendant
l’exécution, en réponse à une saisie ou à une autre opération. Les événements
permettent aux développeurs d’associer des blocs de code spécifiques à des
actions spécifiques, telles des manipulations de la souris ou des frappes au
clavier. Le code qui s’exécute lorsqu’un événement survient est appelé le
gestionnaire de l’événement.
Les événements permettent aux développeurs d’applications de spécifier des
réponses différentes en fonction des actions possibles sans avoir à créer de
nouveaux composants.
Le chapitre 33, “Création d’événements,” explique comment implémenter des
événements standard et comment en définir de nouveaux.
Méthodes
Les méthodes de classes sont des fonctions et procédures qui opèrent sur une
classe plutôt que sur des instances particulières de cette classe. Par exemple, les
méthodes constructeur de composants (Create) sont toutes des méthodes de
classes. Les méthodes de composants sont des procédures et fonctions qui
opèrent sur les instances des composants elles-mêmes. Les développeurs
d’applications utilisent des méthodes pour que les composants effectuent des
actions particulières ou renvoient des valeurs non contenues par des propriétés.
Comme elles nécessitent une exécution de code, les méthodes ne sont disponibles
qu’au moment de l’exécution. Elles sont utiles pour plusieurs raisons :
• Les méthodes encapsulent la fonctionnalité d’un composant dans l’objet même
où résident les données.
• Les méthodes peuvent cacher des procédures compliquées sous une interface
simple et cohérente. Un développeur d’applications peut appeler la méthode
AlignControls d’un composant sans savoir comment elle fonctionne ni si elle
diffère de la méthode AlignControls d’un autre composant.
• Les méthodes permettent de mettre à jour plusieurs propriétés avec un seul
appel.
Le chapitre 34, “Création de méthodes,” explique comment ajouter des méthodes
à vos composants.
Si vous avez déjà écrit une application Windows graphique, vous connaissez les
contraintes imposées par l’interface graphique Windows (GDI), comme les limites
sur le nombre de contextes de périphériques disponibles et l’obligation de restaurer
l’état initial des objets graphiques avant de les détruire.
Avec Delphi, vous n’avez pas besoin de vous en préoccuper. Pour dessiner sur
une fiche ou tout autre composant, il suffit d’accéder à la propriété Canvas du
composant. Pour personnaliser un crayon ou un pinceau, il faut définir une couleur
ou un style. Lorsque vous avez terminé, Delphi dispose des ressources. Delphi
conserve les ressources en mémoire cache pour éviter de les recréer, si votre
application utilise fréquemment le même type de ressources.
Vous pouvez toujours accéder à l’interface GDI Windows, mais votre code sera
beaucoup plus simple et s’exécutera plus rapidement si vous utilisez le canevas
intégré aux composants Delphi. Les fonctionnalités graphiques sont décrites en
détail dans le chapitre 35, “Graphiques et composants.”
Recensement
Avant de pouvoir installer vos composants dans l’EDI de Delphi, vous devez les
recenser. Le recensement indique à Delphi où le composant doit apparaître sur la
palette des composants. Vous pouvez aussi personnaliser la manière dont Delphi
stocke les composants dans le fichier fiche. Le recensement est décrit dans le
chapitre 37, “Accessibilité des composants au moment de la conception.”
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register ;
implementation
procedure Register ;
begin
RegisterComponents('Samples', [TMyControl]);
end;
end.
Dérivation du composant
Chaque composant est une classe dérivée de TComponent, de l’un de ses
descendants plus spécialisés (tels que TControl ou TGraphicControl) ou d’une
classe composant existante. “Comment créer un composant ?” à la page 30-2
indique les classes à dériver pour obtenir les différentes sortes de composants.
La dérivation des classes est expliquée plus en détail dans la section “Définition
de nouvelles classes” à la page 31-2.
Pour dériver un composant, ajoutez une déclaration de type objet à la partie
interface de l’unité qui contiendra le composant.
Une classe composant simple est un composant non visuel descendant
directement de TComponent.
Pour créer une classe composant simple, ajoutez la déclaration de classe suivante
àla partie interface de votre unité composant :
type
TNewComponent = class(TComponent)
end;
Pour l’instant, le nouveau composant ne fait rien de plus que TComponent. C’est
juste un squelette sur lequel vous allez bâtir votre nouveau composant.
Recensement du composant
Le recensement est une opération simple qui indique à Delphi les composants à
ajouter à la bibliothèque des composants et les pages de la palette sur lesquelles
ils doivent apparaître. Pour une présentaiton plus détaillée du processus de
recensement, voir le chapitre 37, “Accessibilité des composants au moment de la
conception.”.
Pour recenser un composant,
1 Ajoutez une procédure nommée Register à la partie interface de l’unité du
composant. Register n’a pas de paramètres, la déclaration est donc très simple :
procedure Register;
Si vous ajoutez un composant à une unité qui contient déjà des composants,
elle doit déjà avoir la procédure Register déclarée, afin que vous n’ayiez pas à
changer la déclaration.
2 Ecrivez la procédureRegister dans la partie implémentation de l’unité, en
appelant RegisterComponents pour chaque composant que vous voulez recenser.
RegisterComponents est une procédure qui prend deux paramètres : le nom
d’une page de palette de composants et un ensemble de types de composants.
Si vous ajoutez un composant à un recensement existant, vous pouvez soit
ajouter le nouveau composant à l’ensemble dans l’instruction existante, soit
ajouter une nouvelle instruction qui appelle RegisterComponents.
Modifier les valeurs par défaut d’une classe pour éviter les répétitions
Dans tout programme, les répétitions superflues sont à proscrire. Si vous vous
surprenez à répéter les mêmes lignes de code, vous serez sans doute amené à les
placer à part dans une sous-routine ou une fonction, ou encore à construire une
bibliothèque de routines utilisables par un autre programme. Le même
raisonnement s’applique aux composants. Si vous modifiez fréquemment les
mêmes propriétés ou si vous appelez les mêmes méthodes, vous créerez sans
doute un nouveau composant qui effectue ces tâches par défaut.
Par exemple, supposons qu’à chaque création d’une nouvelle application, vous
ajoutez une boîte de dialogue accomplissant une fonction déterminée. Bien qu’il
soit simple de recréer à chaque fois cette boîte de dialogue, c’est superflu. Vous
pouvez concevoir la boîte de dialogue une fois pour toute, définir ses propriétés
puis installer le composant enveloppe associé dans la palette des composants. En
faisant du dialogue un composant réutilisable, non seulement vous éliminez une
tâche répétitive mais renforcez la standardisation et minimisez les erreurs qui
peuvent être occasionnées par chaque nouvelle création de la boîte de dialogue.
Remarque Si vous voulez ne modifier que les propriétés publiées d’un composant existant
ou enregistrer des gestionnaires d’événement spécifiques à un composant ou à
un groupe de composants, vous pourrez accomplir ceci plus facilement en créant
un modèle de composant.
Le chapitre 38, “Modification d’un composant existant,” montre un exemple qui
modifie les propriétés par défaut d’un composant.
Déclarez les membres en private si vous voulez qu’ils ne soient disponibles que
dans la classe où ils ont été définis. Déclarez-les en protected si vous voulez
qu’ils ne soient disponibles que dans cette classe et ses descendants. Souvenez-
vous que si un membre est disponible n’importe où dans un fichier unité, il est
disponible partout dans ce fichier. Ainsi, si vous définissez deux classes dans la
même unité, elles pourront accéder à l’une ou l’autre des méthodes privées. Et si
vous dérivez une classe dans une unité différente de son ancêtre, toutes les
classes de la nouvelle unité pourront accéder aux méthodes protégées de
l’ancêtre.
Méthodes statiques
Toutes les méthodes sont statiques à moins que vous ne les déclariez
spécifiquement autrement. Les méthodes statiques fonctionnent comme des
procédures ou des fonctions normales.Le compilateur détermine l’adresse exacte
de la méthode et la lie au moment de la compilation.
Le premier avantage des méthodes statiques est qu’elles sont réparties très
rapidement. Comme le compilateur peut déterminer l’adresse exacte de la
méthode, il la lie directement. Les méthodes virtuelles et dynamiques, au
contraire, utilisent des moyens indirects pour donner l’adresse de leurs méthodes
lors de l’exécution, ce qui prend davantage de temps.
Une méthode statique ne change pas lorsqu’elle est héritée d’une classe
descendante. Si vous déclarez une classe comprenant une méthode statique, puis
dérivez une nouvelle classe à partir de celle-ci, la classe dérivée partage
exactement la même méthode à la même adresse. Cela signifie que vous ne
pouver pas redéfinir des méthodes statiques. Une méthode statique réalise
toujours la même chose quelle que soit la classe qui y est appelée. Si vous
déclarez une méthode dans une classe dérivée ayant le même nom qu’une
méthode statique dans la classe ancêtre, la nouvelle méthode replace simplement
celle héritée dans la classe dérivée.
Méthodes virtuelles
Les méthodes virtuelles emploient un mécanisme de répartition plus compliqué
et plus souple que les méthodes statiques. Une méthode virtuelle peut être
redéfinie dans des classes descendantes, mais est toujours appelée dans la classe
ancêtre. L’adresse d’une méthode virtuelle n’est pas déterminée lors de la
compilation ; à la place, l’objet où la méthode est définie donne l’adresse lors de
l’exécution.
Pour qu’une méthode soit virtuelle, ajoutez la directive virtual après la
déclaration de méthode. La directive virtual crée une entrée dans le tableau de
méthode virtuelle, de l’objet, ou VMT, qui contient les adresses de toutes les
méthodes virtuelles d’un type objet.
Lorsque vous dérivez une nouvelle classe d’une classe existante, la nouvelle
classe a son propre VMT, qui comprend toutes les entrées provenant du VMT de
l’ancêtre plus toutes les méthodes virtuelles supplémentaires déclarées dans la
nouvelle classe.
Méthodes dynamiques
Les méthodes dynamiques sont des méthodes virtuelles avec un mécanisme de
répartition légèrement différent. Comme les méthodes dynamiques n’ont pas
d’entrées dans le tableau de méthode virtuelle de l’objet, elles peuvent réduire la
taille de la mémoire consommée par les objets. Cependant les méthodes de
répartition dynamiques sont quelque peu plus lentre que les méthodes de
répartition virtuelles normales. Si une méthode est fréquemment appelée, ou si
son exécution nécessite un temps court, vous devrez probablement la déclarer
virtuelle plutôt que dynamique.
Les objets doivent stocker les adresses de leurs méthodes dynamiques. Mais
plutôt que de recevoir les entrées dans le tableau de méthode virtuelle, les
méthodes dynamiques sont indiquées séparément. La liste des méthodes
dynamiques contient des entrées uniquements pour les méthodes introduites ou
surchargées par une classe particulière (le tableau de méthode virtuelle, à
l’inverse, comprend toutes les méthodes virtuelles de l’objet, à la fois héritées et
introduites). Les méthodes dynamiques héritées sont réparties en cherchant
chaque liste de méthode dynamique de l’ancêtre, en allant en arrière dans
l’arborescence de l’héritage.
Pour rendre une méthode dynamique, ajoutez la directive dynamic après la
déclaration de méthode.
Classes et pointeurs
Chaque classe (et par conséquent chaque composant) est en fait un pointeur. Le
compilateur déréférence automatiquement les pointeurs de classe à votre place,
aussi n’avez-vous généralement pas besoin de vous poser ces questions. Le statut
des classes en tant que pointeurs devient important lorsque vous passez une
classe comme paramètre. En général, vous transmettrez les classes par valeur
plutôt que par référence. Car les classes sont déjà des pointeurs, c’est-à-dire des
références ; transmettre une classe par référence serait transmettre une référence à
une référence.
32
Création de propriétés
Chapter 32
Types de propriétés
Une propriété peut avoir un type quelconque. Les divers types sont affichées de
manière différente dans l’inspecteur d’objets, ce qui valide l’affectation des
propriétés effectuées au moment de la conception.
Accès direct
L’accès direct est le moyen le plus simple d’accéder aux données d’une propriété.
Autrement dit, les parties read et write de la déclaration d’une propriété
spécifient que l’affectation ou la lecture de la valeur de la propriété s’effectue
directement dans la donnée membre de stockage interne sans appel à une
méthode d’accès. L’accès direct est utile lorsque vous voulez rendre une
propriété accessible dans l’inspecteur d’objets, mais que vous ne voulez pas que
le changement de sa valeur déclenche un processus immédiatement.
En général, vous définirez un accès direct pour la partie read d’une déclaration
de propriété et utiliserez une méthode d’accès pour la partie write. Cela permet
de mettre à jour l’état du composant lorsque la valeur de la propriété change.
La déclaration de type composant suivante montre une propriété qui utilise
l’accès direct pour les parties read et write.
type
TSampleComponent = class(TComponent)
private { le stockage interne est privé}
FMyProperty: Boolean; { déclare la donnée membre pour contenir la valeur }
published { rend la propriété disponible à la conception }
property MyProperty: Boolean read FMyProperty write FMyProperty;
end;
Méthodes d’accès
Vous pouvez spécifier une méthode d’accès plutôt qu’une donnée membre dans
les parties read et write d’une déclaration de propriété. Les méthodes d’accès
doivent être protected, et sont habituellement déclarées comme virtual ; cela
autorise les composants descendants à surcharger l’implémentation de la
propriété.
Evitez de rendre publiques les méthodes d’accès. Les conserver protected vous
prémunit contre toute modification accidentelle d’une propriété par un
développeur d’applications qui appellerait ces méthodes.
Voici une classe qui déclare trois propriétés en utilisant le spécificateur d’index,
qui autorise aux trois propriétés d’avoir les mêmes méthodes d’accès en lecture
et en écriture :
type
TSampleCalendar = class(TCustomGrid)
public
property Day: Integer index 3 read GetDateElement write SetDateElement;
property Month: Integer index 2 read GetDateElement write SetDateElement;
property Year: Integer index 1 read GetDateElement write SetDateElement;
private
function GetDateElement(Index: Integer): Integer; { remarquez le paramètre Index }
procedure SetDateElement(Index: Integer; Value: Integer);
ƒ
Comme chaque élément de la date (day, month et year) est un int et comme la
définition de chacun requiert le codage de la date lorsqu’elle est définie, le code
évite la duplication en partageant les méthodes de lecture et d’écriture pour les
trois propriétés. Vous n’avez besoin que d’une seule méthode pour lire un
élément date et et une autre pour écrire l’élément date.
Voici la méthode read qui obtient l’élément date :
function TSampleCalendar.GetDateElement(Index: Integer): Integer;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(FDate, AYear, AMonth, ADay); { décompose la date codée en éléments }
case Index of
1: Result := AYear;
2: Result := AMonth;
3: Result := ADay;
else Result := -1;
end;
end;
Voici la méthode write qui définit l’élément date approprié :
procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);
var
AYear, AMonth, ADay: Word;
begin
if Value > 0 then { tous les éléments doivent être positifs}
begin
DecodeDate(FDate, AYear, AMonth, ADay); { prend les éléments date actuels }
case Index of { définit le nouvel élément selon Index }
1: AYear := Value;
2: AMonth := Value;
3: ADay := Value;
else Exit;
end;
FDate := EncodeDate(AYear, AMonth, ADay); { code la date modifiée}
Refresh; { actualise le calendrier visible }
end;
end;
Méthode read
La méthode read d’une propriété est une fonction qui n’accepte aucun paramètre
(sauf pour ce qui est mentionné ci-après) et renvoie une valeur du même type
que la propriété. Par convention, le nom de la fonction est Get suivi du nom de
la propriété. Par exemple, la méthode read pour une propriété intitulée Count
serait GetCount. La méthode read manipule les données internes afin de générer
une valeur de la propriété respectant le type demandé.
Les seules exceptions à la règle “aucun paramètre” sont les propriétés tableau et
les propriétés qui utilisent un spécificateur d’index [XXX GOTOLINK: ^X^E
cwgCreatingIndexedProperties], pour lesquelles cet index est transmis comme
paramètre. (Utilisez des spécificateurs d’index pour créer une méthode read
unique partagée par plusieurs propriétés. Pour plus d’informations sur les
spécificateurs d’index, consultez le Guide du langage Pascal Objet.)
Si vous ne déclarez aucune méthode read, la propriété fonctionne uniquement en
écriture. Les propriétés fonctionnant en écriture uniquement sont très rares.
Méthode write
La méthode write d’une propriété est une procédure acceptant un seul paramètre
(sauf pour ce qui est mentionné ci-après) du même type que la propriété. Le
paramètre peut être transmis par référence ou par valeur et peut porter le nom de
votre choix. Par convention, le nom de la méthode write est Set suivi du nom de
la propriété. Par exemple, la méthode write d’une propriété intitulée Count serait
SetCount. La valeur transmise en paramètre devient la nouvelle valeur de la
propriété ; la méthode write doit accomplir les manipulations nécessaires pour
placer les données concernées à l’emplacement de stockage interne de la propriété.
Les seules exceptions à la règle “paramètre unique” sont les propriétés tableau et
les propriétés qui utilisent un spécificateur d’index, pour lesquelles cet index est
transmis comme second paramètre. (Utilisez des spécificateurs d’index pour créer
une méthode read unique partagée par plusieurs propriétés. Pour plus
d’informations sur les spécificateurs d’index, consultez le Guide du langage Pascal
Objet.)
Si vous ne déclarez aucune méthode write, la propriété fonctionne uniquement
en lecture. Pour qu’une propriété publiée puisse être utilisée au moment de la
conception, elle doit être accessible en lecture/écriture.
Les méthodes write testent normalement si une nouvelle valeur diffère de la
valeur actuelle avant de modifier la propriété. Par exemple, voici une méthode
write simple d’une propriété de type entier appelée Count stockant sa valeur
courante dans une donnée membre appelée FCount.
procedure TMyComponent.SetCount(Value: Integer);
begin
if Value <> FCount then
begin
FCount := Value;
Update;
end;
end;
Détermination du stockage
Vous pouvez choisir si Delphi stocke ou non chacune des propriétés de vos
composants. Par défaut, sont stockées toutes les propriétés de la partie published
de la déclaration de classe. Vous pouvez choisir de ne pas stocker une propriété
ou de désigner une fonction qui décidera, au moment de l’exécution, du
stockage de la propriété.
Pour contrôler le stockage par Delphi d’une propriété, ajoutez la directive stored
à la déclaration de propriété, suivie par true, false ou le nom d’une méthode
booléenne.
Le code suivant montre un composant avec la déclaration de trois nouvelles
propriétés. La première est toujours stockée, la deuxième ne l’est jamais et la
troisième est stockée selon la valeur d’une méthode booléenne :
type
TSampleComponent = class(TComponent)
protected
function StoreIt: Boolean;
public { non stockée normalement}
property Important: Integer stored True; { toujours stockée}
published { toujours stockée normalement}
property Unimportant: Integer stored False; { jamais stockée}
property Sometimes: Integer stored StoreIt; { dépend de la valeur de la fonction}
end;
33
Création d’événements
Chapter 33
Bien qu’un gestionnaire d’événement ne puisse pas être une fonction, vous
pouvez toujours obtenir les informations à partir du code du développeur de
l’application en utilisant les paramètres var. Lorsque vous effectuerez ceci,
vérifiez que vous affectez une valeur correcte au paramètre avant d’appeler le
gestionnaire afin de ne pas rendre obligatoire la modification de la valeur par le
code de l’utilisateur.
Un exemple de transmission des paramètres var à un gestionnaire d’événement
est fourni par l’événement OnKeyPress , de type TKeyPressEvent. TKeyPressEvent
définit deux paramètres, l’un indiquant l’objet qui a généré l’événement et l’autre
la touche enfoncée :
type
TKeyPressEvent = procedure (Sender: TObject; var Key: Char) of object;
Normalement, le paramètre Key contient le caractère tapé par l’utilisateur.
Toutefois dans certaines circonstances, l’utilisateur de composant peut souhaiter
changer ce caractère. Par exemple, pour forcer tous les caractères en majuscules
dans un éditeur. Dans un cas comme celui-là, l’utilisateur doit définir le
gestionnaire suivant pour gérer les frappes de touches :
procedure TForm1.Edit1KeyPressed(Sender: TObject; var Key: Char);
begin
Key := UpCase(Key);
end;
Vous pouvez également utiliser les paramètres var pour permettre à l’utilisateur
de surcharger la gestion par défaut.
Comme les événements standard de TControl, les événements des contrôles fenêtrés
disposent de méthodes correspondantes.
procedure TMyControl.Click;
begin
inherited Click; { exécute la gestion standard, y compris l’appel au gestionnaire}
... { vos modifications s’insèrent ici}
end;
Déclenchement de l’événement
Vous avez besoin de savoir ce qui a déclenché l’événement. Pour certains
événements, la réponse est évidente. Par exemple, un événement associé à
l’enfoncement du bouton de souris se produit lorsque l’utilisateur clique avec le
bouton gauche de la souris provoquant l’envoi par Windows d’un message
WM_LBUTTONDOWN à l’application. La réception de ce message provoque l’appel
de la méthode MouseDown d’un composant qui à son tour appelle le code que
l’utilisateur a associé à l’événement OnMouseDown.
Néanmoins, certains événements sont liés de façon moins évidente à des
occurrences externes moins spécifiques. Par exemple, une barre de défilement
dispose d’un événement OnChange qui peut être déclenché par plusieurs
occurrences, telles des frappes de touche, des clics de souris, ou des modifications
dans d’autres contrôles. Lorsque vous définissez vos événements, assurez-vous que
les occurrences appellent tous les événements appropriés.
Notifications simples
Un événement de type notification ne fait qu’indiquer qu’un événement particulier
s’est produit sans fournir aucune information sur le moment et l’endroit où il s’est
produit. Les notifications utilisent le type TNotifyEvent, qui véhiculent un
paramètre unique correspondant à l’émetteur de l’événement. Les seuls éléments
“connus” du gestionnaire associé à une notification sont donc le type d’événement
et le composant impliqué. Par exemple, les événements clic de souris sont des
notifications. Lorsque vous écrivez un gestionnaire pour un événement de ce type,
vous ne récupérez que deux informations : le fait qu’un clic s’est produit et le
composant impliqué.
Une notification est un processus à sens unique. Il n’existe aucun mécanisme
pour renvoyer une information en retour ou pour inhiber la gestion d’une
notification.
Déclaration de l’événement
Une fois déterminé le type de votre gestionnaire d’événement, vous pouvez déclarer
le pointeur de méthode et la propriété pour l’événement. N’oubliez pas d’attribuer
un nom à l’événement qui soit à la fois significatif et descriptif pour que
l’utilisateur puisse comprendre son rôle. Dans la mesure du possible, choisissez des
noms de propriétés qui ressemblent à ceux de composants déjà définis.
Appel de l’événement
Il est préférable de centraliser tous les appels à un événement. Autrement dit, créez
une méthode virtuelle dans votre composant qui appelle le gestionnaire
d’événement de l’application (s’il a été défini) et qui fournit une gestion par défaut.
Le fait de rassembler tous les appels à un événement en un seul endroit vous
permet d’être sûr qu’un programmeur, qui dérive un nouveau composant à
partir du vôtre, pourra personnaliser la gestion de l’événement en surchargeant
cette méthode sans avoir à parcourir votre code pour repérer les endroits où
l’événement est appelé.
Deux autres considérations sont à prendre en compte concernant l’appel de
l’événement :
• Les gestionnaires vides doivent être valides.
• Les utilisateurs peuvent surcharger la gestion par défaut.
34
Création de méthodes
Chapter 34
Les méthodes des composants sont des procédures et des fonctions intégrées
dans la structure d’une classe. Il n’existe pratiquement aucune restriction sur ce
que peuvent réaliser les méthodes d’un composant, mais Delphi n’en respecte
pas moins un certain nombre de standards qu’il est préférable de suivre. Ce
sont :
• Eviter les interdépendances
• Noms des méthodes
• Protection des méthodes
• Rendre virtuelles des méthodes
• Déclaration des méthodes
En général, les composants ne doivent pas contenir beaucoup de méthodes et
vous devez chercher à minimiser le nombre des méthodes appelées par une
application. Il est préférable d’encapsuler sous la forme de propriétés des
caractéristiques qu’il serait tentant d’implémenter sous forme de méthodes. Les
propriétés fournissent une interface qui s’inscrit parfaitement dans
l’environnement Delphi et sont accessibles au moment de la conception.
Méthodes abstraites
Une méthode est parfois déclarée abstract dans un composant Delphi. Dans le
VCL, les méthodes abstraites ne se produisent que dans les classes dont les noms
commencent par “custom”, comme dansTCustomGrid. De telles classes sont
elles-mêmes abstraites, au sens où elles ne servent qu’à la dérivation de classes
descendantes.
Vous ne pouvez pas créer d’objet instance d’une classe qui contient un membre
abstrait. La directive abstract est utilisée pour indiquer des parties de classes qui
doivent être surfacées et définies dans des composants descendants ; cela force
les écrivains de composants à redéclarer le membre abstrait dans des classes
descendantes avant que des instances actuelles de la classe puissent être créées.
implementation
ƒ
procedure TSampleComponent.MakeBigger; { implémente la première méthode}
begin
Height := Height + 5;
Width := Width + 5;
end;
function TSampleComponent.CalculateArea: Integer; { implémente la deuxième méthode}
begin
Result := Width * Height;
end;
Graphiques et composants
Chapter 35
35
Windows fournit une puissante interface GDI (Graphics Device Interface) servant
à dessiner des graphiques indépendamment des périphériques.
Malheureusement, GDI impose au programmeur des contraintes supplémentaires
telles que la gestion des ressources graphiques. Delphi prend en charge toutes
ces tâches GDI ingrates, vous laisse vous concentrer sur le travail productif, vous
épargnant les recherches de handles perdus ou de ressources non restituées.
De même que toute partie de l’API Windows, vous pouvez appeler les fonctions
GDI directement depuis votre application Delphi. Toutefois, vous vous rendrez
vite compte que l’utilisation de l’encapsulation Delphi’s des fonctions graphiques
est un moyen plus efficace et plus rapide de créer des graphiques.
Les rubriques de cette section comprennent :
• Présentation des graphiques
• Utilisation du canevas
• Travail sur les images
• Bitmaps hors écran
• Réponse aux changements
Utilisation du canevas
La classe canevas encapsule les graphiques Windows à plusieurs niveaux, allant
des fonctions de haut niveau (pour dessiner des lignes, des formes et du texte)
aux accès GDI de bas niveau, en passant par les propriétés de niveau
intermédiaire, pour manipuler les moyens de dessin du canevas.
Le tableau suivant résume les possibilités du canevas.
Pour plus d’informations sur les classes canevas, leurs méthodes et leurs
propriétés, reportez-vous à l’aide en ligne.
Les trois sujets suivants sont nécessaires à la compréhension du travail sur les
images dans Delphi :
• Utilisation d’une image, d’un graphique ou d’un canevas
• Chargement et stockage des graphiques
• Gestion des palettes
Pour répondre aux modifications d’un objet graphique, vous devez associer une
méthode à l’événement OnChange de sa classe.
Le composant forme publie les propriétés représentant le crayon et le pinceau
qu’il utilise pour tracer sa forme. Le constructeur du composant associe une
méthode à l’événement OnChange de chacun, ce qui a pour effet de provoquer le
rafraîchissement de l’image du composant si le crayon ou le pinceau sont
modifiés :
type
TShape = class(TGraphicControl)
public
procedure StyleChanged(Sender: TObject);
end;
ƒ
implementation
ƒ
constructor TShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appelle toujours le constructeur hérité ! }
Width := 65;
Height := 65;
FPen := TPen.Create; { construit le crayon}
FPen.OnChange := StyleChanged; { affecte la méthode à l’événement OnChange }
FBrush := TBrush.Create; { construit le pinceau}
FBrush.OnChange := StyleChanged; { affecte la méthode à l’événement OnChange }
end;
procedure TShape.StyleChanged(Sender: TObject);
begin
Invalidate(); { détruit et redessine le composant }
end;
protected
procedure CMChangeColor(var Message: TMessage); message CM_CHANGECOLOR;
end;
procedure TMyComponent.CMChangeColor(var Message: TMessage);
begin
Color := Message.lParam;
inherited ;
end;
Tableau 37.2 Méthodes pour lire et écrire les valeurs des propriétés
Type de propriété Méthode Get Méthode Set
Virgule flottante GetFloatValue SetFloatValue
Pointeur de méthode (événement) GetMethodValue SetMethodValue
Type ordinal GetOrdValue SetOrdValue
Chaîne GetStrValue SetStrValue
Lorsque vous surchargez une méthode GetValue, appelez l’une des méthodes
“Get”. Lorsque vous surchargez SetValue, appelez l’une des méthodes “Set”.
Les propriétés Color sont plus polyvalentes que la plupart des autres propriétés,
l’utilisateur dispose de plusieurs moyens pour sélectionner une couleur dans
l’inspecteur d’objets : il peut taper une valeur, sélectionner dans une liste ou faire
appel à l’éditeur personnalisé. C’est pourquoi la méthode GetAttributes de
TColorProperty, inclut plusieurs attributs dans la valeur qu’elle renvoie :
function TColorProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paMultiSelect, paDialog, paValueList];
end;
begin
FontDlg := TFontDialog.Create(Application);
try
if FontDlg.Execute then
MyComponent.FFont.Assign(FontDlg.Font);
finally
FontDlg.Free
end;
end;
Remarque Si vous souhaitez qu’un double-clic sur le composant affiche l’éditeur de code
d’un gestionnaire d’événement, utilisez TDefaultEditor comme classe de base pour
votre éditeur de composants au lieu de TComponentEditor. Puis, au lieu de
surcharger la méthode Edit, surchargez la méthode protégée
TDefaultEditor.EditProperty. EditProperty recherche les gestionnaires d’événement
du composant et affiche le premier qu’il trouve. Vous pouvez modifier ce
comportement pour visualiser un événement particulier. Par exemple :
procedure TMyEditor.EditProperty(PropertyEditor: TPropertyEditor;
Continue, FreeEditor: Boolean)
begin
if (PropertyEditor.ClassName = ‘TMethodProperty’) and
(PropertyEditor.GetName = ‘OnSpecialEvent’) then
// DefaultEditor.EditProperty(PropertyEditor, Continue, FreeEditor);
end;
Surcharge du constructeur
Lorsque vous placez un composant dans une fiche au moment de la conception ou
lorsqu’une application en cours d’exécution construit un composant, le constructeur
du composant définit les valeurs des propriétés. Quand un composant est chargé
depuis un fichier fiche, l’application définit toutes les propriétés qui ont été
modifiées lors de la conception.
Déclaration de la propriété
Généralement, pour déclarer une propriété, vous déclarez une donnée membre
privée pour stocker les données de la propriété puis vous spécifiez les méthodes
pour lire et/ou écrire sa valeur. Souvent, la méthode pour lire la valeur n’est pas
nécessaire car un simple pointage sur la valeur stockée suffit.
S’agissant de notre contrôle forme, vous aurez à déclarer une donnée membre
contenant la forme courante, puis à déclarer une propriété qui lit et écrit cette
donnée membre et écrit cette donnée membre via un appel de méthode.
Ajoutez les déclarations suivantes dans TSampleShape:
type
TSampleShape = class(TGraphicControl)
private
FShape: TSampleShapeType; { donnée membre pour contenir la valeur de la propriété }
procedure SetShape(Value: TSampleShapeType);
published
property Shape: TSampleShapeType read FShape write SetShape;
end;
Il ne vous reste plus qu’à ajouter l’implémentation de SetShape.
Dans notre exemple, le contrôle forme définit sa taille par un carré de 65 pixels
de côté.
Ajoutez le constructeur surchargé dans la déclaration de la classe composant :
type
TSampleShape = class(TGraphicControl)
public { constructeurs toujours publics }
constructor Create(AOwner: TComponent); override { surcharger la directive }
end;
1 Redéclarez les propriétés Height et Width avec leurs nouvelles valeurs par
défaut :
type
TSampleShape = class(TGraphicControl)
ƒ
published
property Height default 65;
property Width default 65;
end;
2 Ecrivez le nouveau constructeur dans la partie implémentation de l’unité :
constructor TSampleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appelle toujours le constructeur hérité }
Width := 65;
Height := 65;
end;
Les données membres des objets ayant un propriétaire sont presque toujours
déclarés private. Si des applications (ou d’autres composants) ont besoin
d’accéder aux objets ayant un propriétaire, vous devez pour cela déclarer des
propriétés publiées ou publiques.
Ajoutez des données membres pour le crayon et le pinceau de votre contrôle forme :
type
TSampleShape = class(TGraphicControl)
private { les données membres sont presque toujours privées }
FPen: TPen; { donnée membre pour l’objet crayon }
FBrush: TBrush; { donnée membre pour l’objet pinceau }
ƒ
end;
implementation
ƒ
constructor TSampleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appelez toujours le constructeur hérité }
Width := 65;
Height := 65;
FPen := TPen.Create; { construit le crayon }
FPen.OnChange := StyleChanged; { affecte la méthode à l’événement OnChange }
FBrush := TBrush.Create; { construit le pinceau }
FBrush.OnChange := StyleChanged; { affecte la méthode à l’événement OnChange }
end;
procedure TSampleShape.StyleChanged(Sender: TObject);
begin
Invalidate(True); { efface et redessine le composant }
end;
Ces modifications faites, le composant se redessine pour refléter tout changement
du crayon ou du pinceau.
property Ctl3D;
property Font;
property GridLineWidth;
property ParentColor;
property ParentFont;
property OnClick; { événements publiés }
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
end;
Il existe bien d’autres propriétés ne s’appliquant pas à un calendrier qui sont
publiables, par exemple la propriété Options qui permet à l’utilisateur de choisir les
lignes de la grille à dessiner.
Si vous installez le composant calendrier modifié dans la palette des composants
et l’utilisez dans une application, vous trouverez bien d’autres propriétés et
événements opérationnels. Nous allons maintenant commencer à ajouter de
nouvelles fonctionnalités au composant.
begin
inherited Create(AOwner); { appelle le constructeur hérité }
ColCount := 7; { toujours 7 jours/semaine }
RowCount := 7; { toujours 6 semaines plus les titres }
FixedCols := 0; { aucun libellé de ligne }
FixedRows := 1; { une ligne pour les noms de jour }
ScrollBars := ssNone; { pas de défilement nécessaire }
Options := Options - [goRangeSelect] + [goDrawFocusSelected]; {désactive la sélection
// d’intervalle}
end;
Le calendrier a dorénavant sept colonnes et sept lignes, avec la ligne de titre fixe
(ou qui ne défile pas).
Suivi de la date
Pour que le contrôle calendrier soit utile, les utilisateurs ainsi que les applications
doivent disposer d’un moyen de définir la date, le mois et l’année. Delphi stocke
les dates et les heures dans des variables de type TDateTime. TDateTime est une
représentation numérique encodée des dates et des heures particulièrement pratique
pour être manipulée par un programme mais peu commode à interpréter par un
utilisateur.
Vous pouvez donc stocker la date du calendrier sous une forme encodée et fournir
un accès direct à cette valeur lors de l’exécution, mais vous pouvez aussi fournir
les propriétés Day, Month et Year que l’utilisateur du composant peut définir lors
de la conception.
Le suivi de la date dans le calendrier comprend les traitements suivants :
• Stockage interne de la date
• Accès au jour, au mois et à l’année
• Génération des numéros de jours
• Sélection du jour en cours
Pour fournir un accès lors de la conception aux éléments jour, mois et année,
procédez de la façon suivante :
1 Déclarez les trois propriétés, en leur attribuant à chacune un numéro unique
d’index :
type
TSampleCalendar = class(TCustomGrid)
public
property Day: Integer index 3 read GetDateElement write SetDateElement;
property Month: Integer index 2 read GetDateElement write SetDateElement;
property Year: Integer index 1 read GetDateElement write SetDateElement;
ƒ
2 Déclarez et écrivez les méthodes d’implémentation, définissant les différents
éléments pour chaque valeur d’index :
type
TSampleCalendar = class(TCustomGrid)
private
function GetDateElement(Index: Integer): Integer; { notez le paramètre Index }
procedure SetDateElement(Index: Integer; Value: Integer);
ƒ
function TSampleCalendar.GetDateElement(Index: Integer): Integer;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(FDate, AYear, AMonth, ADay); { éclate la date encodée en éléments }
case Index of
1: Result := AYear;
2: Result := AMonth;
3: Result := ADay;
else Result := -1;
end;
end;
procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);
var
AYear, AMonth, ADay: Word;
begin
if Value > 0 then { tous les éléments doivent être positifs }
begin
DecodeDate(FDate, AYear, AMonth, ADay); { récupère les éléments courants de la date}
case Index of { définit le nouvel élément selon l’index }
1: AYear := Value;
2: AMonth := Value;
3: ADay := Value;
else Exit;
end;
FDate := EncodeDate(AYear, AMonth, ADay); { encodage de la date modifiée }
Refresh; { mise à jour du calendrier visible }
end;
end;
procedure TCalendar.PrevMonth;
begin
DecodeDate(IncMonth(CalendarDate, -1), Year, Month, Day);
end;
procedure TCalendar.NextYear;
begin
DecodeDate(IncMonth(CalendarDate, 12), Year, Month, Day);
end;
procedure TCalendar.PrevYear;
begin
DecodeDate(CalendarDate, -12), Year, Month, Day);
end;
N’oubliez pas d’ajouter les déclarations des nouvelles méthodes à la déclaration de
la classe.
Désormais, si vous créez une application qui utilise le composant calendrier, vous
pourrez facilement implémenter le passage de mois en mois ou d’année en année.
Déplacement de la sélection
Le comportement reçu en héritage d’une grille gère le déplacement de la sélection
en réponse aux touches de direction enfoncées ou aux clics de souris. Pour modifier
le jour sélectionné, vous devez modifier le comportement implicite.
Pour gérer les déplacements à l’intérieur du calendrier, vous devez surcharger la
méthode Click de la grille.
Lorsque vous surchargez une méthode telle que Click, en dépendance étroite avec
les interactions de l’utilisateur, vous devez pratiquement toujours inclure un appel à
la méthode reçue en héritage pour ne pas perdre le comportement standard.
Le code suivant est une méthode Click surchargée pour la grille calendrier.
N’oubliez pas d’ajouter la déclaration de Click à TSampleCalendar, en incluant après
la directive override.
procedure TSampleCalendar.Click;
var
TempDay: Integer;
begin
inherited Click; { n’oubliez pas d’appeler la méthode héritée ! }
TempDay := DayNum(Col, Row); { récupère le numéro du jour de la cellule cliquée }
if TempDay <> -1 then Day := TempDay; { change le jour s’il est valide }
end;
begin
MyMouseDown := OnMouseDown;
if Assigned(MyMouseDown then MyMouseDown(Self, Button, Shift, X, Y);
end;
end;
Lorsque MouseDown répond à un message indiquant la manipulation de la
souris, la méthode MouseDown héritée est appelée uniquement si la propriété
ReadOnly du contrôle est False et si l’objet lien de données est en mode édition,
c’est-à-dire si le champ peut être modifié. Si le champ ne peut être modifié, c’est
le code mis par le programmeur dans le gestionnaire de l’événement
OnMouseDown, s’il en existe un, qui est exécuté.
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TAboutBoxDlg]);
end;
end.
Pour l’instant, le nouveau composant possède uniquement les fonctionnalités
intégrées à TComponent. C’est le composant non visuel le plus simple. Dans la
section suivante, vous allez créer l’interface entre le composant et la boîte de
dialogue.
Les propriétés d’un composant enveloppe sont sensiblement plus simples à écrire
que celles d’un composant standard. Souvenez-vous que vous ne faites que créer
des données permanentes que l’enveloppe et la boîte de dialogue peuvent
échanger. En définissant ces données sous la forme de propriétés, vous donnez
aux développeurs la possibilité de définir des données au moment de la
conception qui, lors de l’exécution, seront transmises par l’enveloppe à la boîte
de dialogue.
La déclaration d’une propriété d’interface nécessite deux ajouts à la déclaration
de classe du composant :
• Une donnée membre private, qui est une variable utilisée par l’enveloppe
pour stocker la valeur de la propriété
• La déclaration published de la propriété elle-même qui indique son nom et la
donnée membre de stockage à utiliser
De telles propriétés d’interface n’ont pas besoin de méthodes d’accès. Elles
accèdent directement aux données stockées. Par convention, la donnée membre
qui stocke la valeur de la propriété porte le même nom que la propriété, mais
précédé de la lettre F. La donnée membre et la propriété doivent avoir le même
type.
Par exemple, la déclaration d’une propriété d’interface de type entier appelée
Year, est la suivante :
type
TMyWrapper = class(TComponent)
private
FYear: Integer; { donnée membre pour les données de la propriété Year}
published
property Year: Integer read FYear write FYear; { la propriété et son stockage }
end;
S’agissant de votre boîte A propos de, vous devez disposer de quatre propriétés
de type string pour le nom du produit, les informations de version, les
informations de copyright et les commentaires éventuels.
type
TAboutBoxDlg = class(TComponent)
private
FProductName, FVersion, FCopyright, FComments: string; { déclare les
//données membres}
published
property ProductName: string read FProductName write FProductName;
property Version: string read FVersion write FVersion;
property Copyright: string read FCopyright write FCopyright;
property Comments: string read FComments write FComments;
end;
Si vous installez votre composant dans la palette des composants et si vous le
placez dans une fiche, vous pourrez définir les propriétés, et ces valeurs
apparaîtront de façon permanente dans la fiche. Ainsi, lors de l’exécution de la
boîte de dialogue qu’il enveloppe, le composant pourra les utiliser.
Test du composant
Une fois le composant boîte de dialogue installé, vous pouvez l’utiliser comme
n’importe quelle autre boîte de dialogue commune, en le plaçant sur une fiche et
en l’exécutant. Un moyen rapide de vérifier le fonctionnement de la boîte A
propos de consiste à ajouter un bouton de commande dans une fiche et à
exécuter la boîte de dialogue lorsque l’utilisateur clique sur ce bouton.
Par exemple, si vous avez créé une boîte de dialogue A propos de, et si vous
l’avez ajouté à la palette des composants, vous pouvez tester son fonctionnement
en suivant les étapes ci-dessous :
1 Créez un nouveau projet.
2 Placez un composant A propos de dans la fiche principale.
3 Placez un bouton de commande dans la fiche.
4 Double-cliquez sur le bouton de commande pour créer un gestionnaire
d’événements vide.
5 Dans le gestionnaire d’événements, entrez la ligne de code suivante :
AboutBoxDlg1.Execute;
6 Exécutez l’application.
V
Développement d’applications COM
Part V
Extensions de COM
COM a évolué et a été étendu au-delà des services de base. COM sert de
fondement à d’autres technologies, comme l’Automation (autrefois appelée
Automation OLE), aux contrôles ActiveX et aux documents Active. Pour plus de
détails, voir “Extensions de COM” à la page 43-9.
En outre, vous pouvez désormais créer un objet COM qui fonctionne dans
l’environnement MTS (Microsoft Transaction Server). MTS est un système de
traitement des transactions basé sur les composants, permettant de construire,
déployer et gérer de grosses applications serveur intranet et Internet. Bien que
MTS ne fasse pas partie de l’architecture COM, il a été conçu pour étendre les
capacités de COM dans un vaste environnement distribué. Pour plus
d’informations sur MTS, voir chapitre 49, “Création des objets MTS”.
Delphi fournit des experts permettant d’implémenter facilement des applications
qui incorporent toutes ces technologies dans l’environnement Delphi. Pour plus
de détails, voir “Implémentation des objets COM à l’aide d’experts” à la
page 43-16
Interface COM Le moyen par lequel un objet expose ses services aux
clients. Un objet COM fournit une interface pour chaque
ensemble de méthodes (fonctions membre) et de propriétés
(membres de données et/ou contenu) connexes.
Serveur COM Un module, EXE, DLL ou OCX, contenant le code d’un
objet COM. Les implémentations d’objets résident sur les
serveurs. Un objet COM implémente une ou plusieurs
interfaces.
Client COM Le code appelant les interfaces afin d’obtenir du serveur les
services demandés. Les clients savent ce qu’ils veulent
obtenir du serveur (via l’interface) ; les clients ne savent pas
comment en interne le serveur fournit les services. Le client
COM le plus courant à implémenter est un contrôleur
Automation.
Interfaces COM
Les clients COM communiquent avec des objets par le biais d’interfaces COM.
Les interfaces sont des groupes de routines, liées par la logique ou par la
sémantique, qui assurent la communication entre le fournisseur d’un service
(objet serveur) et ses clients. Voici la représentation standard d’une interface
COM :
Figure 43.1 Une interface COM
Par exemple, chaque objet COM implémente l’interface de base, IUnknown, qui
indique au client les interfaces qui sont disponibles sur le client.
Les objets peuvent avoir plusieurs interfaces, où chacune implémente une
fonctionnalité. L’interface est le moyen de mettre à disposition du client le
service fournit par l’objet, sans lui donner les détails de l’implémentation sur la
façon dont ce service est fournit.
Les aspects majeurs des interfaces COM sont les suivants :
• Une fois publiées, les interfaces sont immuables ; c’est-à-dire qu’elles ne
changent plus. Une interface permet d’accéder à un ensemble précis de
fonctions. Les fonctionnalités supplémentaires sont fournies par le biais
d’interfaces supplémentaires.
• Par convention, les identificateurs d’interfaces COM commencent par un
I majuscule suivi d’un nom symbolique définissant l’interface, comme IMalloc
ou IPersist.
• L’identification unique des interfaces est garantie par l’usage d’un GUID
(Globally Unique Identifier), qui est un nombre aléatoire de 128 bits. Les
GUID utilisés pour identifier les interfaces sont appelés IID (Identificateurs
d’interfaces). Ils permettent d’éliminer les conflits de noms entre différentes
versions d’un produit ou différents produits.
• Les interfaces sont indépendantes du langage. Vous pouvez utiliser n’importe
quel langage pour implémenter une interface COM, à condition que ce
langage supporte les structures de pointeurs et puisse appeler une fonction via
un pointeur, de façon explicite ou implicite.
• Les interfaces ne sont pas elles-mêmes des objets ; elles fournissent l’accès à
un objet. Donc, les clients n’ont pas accès directement aux données ; ils
accèdent aux données par le biais d’un pointeur d’interface.
• Les interfaces sont toujours dérivées de l’interface de base, IUnknown.
• Les interfaces peuvent être redirigées par COM via des proxy pour permettre
aux appels aux méthodes de l’interface de s’effectuer entre différents threads,
processus et machines en réseau, sans que les objets client ou serveur ne
soient jamais informés de la redirection.
Les clients obtiennent des pointeurs sur d’autres interfaces via la méthode
QueryInterface de IUnknown. QueryInterface connaît chaque interface de l’objet
serveur et peut donner au client un pointeur vers l’interface demandée. Comme
il reçoit un pointeur vers une interface, le client est assuré de pouvoir appeler
n’importe quelle méthode de l’interface.
Les objets contrôlent leur propre durée de vie grâce aux méthodes AddRef et
Release de IUnknown, qui sont de simples méthodes de décompte de références.
Tant que le décompte de références est différent de zéro, l’objet reste en
mémoire. Dès qu’il atteint zéro, l’implémentation de l’interface peut en toute
sécurité disposer du ou des objets sous-jacents.
Serveurs COM
Un serveur COM est une application ou une bibliothèque qui fournit des
services à une application ou bibliothèque client. Un serveur COM est constitué
d’un ou de plusieurs objets COM, un objet COM étant un ensemble de
propriétés (données membre ou contenu) et de méthodes (fonctions membre).
Les clients ne savent pas comment l’objet COM effectue son service ;
l’implémentation de l’objet est encapsulée. Un objet met ses services à disposition
par le biais de son interface comme décrit précédemment.
En outre, les clients n’ont pas besoin de savoir où réside l’objet COM. COM
fournit un accès transparent quel que soit l’emplacement de l’objet.
Quand il demande un service à un objet COM, le client transmet un
identificateur de classe (CLSID) à COM, qui localise l’implémentation appropriée
du serveur, amène le code en mémoire, et fait créer par le serveur une instance
de l’objet pour le client. Un serveur COM doit donc fournir un objet fabricant de
classe (IClassFactory) qui crée sur demande des instances d’objet. (Le CLSID est
basé sur le GUID de l’interface.)
En général, un serveur COM doit effectuer ceci :
• Recenser des entrées dans le registre système pour associer le module serveur
à l’identificateur de classe (CLSID).
• Implémenter un objet fabricant de classe, qui est un type d’objet spécial qui
fabrique un autre objet d’un CLSID particulier.
• Exposer le fabricant d’objet à COM.
• Fournir un mécanisme de déchargement grâce auquel un serveur qui ne sert
pas de client pourra être supprimé de la mémoire.
Remarque Les experts de Delphi automatisent la création des objets et des serveurs COM
comme décrit dans “Implémentation des objets COM à l’aide d’experts” à la
page 43-16.
Comme illustré dans la figure suivante, pour les serveurs en processus, les
pointeurs sur les interfaces de l’objet sont dans le même espace processus que le
client, et COM fait des appels directs dans l’implémentation de l’objet.
Figure 43.3 Serveurs en processus
Comme illustré dans la figure suivante, quand le processus est soit différent, soit
sur une autre machine, COM utilise un proxy pour initier les appels de
procédure distants. Le proxy réside dans le même processus que le client, de
sorte que vu du client, tous les appels à des interfaces semblent pareils. Le proxy
intercepte l’appel du client et le transmet la où l’objet réel s’exécute. Le
mécanisme qui permet aux clients d’accéder aux objets d’un espace processus
différent, ou même d’une machine différente, comme s’ils se trouvaient dans leur
propre processus, est appelé le marshaling.
La différence entre les serveurs hors processus et distants est le type de
communication inter-processus utilisé. Le proxy utilise COM pour communiquer
avec un serveur hors processus et COM distribué (DCOM) pour communiquer
avec une machine distante.
Figure 43.4 Serveurs hors processus et distants
Le mécanisme du marshaling
Le marshaling est le mécanisme qui permet à un client de faire des appels aux
fonctions de l’interface d’objets distants qui se trouvent dans un autre processus
ou sur une autre machine. Le marshaling
• Prend un pointeur d’interface dans le processus du serveur et rend un
pointeur de proxy disponible au code dans le processus du client.
• Prend les arguments d’un appel à l’interface passés depuis le client et les
place dans l’espace processus de l’objet distant.
Pour tout appel à l’interface, le client met les arguments sur une pile et émet un
appel à une fonction via le pointeur d’interface. Si l’appel à l’objet n’est pas en
processus, il est passé au proxy. Celui-ci compresse les arguments dans un
paquet de marshaling et transmet la structure à l’objet distant. Le stub de l’objet
décompresse le paquet, place les arguments sur la pile et appelle
l’implémentation de l’objet. L’objet recrée l’appel du client dans son propre
espace d’adressage.
Le type de marshaling dépend de ce que l’objet COM implémente. Les objets
peuvent utiliser le mécanisme de marshaling standard fourni par l’interface
IDispatch. C’est un mécanisme de marshaling générique qui permet la
communication via un appel standard à un procédure distante (RPC). Pour plus
de détails sur l’interface IDispatch, voir le chapitre 46, “Création d’un serveur
Automation”.
Les objets peuvent fournir leur propre marshaling personnalisé, pour avoir le
contrôle complet de la communication entre processus et machines. Mais, cette
forme de marshaling personnalisé est difficile et peu courante. Le répertoire
demos\ActiveX contient un exemple de marshaling personnalisé, TimeServ. Pour
localiser le programme exemple, reportez-vous au fichier Lisezmoi de ce répertoire.
Remarque Une autre technologie Microsoft, MTS (Microsoft Transaction Server), apporte
un support supplémentaire pour les objets distants. Pour plus de détails, voir le
chapitre 49, “Création des objets MTS”.
Clients COM
Il est important de concevoir une application COM dans laquelle ce sont les
clients qui déterminent la façon dont les objets sont utilisés ; les objets serveur ne
sont pas concernés par l’utilisation qu’en fait le client. Celui-ci connaît ce qu’un
objet peut fournir via ses interfaces. En outre, les clients n’ont pas besoin de
savoir comment (ou même où) un objet fournit ses services ; c’est le problème de
l’objet de fournir le service publié par le biais de l’interface.
Un client COM typique est le contrôleur Automation. Le contrôleur Automation
est la partie de l’application qui a la vue la plus complète des objectifs de
l’application. Il connaît le type d’information dont elle a besoin des divers objets
du serveur et il demande les services lorsque c’est nécessaire.
Pour plus de détails sur la création d’un contrôleur Automation, voir le
chapitre 45, “Création d’un contrôleur Automation”.
Extensions de COM
COM a été initialement conçu pour fournir une fonctionnalité de communication
de base et permettre l’enrichissement de cette fonctionnalité via des extensions.
COM, lui-même, a étendu sa fonctionnalité première en définissant des
ensembles spécialisés d’interfaces couvrant des besoins spécifiques.
Les extensions de COM continuent d’évoluer. Au début, les technologies et les
services OLE ont été développés pour offrir une variété de services destinés au
développement d’applications Windows.
Aujourd’hui, Microsoft a consolidé ses technologies OLE et OCX sous le terme
ActiveX. ActiveX est une technologie permettant aux objets COM d’être plus
compacts et plus efficaces, ce qui est indispensable aux applications tournant sur
des réseaux de taille importante.
Bientôt, Microsoft pourra incorporer au modèle COM certaines des technologies
MTS qui permettront de construire de complexes applications Internet et intranet.
Le tableau suivant est un résumé des extensions de services que COM fournit
actuellement. Les sections suivantes décrivent ces services en détail.
Contrôles ActiveX
Les contrôles ActiveX sont des contrôles visuels qui exécutent seulement des
serveurs en processus, et peuvent être incorporés dans une application conteneur
de contrôles ActiveX. Ce ne sont pas eux-mêmes des applications complètes,
mais de simples contrôles OLE préfabriqués réutilisables dans diverses
applications. Les contrôles ActiveX utilisent l’Automation pour exposer leurs
propriétés, méthodes et événements. Leurs fonctionnalités incluent la capacité à
déclencher des événements, la liaison aux sources de données et la gestion de
licence.
De plus en plus fréquemment, les contrôles ActiveX s’utilisent dans un site Web
comme objets interactifs placés dans une page Web. Ainsi, ActiveX est devenu
un standard particulièrement destiné à des contenus interactifs pour le Web, y
compris l’utilisation de documents ActiveX employés pour visualiser des
documents non HTML via un navigateur Web. Pour plus d’informations sur la
technologie ActiveX, voir le site Web de Microsoft.
Les experts de Delphi facilitent la création des contrôles ActiveX. Pour plus
d’informations sur la création et l’utilisation de ces types d’objets, voir le
chapitre 47, “Création d’un contrôle ActiveX”.
Bibliothèques de types
Les bibliothèques de types offrent un moyen d’obtenir davantage d’informations
de type sur un objet que les interfaces de l’objet. Les bibliothèques de types
contiennent les informations nécessaires sur les objets et leurs interfaces, comme
les interfaces associées à tels objets (étant donné le CLSID), les fonctions membre
de chaque interface et les arguments requis par ces fonctions.
Vous pouvez obtenir les informations de type en interrogeant une instance d’un
objet pendant qu’elle s’exécute ou, en chargeant et en lisant les bibliothèques de
types. Grâce à ces informations, vous pouvez implémenter un client pour qu’il
utilise un objet souhaité, en sachant exactement les fonctions membre dont vous
avez besoin, et ce qu’il faut passer à ces fonctions.
Les clients des serveurs Automation et des contrôles ActiveX s’attendent à
trouver ces informations de type. Les experts Automation et ActiveX génèrent
automatiquement une bibliothèque de types.Vous pouvez voir ou modifier ces
informations de type en utilisant l’éditeur de bibliothèques de types, comme
décrit dans le chapitre 48, “Utilisation des bibliothèques de types”.
Cette section décrit le contenu d’une bibliothèque de types, comment la créer,
quand l’utiliser et comment y accéder. Pour les développeurs souhaitant partager
des interfaces à travers divers langages, la section se termine par des suggestions
sur l’utilisation des outils de gestion de bibliothèques de types.
Interface Description
ITypeLib Fournit des méthodes pour accéder à la description d’une bibliothèque
de types.
ITypeInfo Fournit la description de chaque objet d’une bibliothèque de types. Par
exemple, un navigateur utilise cette interface pour extraire des
informations sur les objets de la bibliothèque de types.
ITypeComp Fournit un moyen rapide d’accéder aux informations dont le
compilateur a besoin lors de la liaison avec une interface.
• La fonction RegisterTypeLib peut être utilisée pour recenser vos objets présentés
dans la base de données de recensement.
• La fonction UnRegisterTypeLib peut être utilisée pour désinstaller complètement
la bibliothèque de types d’une application du registre.
• L’accès local au serveur est accéléré car l’automation utilise les informations
de la bibliothèque de types pour regrouper les paramètres qui sont passés à
un objet d’un autre processus.
Documents Active
Les documents Active (appelés auparavant documents OLE) sont un ensemble de
services COM supportant la liaison et l’incorporation, le glisser-déplacer et
l’édition visuelle. Les documents Active intègrent de façon transparente des
données ou des objets de différents formats, par exemple des clips sonores, des
feuilles de calcul, du texte et des images.
Contrairement aux contrôles ActiveX, les documents Active ne sont pas limités
aux serveurs en processus ; ils peuvent être utilisés dans des applications inter-
processus.
A la différence des objets Automation, qui ne sont presque jamais visuels, les
objets document Active peuvent être visuellement actifs dans une autre
application. Ils sont associés à deux types de données : les données de
représentation qui sont utilisées pour l’affichage visuel à l’écran ou sur un
périphérique de sortie et les données natives utilisées pour modifier l’objet.
Les objets document Active peuvent être des conteneurs ou des serveurs de
documents. Bien que Delphi ne fournisse pas d’expert pour créer
automatiquement des documents Active, vous pouvez utiliser la classe
TOleContainer de la VCL pour supporter la liaison et l’incorporation dans les
documents Active existants.
Vous pouvez aussi utiliser TOleContainer comme base d’un conteneur de
document Active. Pour créer des objets pour les serveurs de documents Active,
utilisez une des classes de base COM de la VCL et implémentez les interfaces
appropriées à ce type d’objet, en fonction des services que l’objet doit gérer. Pour
plus d’informations sur la création et l’utilisation de serveurs de documents
Active, voir le site Web Microsoft.
Remarque Bien que la spécification des documents Active contienne une gestion intégrée du
marshaling des applications à processus croisé, les documents Active ne
s’exécutent pas sur des serveurs distants car les types qu’ils utilisent (handles de
fenêtre, de menu, etc.) sont spécifiques à un système sur une machine donnée.
Les experts automatisent les tâches intervenant dans la création de chaque type
d’objet. Les experts fournissent les interfaces COM requises pour chaque type
d’objet. Comme le montre la figure 43.6, avec un simple objet COM, l’expert
implémente la seule interface COM obligatoire, IUnknown, qui fournit un
pointeur d’interface vers l’objet.
Figure 43.6 Interface d’un objet COM simple
Comme le montre la figure 43.7, pour les objets Automation, l’expert implémente
IUnknown et IDispatch, qui fournissent le marshaling automatique.
Figure 43.7 Interfaces d’un objet Automation
Comme le montre la figure 43.8, pour les objets contrôles ActiveX, l’expert
implémente toutes les interfaces requises par les contrôles ActiveX : IUnknown,
IDispatch, IOleObject, IOLEControl, etc. Pour avoir la liste complète des interfaces,
reportez-vous à la page de référence de l’objet TActiveXControl.
Figure 43.8 Interfaces d’un contrôle ActiveX
Si vous voulez, vous pouvez ajouter d’autres objets COM (ou refaire une
implémentation existante). Pour fournir une nouvelle interface, créez un
descendant de l’interface IDispatch et implémentez les méthodes nécessaires. Pour
implémenter à nouveau une interface, créez un descendant de cette interface et
modifiez ce descendant.
Interfaces Spécifiez les noms des interfaces COM que cet objet COM
implémentées doit implémenter.
Description Entrez la description de l’objet COM que vous êtes en train
de créer.
Inclure la Cochez cette case pour générer une bibliothèque de types
bibliothèque de pour cet objet. Une bibliothèque de types contient les
types informations qui vous permettent d’exposer toute interface
de l’objet, ainsi que ses méthodes et ses propriétés, aux
applications client.
Instanciation Signification
Interne L’objet ne peut être créé que de manière interne. Une application externe
ne peut pas créer d’instance de l’objet directement. Par exemple, une
application de traitement de texte peut avoir un objet document qui ne
peut être créé qu’en appelant une méthode de l’application qui peut
créer l’objet document.
Instance unique Autorise uniquement une seule interface COM pour chaque exécutable
(application), de sorte que la création de plusieurs instances entraîne la
création de plusieurs applications. Instance unique spécifie qu’aussitôt
qu’une application s’est connectée à l’objet, celui-ci est retiré de la vue
publique afin qu’aucune autre application ne puisse s’y connecter. Cette
option est souvent utilisée pour les applications MDI (interface à
documents multiples). Lorsqu’un client requiert les services d’un objet à
instance unique, toutes les demandes sont gérées par le même serveur.
Par exemple, chaque fois qu’un utilisateur demande d’ouvrir un nouveau
document dans une application de traitement de texte, le nouveau
document s’ouvre habituellement dans le même processus d’application.
Instance multiple Spécifie que plusieurs applications peuvent se connecter à l’objet. Chaque
fois qu’un client demande un service, une nouvelle instance du serveur
est invoquée. (C’est-à-dire qu’il peut y avoir plusieurs instances dans un
seul exécutable.) Chaque fois qu’un utilisateur essaie d’ouvrir
l’Explorateur de Windows, un Explorateur distinct est créé.
Le tableau 44.1 présente la liste des différents modèles de threads que vous
pouvez spécifier.
COM sait qu’elle en connaît le traitement. Bien sûr, le marshaling affecte quelque
peu les performances, mais il permet de faire fonctionner ensemble des parties
utilisant des modèles de threads différents.
Remarque Le modèle de thread que vous choisissez dans l’expert détermine comment
l’objet est publié dans le registre. Vous devez être certain que l’implémentation
de l’objet est conforme au modèle de thread choisi.
Le modèle de thread n’est valide que pour les serveurs en processus. La
définition d’un modèle de thread dans l’expert définit la clé modèle de thread
dans l’entrée du registre CLSID, InProcessServer32.
Les serveurs hors processus sont recensés en tant qu’EXE et l’implémentation du
modèle de thread est à votre charge.
Remarque Quel que soit le modèle de thread, les variables locales sont toujours sécurisées.
En effet, les variables locales sont stockées sur la pile et chaque thread possède
sa propre pile.
Notez que le variant peut être transtypé en une interface IUnknown puis assigné
à un autre type d’interface. Une exception est lancée si le variant ne contient pas
d’interface ou si l’interface indiquée n’est pas supportée.
Les variants sont automatiquement nettoyés et il n’est pas nécessaire pour libérer
un objet de définir un variant comme non assigné, sauf si vous voulez que cette
libération survienne à un moment précis. Pour donner à un variant la valeur
UnAssigned, ou la valeur Null, utilisez le code suivant :
var
MyVariant: Variant;
begin
MyVariant := CreateOleObject(‘Word.Basic’);
ƒ
MyVariant := UnAssigned;
end;
UnAssigned est une variable de type Variant qui est prédéfinie par la valeur
varEmpty au cours de l’initialisation de l’unité System.
Automation et registre
Quand vous appelez CreateOleObject, vous lui passez une chaîne contenant un ID
de programme ou ProgID. Par exemple, Word.Basic est le ProgID du serveur
Automation dans Microsoft Word.
Un ID de programme est une chaîne qui peut être recherchée dans le registre et
qui référence un CLSID. Les CLSID sont des numéros uniques qui peuvent être
utilisés par le système d’exploitation pour référencer un objet Automation.
Lorsque vous appelez CreateOleObject, Windows vérifie si Word est chargé en
mémoire ; sinon, il le lance en transmettant le ProgID. Windows trouve ensuite
une interface (pointeur) vers l’objet Automation requis, et la renvoie dans la
valeur de retour de CreateOleObject. Le pointeur renvoyé n’est pas un pointeur
sur Word lui-même -- c’est un pointeur sur un objet qui réside dans Word.
Dès que vous avez une interface sur l’objet Automation dans Word, vous pouvez
commencer à appeler les fonctions rendues disponibles par l’objet Automation.
En particulier, les 200 fonctions Word Basic de l’aide Word en ligne sont
disponibles. Elle comprennent des commandes pour ouvrir des documents, les
enregistrer, les formater, les imprimer, etc.
begin
V := CreateOleObject('Word.Basic');
V.FileNew('Normal');
V.Insert('Un esprit sain' + #13);
V.Insert('dans un corps sain.');
V.FileSaveAs('C:\SEMPERFI.DOC');
end;
Ce code ne fait pas apparaître Word à l’écran. A la place, Word est lancé en
mémoire de façon temporaire, tout en restant invisible. Dès que la variable V sort
de la portée ou dès qu’elle est définie par varNothing, Word s’arrête à nouveau.
Si Word n’est pas déjà en fonctionnement, CreateOleObject le lance en mémoire,
en transmettant le paramètre /Automation. Word s’exécute silencieusement en
arrière-plan sans jamais devenir visible et se ferme tout seul dès qu’il n’y a plus
de client Automation à servir.
Lorsqu’ils sont appelés par un contrôleur Automation, la plupart des serveurs
s’exécutent en arrière-plan.
Paramètre Signification
0 Document Word
1 Modèle de document
2 Texte seulement
3 Texte seulement avec sauts de ligne
Paramètre Signification
4 Texte MS-DOS (caractères étendus enregistrés dans le jeu de caractères IBM®
PC)
5 Texte MS-DOS avec sauts de ligne
6 RTF
Pour définir les paramètres dans un ordre différent, utilisez des paramètres
nommés. Par exemple, vous pouvez écrire :
V.FichierEnregistrerSous('C:\SEMPERFI.DOC', MotDePasse := 'Sam');
Cela enregistre SEMPERFI.DOC en format Word et lui attribue le mot de passe
“Sam”. La prochaine fois que vous essayerez d’ouvrir ce document, vous devrez
fournir le mot de passe.
Normalement, le mot de passe est le quatrième paramètre de cette fonction, mais
vous pouvez le placer en deuxième si vous l’appelez par son nom. La ligne de
code suivante a exactement le même effet que le code précédent :
V.FichierEnregistrerSous(MotDePasse := 'Sam', Nom := 'C:\SEMPERFI.DOC');
Outre les paramètres nommés, Word supporte également les paramètres de position.
V.FileSaveAs('C:\SEMPERFI.DOC',,,'Sammy');
Dans le code précédent, le mot de passe “Sammy” est associé à SEMPERFI.DOC.
Word sait que “Sammy” est le mot de passe car ce dernier se trouve en
quatrième position. Les deuxième et troisième paramètres prennent ici leur
valeur par défaut puisqu’ils sont laissés vides.
begin
Count := VarArrayDimCount(V);
S := #13 + 'DimCount: ' + IntToStr(Count) + #13;
for i := 1 to Count do
begin
HighBound := VarArrayHighBound(V, i);
LowBound := VarArrayLowBound(V, i);
S := S + 'HighBound: ' + IntToStr(HighBound) + #13;
S := S + 'LowBound: ' + IntToStr(LowBound) + #13;
end;
ShowMessage(S);
end;
Cette routine commence par obtenir le nombre de dimensions du tableau. Elle
passe ensuite dans chaque dimension pour récupérer sa valeur supérieure et sa
valeur inférieure. Si vous créez un tableau par l’appel suivant :
MyVariant := VarArrayCreate([0, 5, 1, 3], varVariant);
La fonction ShowInfo produit le résultat suivant lorsqu’on lui passe MyVariant :
DimCount: 2
HighBound = 5
LowBound = 0
HighBound = 3
LowBound = 1
ShowInfo provoque une exception si vous passez un variant qui fait que
VarIsArray renvoie False.
Nom de classe Spécifiez la classe dont vous voulez exposer les propriétés et
les méthodes aux applications client.
Instancie Spécifiez un mode d’instanciation pour indiquer comment
lancer le serveur Automation. Pour plus de détails, voir
“Types d’instanciation des objets COM” à la page 44-3.
Remarque : quand l’objet Automation est utilisé uniquement
comme serveur en processus, l’instanciation est ignorée.
Modèle de thread Choisissez le modèle de thread pour indiquer comment les
applications client peuvent appeler l’interface de l’objet. C’est
le modèle de thread que vous validez pour l’implémentation
de l’objet Automation. Pour plus d’informations sur les
modèles de thread, voir “Choix d’un modèle de thread” à la
page 44-3.
Remarque : le modèle de thread choisi détermine la façon
dont l’objet est recensé. Vous devez vous assurer que
l’implémentation de l’objet est conforme au modèle
sélectionné.
Générer le code Cochez cette case pour demander à l’expert d’implémenter
de support une interface distincte pour la gestion des événements de
d’événement l’objet Automation.
Une fois cette procédure terminée, une nouvelle unité est ajoutée au projet en
cours, elle contient la définition de l’objet Automation. De plus, l’expert ajoute
au projet une bibliothèque de types et l’ouvre. Vous pouvez alors exposer les
propriétés et les méthodes de l’interface via la bibliothèque de types.
L’objet Automation implémente une interface double, qui supporte à la fois la
liaison immédiate (à la compilation) via la vtable et la liaison différée (à
l’exécution) via l’interface IDispatch. Pour plus d’informations sur les interfaces
doubles, voir “Interfaces Automation” à la page 46-7.
Interfaces Automation
Les experts de Delphi implémentent par défaut une interface double, ce qui
signifie que l’objet Automation supporte à la fois :
• La liaison différée à l’exécution, via l’interface IDispatch. C’est l’interface de
répartition ou dispinterface.
• La liaison immédiate à la compilation, qui s’effectue via un appel direct à
l’une des fonctions membre de la table des fonctions virtuelles (vtable) de
l’objet. C’est l’ interface personnalisée.
Interfaces doubles
Une interface double est à la fois une interface personnalisée et une
dispinterface. Elle est implémentée en tant qu’interface vtable COM qui dérive de
IDispatch. Pour les contrôleurs qui accèdent à l’objet uniquement pendant
l’exécution, la dispinterface est disponible. Pour la majorité des objets qui
peuvent tirer profit de la liaison à la compilation, c’est l’interface vtable la plus
efficace qui est utilisée.
Les interfaces doubles offrent les avantages combinés des interfaces vtable et des
dispinterfaces :
• Pour les interfaces vtable, le compilateur fait une vérification de type et
fournit des messages d’erreurs plus informatifs.
• Pour les contrôleurs Automation qui ne peuvent pas obtenir d’information de
type, la dispinterface fournit l’accès à l’objet à l’exécution.
• Pour les serveurs en processus, vous bénéficiez d’un accès rapide via les
interfaces vtable.
• Pour les serveurs hors processus, COM effectue le marshaling des données à
la fois pour les interfaces vtable et pour les dispinterfaces. COM fournit une
implémentation proxy/stub générique qui peut réaliser le marshaling de
l’interface en fonction des informations contenues dans une bibliothèque de
types. Pour plus d’informations sur le marshaling, voir “Marshaling des
données” à la page 46-9.
Le diagramme suivant représente une interface IMyInterface dans un objet qui
supporte une interface double nommée IMyInterface. Les trois premières entrées
de la vtable d’une interface double font référence à l’interface IUnknown, les
quatre suivantes font référence à l’interface IDispatch, les autres sont des entrées
COM pour l’accès direct aux membres de l’interface personnalisée.
Interfaces de répartition
Les contrôleurs Automation sont des clients qui utilisent l’interface COM
IDispatch pour accéder aux objets du serveur COM. Le contrôleur doit d’abord
créer l’objet, puis demander à l’interface IUnknown de l’objet un pointeur sur son
interface IDispatch. IDispatch garde en interne la trace des méthodes et des
propriétés par le biais d’un identificateur de répartition (dispID), qui est un
numéro d’identification propre à chaque membre interface. Par IDispatch, un
contrôleur récupère les informations de type de l’objet pour l’interface de
répartition, puis associe le nom des membres interface aux dispID spécifiques.
Ces dispID sont accessibles à l’exécution et les contrôleurs y accèdent en
appelant la méthode GetIDsOfNames de IDispatch.
Lorsqu’il connaît le dispID, le contrôleur peut appeler la méthode Invoke de
IDispatch pour exécuter le code requis (propriété ou méthode), en regroupant les
paramètres de la propriété ou de la méthode dans l’un des paramètres Invoke.
Invoke a une signature fixe définie lors de la compilation, qui lui permet
d’accepter des arguments variés lors de l’appel d’une méthode d’interface.
L’implémentation de l’objet automation de Invoke doit alors dégrouper les
paramètres, appeler la propriété ou la méthode et gérer les éventuelles erreurs.
Lorsque la propriété ou la méthode revient, l’objet retransmet la valeur renvoyée
au contrôleur.
Cette procédure est appelée liaison différée car le contrôleur se lie à la propriété
ou à la méthode lors de l’exécution de l’application plutôt que lors de sa
compilation.
Interfaces personnalisées
Les interfaces personnalisées sont des interfaces définies par l’utilisateur qui
permettent aux clients d’appeler les méthodes de l’interface en fonction de leur
ordre dans la vtable et du type des arguments. La vtable contient les adresses de
toutes les propriétés et méthodes qui sont membres de l’objet, y compris les
fonctions membre des interfaces qu’il supporte. Si l’objet ne supporte pas
IDispatch, les entrées correspondant aux membres des interfaces personnalisées
de l’objet suivent immédiatement celles des membres de IUnknown.
Si un client peut obtenir une bibliothèque de types pour l’objet, il peut obtenir
les dispID d’une interface IDispatch et se lier directement à un déplacement de la
vtable. Cette liaison à la compilation génère du code pour appeler directement
n’importe quelle méthode ou propriété de l’objet par sa vtable, en évitant donc
les appels à GetIDsOfNames et à Invoke. Comme cet accès se fait directement par
la liaison de la vtable et qu’aucun appel n’est effectué via IDispatch, cette
procédure est plus rapide qu’avec les dispinterfaces.
• Les types énumération définis dans une bibliothèque de types. Les types
énumération compatibles Automation OLE sont stockés dans des valeurs
32 bits et sont traités comme des valeurs de type Integer pour la transmission
des paramètres.
• Les types interface définis dans une bibliothèque de types qui sont sécurisés
Automation OLE, c’est-à-dire dérivés de IDispatch et contenant seulement des
types compatibles Automation OLE.
• Les types dispinterface définis dans une bibliothèque de types.
• IFont, IStrings et IPicture. Les objets helper doivent être instanciés pour que
correspondent
• un IFont à un TFont
• un IStrings à un TStrings
• un IPicture à un TPicture
Les experts contrôle ActiveX et ActiveForm créent automatiquement ces objets
helper lorsque c’est nécessaire. Pour utiliser les objets helper, appelez
respectivement les routines globales GetOleFont, GetOleStrings, GetOlePicture.
Marshaling personnalisé
Typiquement, vous utiliserez le marshaling automatique dans les serveurs hors
processus et distants parce que c’est le plus simple -- COM fait le travail à votre
place. Cependant, vous pouvez décider de fournir un marshaling personnalisé si
vous pensez que ses performances seront supérieures.
Vous trouverez un exemple de marshaling personnalisé dans le répertoire
demos\ActiveX. Lisez le fichier Lisezmoi de ce répertoire pour localiser ce
programme de test.
Contrôle VCL
Un contrôle ActiveX dans Delphi est simplement un contrôle VCL qui a été
rendu accessible aux applications et aux objets supportant les contrôles ActiveX.
Lorsque vous créez un contrôle ActiveX, vous devez d’abord concevoir ou
choisir le contrôle VCL à partir duquel vous allez le construire.
Remarque Les contrôles disponibles dans la liste de l’expert sont dérivés de TWinControl.
Certains contrôles, comme EditControl, sont recensés comme contrôles
NonActiveX et n’apparaissent donc pas dans la liste.
Bibliothèque de types
Une bibliothèque de types contient les définitions des types du contrôle ; elle est
créée automatiquement par l’expert contrôle ActiveX. Ces informations de types,
qui fournissent plus de détails que l’interface, représentent pour les contrôles un
moyen de publier leurs services aux applications hôtes. Lorsque vous concevez
votre contrôle, les informations de la bibliothèque de types sont stockées dans un
fichier portant l’extension .TLB et un fichier Pascal correspondant contient les
conversions Pascal. Lorsque vous construisez le contrôle ActiveX, les
informations de la bibliothèque de types sont automatiquement compilées dans
la DLL du contrôle ActiveX en tant que ressource.
Page de propriétés
La page de propriétés permet à l’utilisateur d’un contrôle de voir et de modifier
ses propriétés. Vous pouvez grouper plusieurs propriétés sur une page, ou
utiliser une page pour fournir une interface de type dialogue à une propriété.
Pour savoir comment créer des pages de propriétés, voir “Création d’une page
de propriétés pour un contrôle ActiveX” à la page 47-14.
Inclure la boîte Quand cette case est cochée, une boîte A propos est intégrée
A propos dans le projet. Dans un environnement de développement,
l’utilisateur du contrôle peut afficher la boîte de dialogue A
propos. La boîte de dialogue A propos est une fiche distincte
qu’il est possible de modifier. Par défaut, cette boîte de
dialogue contient le nom du contrôle ActiveX, une image,
des informations de copyright et un bouton OK.
Classe VCL Cette option est estompée puisque les fiches ActiveForms
sont toujours basées sur TActiveForm.
Nouveau nom L’expert fournit un nom par défaut que les clients utiliseront
pour identifier votre contrôle ActiveX. Changez ce nom si
vous voulez fournir un autre nom de classe OLE.
Unité L’expert fournit un nom par défaut à l’unité contenant le
implémentation code d’implémentation du comportement du contrôle
ActiveX. Acceptez ce nom par défaut ou tapez en un autre.
Projet L’expert fournit un nom par défaut au projet de bibliothèque
ActiveX pour votre contrôle ActiveX, si aucun projet en
cours n’est ouvert. Si une bibliothèque ActiveX est ouverte,
cette option est désactivée.
Modèle de thread Choisissez le modèle de thread pour indiquer comment les
applications client appellent l’interface de votre contrôle.
C’est le modèle de thread que vous validez pour
l’implémentation dans le contrôle. Pour plus d’informations
sur les modèles de thread “Choix d’un modèle de thread” à
la page 44-3.
Remarque : le modèle de thread choisi détermine la façon
dont l’objet est recensé. Vous devez vous assurer que
l’implémentation de l’objet est conforme au modèle
sélectionné.
Remarque Comme les méthodes d’une interface Automation sont déclarées safecall, vous
n’avez pas besoin d’implémenter le code d’exception OLE pour ces méthodes —
le compilateur Delphi gère cela pour vous en générant autour du corps des
méthodes safecall le code permettant de capturer les exceptions Delphi et de les
convertir en structures d’information et en codes de retour des erreurs OLE.
Actualisation de l’objet
Ajoutez du code à la méthode UpdateObject pour mettre à jour la propriété
quand l’utilisateur modifie les contrôles de la page de propriétés. Vous devez
ajouter du code à la méthode UpdateObject afin de définir la nouvelle valeur des
propriétés du contrôle ActiveX.
Par exemple, le code suivant affecte la propriété EditMask d’un contrôle ActiveX
(OleObject) en utilisant la valeur du contrôle boîte de saisie (InputMask) de la
page de propriétés :
procedure TPropertyPage1.UpdateObject;
begin
{ Actualise OleObjects à partir des contrôles }
OleObject.EditMask := InputMask.Text;
end;
Fichier .INF
Si votre contrôle ActiveX dépend de paquets ou d’autres fichiers
supplémentaires, ces fichiers doivent être inclus quand vous déployez le contrôle
ActiveX. Quand le contrôle ActiveX est déployé avec des paquets ou des fichiers
supplémentaires, un fichier portant l’extension INF (pour INFormation) est
automatiquement créé. Ce fichier spécifie les divers fichiers nécessaires devant
être téléchargés et configurés pour que la bibliothèque ActiveX s’exécute. La
syntaxe du fichier .INF permet la désignation par URL de paquets ou de fichiers
supplémentaires devant être téléchargés.
Les options de déploiement Web sont affichés sur les pages suivantes :
• page Projet
• page Paquets
• page Fichiers supplémentaires
• page Encodage
Combinaisons d’options
Le tableau suivant résume le résultat de la combinaison des différentes options
de déploiement Web concernant les paquets, la compression de fichiers CAB et
la signature par encodage.
Page Projet
La page Projet permet de spécifier l’emplacement de fichiers et d’URL et de
définir d’autres options de déploiement pour le projet. Les options de la page
Projet s’appliquent aux fichier bibliothèque ActiveX ou au fichier CAB contenant
le contrôle ActiveX et devient l’option par défaut pour les paquets et fichiers
supplémentaires déployés avec le projet.
Remarque Ce sont des chemins d’accès stricts ne contenant pas de nom de fichier.
Outre la spécification de l’emplacement des fichiers ActiveX, la page Projet
permet de spécifier s’il faut utiliser la compression de fichier CAB, les numéros
de version, l’encodage, etc. Le tableau suivant décrit les options proposées :
Page Paquets
La page Paquets permet de spécifier comment les paquets utilisés dans le projet
sont déployés. Chaque paquet utilisé par le projet peut spécifier individuellement
ces paramètres. Quand vous déployez votre contrôle ActiveX, vous pouvez
spécifier des options de déploiement individuellement pour chaque fichier
paquet utilisé par le projet pour le déploiement. Chacun de ces paquets peut être
encodé et placé dans un fichier CAB. Les paquets livrés avec Delphi sont déjà
encodés avec la signature Borland.
Options CAB
Options de sortie
Les options de sortie permettent de spécifier si le paquet comprend des
informations de version et s’il est encodé.
Options CAB
Options de sortie
Page Encodage
La Page Encodage permet à l’utilisateur du contrôle de déterminer avec certitude
qui a écrit le contrôle et si le code n’a pas été modifié depuis la signature.
Chaque fichier déployé peut avoir une signature par encodage. L’encodage ne
modifie pas les données ; il crée une signature digitale qui est ajoutée au fichier.
Pour générer une signature digitale, une valeur hachée (appelée également résumé
du message) est tout d’abord créée en utilisant l’Algorithme cryptographique
spécifié. Cette valeur hachée est ensuite signée en utilisant la Clé privée.
Pour la clé privée et les fichiers justificatifs, contactez Microsoft Corporation.
Informations requises
Pour pouvoir encoder le contrôle ActiveX, vous devez spécifier une clé privée et
un fichier de certificat justificatif. Spécifiez ces valeurs dans la zone Informations
requises de la page Encodage.
Informations facultatives
Outre les informations requises, vous pouvez spécifier des informations facultatives
permettant au client de connaître le nom de l’application et de la société.
Algorithme cryptographique
Choisissez l’un des algorithmes cryptographiques suivants. MD5, la valeur par
défaut, est le plus couramment utilisé. Vous pouvez sélectionner l’un ou l’autre
des algorithmes selon qu’ils sont gérés ou non par le navigateur.
Barre d’outils
Pages
Barre d’état
• La barre d’état, qui affiche les erreurs de syntaxe quand vous essayez
d’ajouter des types illégaux à la bibliothèque de types.
• Les pages, qui affichent des informations sur l’objet sélectionné. Les pages
affichées dépendent du type d’objet sélectionné.
Barre d’outils
La barre d’outils de l’éditeur de bibliothèques de types, située en haut, contient
des boutons sur lesquels vous cliquez pour ajouter des informations à la
bibliothèque de types.
Vous pouvez modifier les types d’information suivants à l’aide de la barre d’outils :
Icône Signification
Une bibliothèque de types. Peut être développée pour détailler les informations de
type, y compris les objets et les interfaces.
Une CoClasse.
Une énumération.
Un alias.
Un enregistrement.
Une union.
Un module.
Une propriété.
Barre d’état
Lors de la modification, l’enregistrement ou la lecture d’une bibliothèque de
types, les erreurs de syntaxe, les erreurs de traductions et les avertissements sont
affichés dans le volet Barre d’état.
Si, par exemple, vous spécifiez un type non géré par l’éditeur de bibliothèques
de types, vous obtiendrez une erreur de syntaxe. Pour une liste complète des
types gérés par l’éditeur de bibliothèques de types, voir “Types autorisés” à la
page 48-22.
Page Attributs
Tous les éléments d’une bibliothèque de types ont une page d’attributs qui
permet de définir un nom et d’autres attributs spécifiques à l’élément. Si, par
exemple, une interface est sélectionnée, vous pouvez spécifier le GUID et
l’interface parent. Si un champ est sélectionné, vous pouvez spécifier son type.
Les sections suivantes décrivent en détail les attributs de chaque sorte d’élément
d’une bibliothèque de types.
Les attributs communs à tous les éléments de la bibliothèque de types sont ceux
associés à l’aide. Il est fortement recommandé que vous utilisiez les chaînes
d’aide pour décrire les éléments de la bibliothèque de types afin de faciliter son
utilisation par des applications.
L’éditeur de bibliothèques de types gère deux mécanismes d’assistance. Le
mécanisme traditionnel d’aide, où un fichier d’aide est contenu dans la
bibliothèque de types ou, sinon, un fichier d’aide placé dans une DLL distincte
(pour simplifier la localisation).
Page Texte
Tous les éléments des bibliothèques de types disposent d’une page Texte qui
affiche la syntaxe de l’élément. Cette syntaxe est au format IDL (Interface
Definition Language) ou Pascal Objet. Les modifications effectuées dans les
autres pages de l’élément sont reflétées ici. Si vous ajoutez du code directement
dans la page Texte, les modifications sont reflétées dans les autres pages de
l’éditeur de bibliothèques de types.
L’éditeur de bibliothèques de types génère des erreurs de syntaxe si vous ajoutez
des identificateurs qui ne sont pas gérés par l’éditeur ; l’éditeur ne gère
actuellement que les identificateurs associés à la gestion de bibliothèques (et pas
ceux associés à la gestion RPC).
Pages Indicateurs
Certains éléments d’une bibliothèque de types disposent d’indicateurs qui
permettent d’activer ou d’inhiber certains comportements. Les sections suivantes
décrivent en détail les indicateurs pour chaque sorte d’élément de la bibliothèque
de types.
Remarque Les propriétés ActiveX peuvent être marquées Write By Reference, ce qui signifie
que la propriété est passée en tant que pointeur plutôt que par valeur. Certaines
applications, comme Visual Basic, utilisent si possible Write By Reference pour
optimiser les performances. Pour passer une propriété uniquement par référence
plutôt que par valeur, utilisez le type de propriété By Reference Only. Pour
passer une propriété par référence aussi bien que par valeur, cliquez sur
l’indicateur By Reference.
La page Paramètres est différente selon que vous travaillez en IDL ou en Pascal
Objet.
Quand vous ajoutez un paramètre, si vous travaillez en Pascal Objet, l’éditeur de
bibliothèques de types fournit :
• Le modificateur
• Le nom par défaut
• Le type
Si vous travaillez en IDL, l’éditeur de bibliothèques de types fournit :
• Le nom par défaut
• Le type
• L’indicateur
Vous pouvez modifier le nom en saisissant une nouvelle valeur. Modifiez le type
en choisissant une nouvelle valeur dans la liste déroulante. Les types autorisés
sont ceux gérés par l’éditeur de bibliothèques de types indiqués dans “Types
autorisés” à la page 48-22.
Si vous travaillez en Pascal Objet, changez le modificateur en choisissant une
nouvelle valeur dans la liste déroulante. Les valeurs possibles sont :
Utilisez la colonne défaut pour spécifier les valeurs de paramètres par défaut.
Lorsque vous ajoutez une valeur par défaut, l’éditeur de bibliothèques de types
ajoute automatiquement les indicateurs appropriés à la bibliothèque de types.
Remarque Lorsque vous travaillez dans IDL, les valeurs par défaut sont spécifiées à l’aide
d’indicateurs plutôt que dans une colonne à part. De même, les identificateurs
locaux sont spécifiés à l’aide d’un indicateur plutôt qu’en utilisant un
spécificateur de type de paramètre de TLCID.
Vous pouvez utiliser les boutons Vers le haut et Vers le bas pour modifier
l’ordre des paramètres. Cependant, l’éditeur n’autorise pas des déplacements qui
violeraient une règle du langage IDL. Ainsi, l’éditeur de bibliothèques de types
applique la règle imposant que la valeur renvoyée soit toujours le dernier
paramètre de la liste des paramètres.
Attribut Signification
Nom Nom sous lequel la dispinterface est connu dans la bibliothèque de types.
Ce doit être un nom unique dans la bibliothèque de types.
GUID Identificateur global unique sur 128 bits de l’interface de répartition
(optionnel).
Version Version particulière de l’interface de répartition au cas où plusieurs
versions existent. La version est soit une paire d’entiers décimaux séparés
par un point, soit un entier décimal unique. Le premier de ces deux entiers
représente le numéro principal de la version, le second représente le
numéro mineur de la version de l’interface. Si un seul entier est spécifié, il
représente le numéro principal de la version. Ces deux numéros de version
sont des entiers courts non signés compris entre 0 et 65535 (bornes
comprises).
Chaîne d’aide Une courte description de l’élément. Utilisé avec le contexte d’aide pour
spécifier l’aide sous la forme d’un fichier d’aide.
Contexte L’identificateur de contexte d’aide de l’élément, qui identifie la rubrique
d’aide d’aide associée à l’élément dans le fichier d’aide.
Contexte de Pour les DLL d’aide, l’identificateur de contexte d’aide de l’élément qui
chaîne d’aide identifie la rubrique d’aide associée à cet élément dans le fichier d’aide.
S’utilise avec les DLL de chaîne d’aide pour proposer l’aide dans une DLL
distincte.
Il est fortement conseillé de spécifier une chaîne d’aide pour les énumérations.
Voici un exemple d’entrée d’un type énumération pour un bouton de souris qui
inclut un chaîne d’aide pour chacun des éléments de l’énumération :
mbLeft = 0 [helpstring ‘mbLeft’];
mbRight = 1 [helpstring ‘mbRight’];
mbMiddle = 3 [helpstring ‘mbMiddle’];
Les paramètres des méthodes de module se spécifient comme ceux des méthodes
d’interface, comme décrit dans “Page Paramètres des propriétés et méthodes” à
la page 48-11.
Constantes de module
Pour définir une constante de module, il faut spécifier :
• Son nom
• Sa valeur
• Son type
Une constante de module peut être numérique ou chaîne, selon son attribut. Les
entrées numériques sont généralement sous la forme d’un entier au format
décimal ou hexadécimal ; ce peut être aussi une constante caractère (comme \0).
Les entrées chaîne sont délimitées par des guillemets (““) et ne peuvent s’étendre
sur plusieurs lignes. La barre oblique inverse sert de caractère d’échappement.
Quand ce caractère est suivi d’un autre caractère (y compris une autre barre
oblique inverse), il empêche l’interprétation littérale de ce caractère. Par exemple,
pour placer une barre oblique inverse dans un texte, utilisez :
“Pathname: c:\\bin\\”
Types autorisés
Dans l’éditeur de bibliothèques de types, vous utilisez des identificateurs de
types différents, selon que vous travaillez en IDL ou en Pascal Objet. Spécifiez le
langage que vous voulez utiliser dans la boîte de dialogue Options
d’environnement.
Les types suivants sont autorisés dans une bibliothèque de types. La colonne
Compatible Automation spécifie si le type peut être utilisé par une interface dont
l’indicateur Automation ou Dispinterface est activé.
Remarque Byte (VT_UI1) est compatible avec l’Automation, mais il n’est pas autorisé dans
un Variant ou un OleVariant car de nombreux serveurs Automation ne gèrent
pas correctement cette valeur.
Outre ces types, toute interface ou type défini dans la bibliothèque ou dans les
bibliothèques référencées peut s’utiliser dans une définition de bibliothèque de
types.
Les SafeArray
Dans l’éditeur de bibliothèques de types, un SafeArray doit spécifier son type de
composant. Par exemple, dans le code suivant, le SafeArray spécifie un
composant de type entier :
procedure HighLightLines(Lines: SafeArray of Integer);
Le type de composant d’un SafeArray doit être compatible avec l’Automation.
Dans l’unité de conversion de bibliothèque de types Delphi, le type de
composant n’est ni nécessaire ni autorisé.
Par exemple, le texte suivant est la déclaration d’une coclasse pour l’interface
IMyInt et la dispinterface DmyInt :
myapp = coclass (IMyInt [source], DMyInt);
[uuid ‘{2MD36ABF-90E3-11D1-AA75-02C04FB73F42}’,
version 1.0,
helpstring ‘Une classe’,
appobject]
La syntaxe IDL correspondante est
[uuid ‘{2MD36ABF-90E3-11D1-AA75-02C04FB73F42}’,
version 1.0,
helpstring ‘Une classe’,
appobject]
coclass myapp
{
methods :
[source] interface IMyInt);
dispinterface DMyInt;
};
4 Choisissez OK.
L’éditeur de bibliothèques de types s’affiche en demandant le nom de la
bibliothèque de types.
5 Entrez le nom de la bibliothèque de types.
Le nouveau membre contient les attributs par défaut que vous pouvez modifier
dans la page Attributs.
Vous pouvez également ajouter des méthodes et propriétés directement dans la
page Texte à l’aide de la syntaxe Pascal. Par exemple, vous pouvez saisir les
déclarations de propriétés suivantes dans la page Texte d’une interface :
property AutoSelect: WordBool; dispid 1;
property AutoSize: WordBool; dispid 2;
property BorderStyle: BorderStyle; dispid 3;
Une fois des membres ajoutés à une interface, les membres apparaissent comme
éléments séparés dans le volet liste des objets. Chaque membre dispose de sa
propre page d’attributs vous permettant d’en modifier les caractéristiques.
sein de l’exécutable MTS. En s’exécutant avec l’EXE MTS, les objets MTS
bénéficient des fonctionnalités de l’environnement d’exécution MTS comme le
pooling des ressources ou le support des transactions.
L’exécutable MTS (.EXE) peut être exécuté dans le même processus que le client
de base comme le montre la figure 49.2.
Figure 49.2 Composant MTS en processus
Le composant MTS peut être installé sur un processus serveur distant au sein de
la même machine comme le montre la figure suivante. Le client de base parle à
un proxy qui effectue le marshaling de la requête du client pour le stub du
composant MTS, qui à son tour accède au composant MTS via son interface.
Figure 49.3 Un composant MTS dans un serveur hors processus
Le composant MTS peut être installé dans un processus serveur distant sur un
ordinateur séparé comme le montre la figure suivante. Exactement comme dans
tout autre processus serveur distant, le client et le serveur distant communiquent
au travers de machines utilisant DCOM.
Figure 49.4 Un composant MTS dans un processus serveur distant
Activation just-in-time
La capacité d’un objet à être désactivé et réactivé alors que des clients lui font
référence est nommée activation just-in-time. Vu du client, il existe une seule
instance de l’objet à partir du moment où le client l’a créée et jusqu’au moment
où il la libère. En réalité, il se peut que l’objet ait été désactivé et réactivé de
nombreuses fois. Les objets pouvant être ainsi désactivés, les clients peuvent
continuer de faire référence à un objet pendant un temps indéterminé sans
affecter les ressources du système. Lorsqu’un objet devient désactivé, MTS libère
toutes les ressources de l’objet, par exemple, sa connexion à la base de données.
Lorsqu’un objet COM est créé en tant qu’élément de l’environnement MTS, un
objet de contexte est également créé. Cet objet de contexte existe pendant
l’intégralité de la durée de vie de l’objet MTS correspondant, pendant un ou
plusieurs cycles de réactivation. MTS utilise l’objet de contexte pour conserver la
trace de l’objet durant la désactivation. Cet objet de contexte, accessible via
l’interface IObjectContext, coordonne les transactions. Un objet COM est créé dans
l’état désactivé et devient actif lorsqu’il reçoit la demande d’un client.
Un objet MTS est désactivé lorsqu’un des événement suivants se produit :
• L’objet demande la désactivation avec SetComplete ou SetAbort : Un objet
appelle la méthode IObjectContext SetComplete lorsqu’il a terminé son travail
avec succès et qu’il n’a pas besoin de sauver l’état interne de l’objet pour un
prochain appel du client. Un objet appelle SetAbort pour indiquer qu’il ne
peut terminer son travail avec succès et que l’état de l’objet n’a pas besoin
d’être sauvé. C’est-à-dire que l’objet reprend l’état qu’il avait avant la
transaction. Souvent, les objets sont conçus sans état, ce qui signifie que les
objets sont désactivés après le retour de toutes les méthodes.
• Une transaction est validée ou annulée : Lorsqu’une transaction sur un objet
est validée ou annulée, l’objet est désactivé. Parmi ces objets désactivés, les
seuls qui continuent à exister sont ceux à qui des clients hors transaction sont
en train de faire référence. Les prochains appels à ces objets les réactivent et
les font s’exécuter dans la prochaine transaction.
• Le dernier client libère l’objet : Bien sûr, lorsqu’un client libère l’objet, il est
désactivé et le contexte d’objet également.
• Les mises à jour validées des ressources gérées (comme les enregistrements
d’une base de données) survivent aux pannes, y compris les pannes de
communication, les pannes de processus et les pannes système des serveurs.
C’est ce que nous appelons durabilité. L’ouverture d’une transaction vous
permet de bénéficier d’un état durable après les pannes survenues sur les
supports disque.
Lorsque vous déclarez qu’un composant MTS fait partie d’une transaction, MTS
associe des transactions avec les objets du composant. Lorsque la méthode d’un
objet est exécutée, les services que les gestionnaires et les dispenseurs de
ressources réalisent pour lui s’exécutent sous le contrôle d’une transaction. Le
travail de multiples objets peut être rassemblé en une unique transaction.
Attributs transactionnels
Tout composant MTS a un attribut transactionnel enregistré dans le catalogue
MTS. Le catalogue MTS maintient les informations de configuration des
composants, paquets et rôles. Vous administrez le catalogue en utilisant
l’Explorateur MTS, comme décrit dans “Administration des objets MTS avec
l’Explorateur MTS” à la page 49-23.
Chaque attribut transactionnel peut être défini par une des valeurs suivantes :
Requiert une Les objets MTS doivent s’exécuter dans la portée d’une
transaction transaction. Lorsqu’un nouvel objet est créé, son contexte
hérite de la transaction du contexte du client. Si le client n’a
pas de contexte transactionnel, MTS crée automatiquement
un nouveau contexte transactionnel pour l’objet.
Requiert une Les objets MTS doivent s’exécuter dans leurs propres
nouvelle transaction transactions. Lorsqu’un nouvel objet est créé, MTS crée
automatiquement une nouvelle transaction pour cet objet,
que son client ait ou non une transaction. Un objet ne
s’exécute jamais dans la portée de la transaction de son
client. Au contraire, le système crée toujours des transactions
indépendantes pour les nouveaux objets.
Supporte les Les objets MTS peuvent s’exécuter dans la portée des
transactions transactions de leur client. Lorsqu’un nouvel objet est créé, son
contexte hérite de la transaction du contexte du client. Cela
permet à plusieurs objets d’être rassemblés dans une même
transaction. Si le client n’a pas de transaction, le nouveau
contexte est également créé sans transaction.
Ne supporte pas les Les objets MTS ne s’exécutent pas dans la portée des
transactions transactions. Lorsqu’un nouvel objet est créé, son contexte
d’objet est créé sans transaction, que son client ait ou non
une transaction. Utilisez cela pour les objets COM conçus
avant le support de MTS.
Avec les transactions MTS, vous pouvez implémenter la logique de gestion de votre
application dans les objets serveur. Les objets serveur peuvent imposer les règles
de sorte que le client n’ait pas besoin de s’en préoccuper. Par exemple, dans notre
application médicale, un client technicien radio peut ajouter et voir les radiographies
d’un enregistrement médical. Il n’a pas besoin de savoir que l’application ne permet
pas aux techniciens radio d’ajouter ou de voir tout autre type d’enregistrement. Cette
logique se trouve dans les autres objets serveur de l’application.
Dispenseurs de ressources
Un dispenseur de ressources gère l’état partagé non durable de la part des
composants de l’application dans un processus. Les dispenseurs de ressources
sont semblables aux gestionnaires de ressources comme SQL Server, mais sans
garantie de durabilité. MTS fournit deux dispenseurs de ressources :
• Dispenseur de ressources BDE
• Gestionnaire de propriétés partagées
protected
procedure OnActivate; override ;
procedure OnDeactivate; override ;
procedure IncCounter;
end;
implementation
uses ComServ;
{ Tfoobar }
procedure Tfoobar.OnActivate;
var
Exists: WordBool;
Counter: ISharedProperty;
begin
Group := CreateSharedPropertyGroup('MyGroup');
Counter := Group.CreateProperty('Counter', Exists);
end;
procedure Tfoobar.IncCounter;
var
Counter: ISharedProperty;
begin
Counter := Group.PropertyByName['Counter'];
Counter.Value := Counter.Value + 1;
end;
procedure Tfoobar.OnDeactivate;
begin
Group := nil;
end;
initialization
TAutoObjectFactory.Create(ComServer, Tfoobar, Class_foobar, ciMultiInstance,
tmApartment);
end.
Le pooling des ressources dans l’environnement MTS est généralement apporté par
le moteur de base de données sous-jacent. Dans Delphi, le pooling des ressources
est fourni par le BDE (Borland Database Engine). Toutes les connexions aux bases
de données allouées par les objets MTS proviennent de ce groupe. Ces connexions
peuvent participer aux commit en deux phases sous le contrôle de MTS.
Lorsque vous suivez cette procédure, une nouvelle unité est ajoutée au projet en
cours contenant la définition de l’objet MTS. De plus, l’expert ajoute un projet
bibliothèque de types et ouvre la bibliothèque. Alors, vous pouvez exposer les
propriétés et les méthodes de l’interface par le biais de la bibliothèque de types.
Vous exposez l’interface comme vous exposeriez n’importe quel objet
Automation comme décrit dans “Exposition des propriétés, méthodes et
événements d’une application” à la page 46-3.
L’objet MTS implémente une interface double, qui supporte à la fois l’édition de
liens précoce (lors de la compilation), via la vtable, et l’édition de liens tardive
(lors de l’exécution), via l’interface IDispatch. Pour avoir plus d’informations sur
les interfaces doubles, voyez “Interfaces Automation” à la page 46-7.
L’expert objet MTS implémente les méthodes de l’interface IObjectControl,
Activate, Deactivate et CanBePooled.
Remarque Ces modèles de threads sont semblables à ceux définis par les objets COM.
Cependant, comme l’environnement MTS fournit un support des threads plus
avantageux, la signification de chaque modèle de thread diffère. D’autre part, les
modèles de threads Libre ou Les deux ne s’appliquent pas aux objets s’exécutant
dans l’environnement MTS à cause de la façon dont MTS supporte les activités.
Activités MTS
MTS supporte les accès simultanés via les activités. Tout objet MTS appartient à
une activité ; elle est enregistrée dans le contexte de l’objet. L’association entre un
objet et une activité ne peut être modifiée. Une activité comprend l’objet MTS
créé par le client de base, ainsi que tous les objets MTS créés par cet objet et ses
descendants. Ces objets peuvent être distribués dans un ou plusieurs processus
s’exécutant sur un ou plusieurs ordinateurs.
Par exemple, une application destinée à des médecins peut posséder un objet
MTS ajoutant des mises à jour et supprimant des enregistrements dans plusieurs
bases de données médicales, chacune représentée par un objet différent. Cet objet
d’ajout peut utiliser également d’autres objets, comme un objet de réception qui
enregistre la transaction. Il en résulte plusieurs objets MTS qui sont, soit
directement, soit indirectement, sous le contrôle du client de base. Ces objets
appartiennent tous à la même activité.
MTS suit le flux d’exécution dans chaque activité, en empêchant qu’un
phénomène de parallélisme n’altère malencontreusement l’état de l’application.
Le résultat de cette fonctionnalité est l’unicité du thread logique d’exécution pour
toute une série d’objets potentiellement distribuables. Grâce à ce thread logique
unique, les applications sont nettement plus faciles à écrire.
Chaque fois qu’un nouvel objet MTS est créé, une nouvelle activité est créée.
Lorsqu’un objet MTS est créé à partir d’un contexte existant, à partir d’un objet
de contexte transactionnel ou d’un objet de contexte MTS, le nouvel objet devient
membre de la même activité. Autrement dit, le nouveau contexte hérite de
l’identificateur d’activité du contexte utilisé pour le créer.
MTS n’autorise qu’un seul thread logique d’exécution pour une même activité.
Ce comportement est semblable à celui d’un apartment COM, mais les objets
peuvent être distribués dans plusieurs processus. Lorsque un client de base fait
appel à une activité, toutes les autres demandes de travail dans cette activité (par
exemple, celles provenant d’un autre thread client) sont bloquées jusqu’à ce que
le thread d’exécution initial revienne vers le client.
Pour avoir plus d’informations sur les threads en l’environnement MTS,
recherchez dans la documentation MTS la rubrique Components and Threading.
Les appels qui utilisent des références sécurisées sont toujours transmis à
l’environnement d’exécution MTS. Cela permet à MTS de gérer les options de
contexte, et aux objets MTS d’avoir des durées de vie indépendantes des
références client.
Callbacks
Les objets peuvent faire des callbacks aux clients et aux autres composants MTS.
Par exemple, vous pouvez avoir un objet qui crée un autre objet. L’objet qui créé
peut transmettre à l’objet créé une référence à lui-même ; l’objet créé peut ensuite
utiliser cette référence pour appeler l’objet qui l’a créé.
Si vous choisissez d’utiliser les callbacks, prenez garde aux restrictions suivantes :
• Un callback au client de base ou à un autre paquet nécessite, sur le client, une
sécurité au niveau des accès. De plus, le client doit être un serveur DCOM.
• Voir les propriétés des composants d’un paquet et voir les paquets installés
sur un ordinateur
• Surveiller et gérer les transactions pour les composants MTS qui en comportent
• Déplacer le paquets entre ordinateurs
• Rendre un objet MTS distant disponible à un client local
Pour avoir plus de détails concernant l’Explorateur MTS, voir le MTS
Administrator’s Guide.
Index I-1
noms de base de données Application, variable 5-3, 28-7 applications bidirectionnelles
et 14-3 applications méthodes 11-7
sessions et 14-4 ActiveX 3-11 propriétés 11-5
spécification 17-5, 17-6 annulation des applications client
suppression 16-12 modifications 18-27 base de données 17-2
AliasName, propriété 17-5 base de données 13-1 CORBA 27-2, 27-12–27-16
Align To Grid, commande 2-59 CGI 3-11 extraction de données 21-3
Align, commande 2-59 client/serveur 15-1, 17-2 mises à jour en mémoire
Align, propriété 5-3 protocoles réseau 17-9 cache et 24-2
barres d’état 2-35 COM 3-11, 43-2, 43-16 multiniveaux 15-38
boîtes de défilement 2-34 COM et CORBA mise à jour des
contrôles texte formaté 6-8 combinés 27-5 enregistrements 15-35
volets 5-28 CORBA 3-12, 27-1 régularisation des mises à
AlignButton, propriété 2-25 création 3-1 jour 15-36
alignement 2-59 distribuées 3-9–3-12 protocoles réseau 17-9
Alignment, propriété 19-3 threads et 9-13 applications client simples 15-2
barres d’état 2-36 état en cours 2-34 applications CORBA 27-1
contrôles éditeur de texte graphiquesl 30-8, 35-1 clients 27-12–27-16
formaté 2-22 informations d’état 2-35 déploiement 27-17–27-21
en-têtes de colonne 25-25 ISAPI 3-11, 28-5, 28-6 serveurs 27-5–27-12
grilles de décision 26-14 MDI 3-2, 3-3 serveurs COM et CORBA
grilles de données 25-25 MTS 3-12 combinés 27-5
mémo, champs 25-11 multiniveaux vue générale 27-2–27-4
mémos 2-22 présentation 15-10 applications de base de
valeurs de champ 19-15 multithread 9-1, 16-3, 16-18– données 12-4, 13-1
AllowAllUp, propriété 2-28 16-19 architecture 13-7
boutons outils 5-32 distribuées 9-13 basées sur le BDE ou
turboboutons 5-30 NSAPI 3-11, 28-5, 28-6 linéaires 14-13
AllowDelete, propriété 25-32 optimisation des distribuées 3-12
AllowGrayed, propriété 2-28 recherches 20-6 évolution 13-8, 14-18
AllowInsert, propriété 25-32 réalisation de palettes 35-5, fichier linéraire 14-12–14-16
alTop, constante 5-28 35-6 multiniveaux 15-10
Analyser Params, SDI 3-2 applications distantes
commande 15-38 serveur Web 3-11 extraction de données 21-1,
ancêtres, classes 2-8, 2-11, 2-14 service 3-4 21-3, 21-16, 21-19
années bissextiles 40-8 synchronisation des mises à jour en mémoire
annulation des mises à jour en tables 20-27 cache et 24-1
mémoire cache 24-9–24-10 TCP/IP 3-10 opérations groupées 20-24
annulation des Win-CGI 3-11 TCP/IP 29-1
modifications 18-27 applications à niveau applications distribuées 3-9
annulation des modifications de double 13-3, 13-7, 13-10, 14-1– ActiveX 3-11
données 18-27 14-12 base de données 3-12
ANSI, chaînes standard 4-25 ou applications à niveau COM 3-11
ANSI, jeux de caractères 11-2 unique 14-3 CORBA 3-12, 27-1
AnsiChar 4-25 applications à niveau triple Voir MTS 3-12
AnsiString 4-27 applications multiniveaux multithread 9-13
apartment, modèle de applications à niveau applications internationales 11-1
thread 44-5 unique 13-2, 13-7, 13-9, 14-1– abréviations et 11-8
Append, méthode 18-8, 18-26 14-16 conversion des saisies
Insert et 18-25 basées sur le BDE ou clavier 11-8
AppendRecord, méthode 18-28 linéaires 14-13 localisation 11-12
application de répartition de fichier linéraire 14-12–14-16 applications linéaires 14-12–
sockets 15-13 ou applications à niveau 14-16
application, serveurs 13-11 double 14-3 mémoire 14-12
Index I-3
barres d’outils 2-28, 5-27 DatabaseName, propriété, BeforeDisconnect,
ajout 5-30–5-32 et 14-4 événement 15-32
ajout de volets décompte 16-13 BeforeDispatch,
comme 5-28, 5-30 dénomination 17-5, 20-2 événement 28-9, 28-11
conception 5-27–5-35 distantes 13-3 BeforeUpdateRecord,
définition des marges 5-29 enregistrement de événement 15-24
désactivation des données 18-27 BeginDrag, méthode 6-1
boutons 5-31 extraction de données 18-19, BeginRead, méthode 9-8
insertion de boutons 5-28– 19-21, 24-1 BeginWrite, méthode 9-8
5-30, 5-31 fermeture 16-6 Bevel, composant 2-38
masquer 5-34 génération de réponses Beveled, propriété 2-26
menus contextuels 5-34 HTML 28-21–28-25 BevelInner, propriété 2-38
outil de dessin par importation de BevelOuter, propriété 2-38
défautl 5-29 données 20-21 BevelWidth, propriété 2-38
transparentes 5-31, 5-33 limitation des extractions de bibliothèque COM 43-2
turboboutons 2-27 données 20-12 bibliothèques
barres de défilement 2-24 locales 13-2 contrôles personnalisés 30-5
barres de menus marquage bibliothèques de types 43-9,
déplacement d’éléments 5-19 d’enregistrements 18-15– 43-11, 43-12, 48-1
barres de progression 2-35 18-16 accès 43-14
barres graduées 2-24 modèles multiniveaux 15-2 ajout d’interfaces 48-31
barres multiples 2-29, 5-27 modification des ajout de méthodes 48-31
ajout 5-32–5-33 données 14-10, 18-24, 18-28 ajout de propriétés 48-31
conception 5-27–5-35 nouveau tri des attributs 48-7
configuration 5-33 champs 20-11 avantages 43-14
masquer 5-34 propriétés d’accès 41-5–41-6 contenu 43-13, 48-1
bascules 5-30, 5-32 relationnelles 13-1 contrôles ActiveX 47-3
base de données temporaire, sécurité 13-3 création 43-13, 48-22
composants 16-9, 17-2 sources de données et 25-6 création de contrôleurs
base de données, suppression de tables 20-18 Automation 45-2
composants 17-4 tables 13-15 déploiement 48-34
bases de données 13-1–13-6, changement de nom 20-18 dérecensement 43-15
14-3, 17-1, 17-10, 41-1 test de l’état 16-5 enregistrement 48-33
accès aux 16-1, 16-7, 20-2, test des associations 16-9 exportation d’un fichier
21-4 transactions 13-4, 14-7 IDL 48-34
accès non autorisé 17-7 types 13-2 IDL et ODL 43-13
ajout de données 18-25– bases de données locales 13-2 inclusion en tant que
18-26, 18-28 bases de données ressources 44-3, 48-34
ajout de tables 20-19 relationnelles 13-1, 15-25, 21-1 informations de type 48-6
alias et 17-5, 20-2 Basic Object Adaptor navigateurs 43-14
application des mises à jour (BOA) 27-2, 27-16 outils 43-15
en mémoire cache 24-6 batAppend, constante 20-21, ouverture 48-31
applications Web et 28-21 20-23 page Utilise (éditeur de
association aux sessions 16-3, batAppendUpdate, types) 48-7
16-9, 17-4 constante 20-21, 20-23 quand les utiliser 43-13
BDE et 14-5 BatchMove, méthode 20-21 recensement 43-15, 48-34
choix 13-2 batCopy, constante 20-21, 20-24 recensement des objets 43-15
connexion 13-3, 14-5 précaution 20-21 référence à d’autres
connexion aux 17-7 batDelete, constante 20-21, 20-24 bibliothèques de types 48-7
connexions batUpdate, constante 20-21, types autorisés 48-22
pooling 49-12 20-23 vérification de la
création 16-3, 17-3 BeforeClose, événement 18-5, syntaxe 48-34
à l’exécution 17-3 18-6, 18-27 visualisation 43-15
dans les applications BeforeConnect, visualisation dans
multithread 14-5 événement 15-32 l’éditeur 48-7
Index I-5
boutons souris 7-25 présentation 7-1–7-5 chaînes 32-2, 32-9
clic 5-34, 7-25, 7-26 propriétés communes, affichages tabulaires 2-37
événements de déplacement méthodes 7-2 association de
souris et 7-27 rafraîchissement de graphiques 6-16
BPL, fichiers 10-1, 12-3 l’écran 7-4 comparaison 18-22
Brush, propriété 2-38, 7-2, 7-8, CanModify, propriété comptage de références 4-27,
35-3 contrôles orientés 4-33
BrushCopy, méthode 35-3, 35-7 données 25-4 conversions PChar 4-33
Business Object Broker 12-6 ensembles de données 18-7 conversions sur 2 octets 11-3
ButtonAutoSize, propriété 26-11 grilles de données 25-29 corruption de la
ButtonStyle, propriété 25-23, requêtes 21-18 mémoire 4-35
25-24, 25-25 tables 20-5 déclaration et
ByteType 4-30 Canvas, propriété 2-39, 30-8 initialisation 4-32
Caption, propriété 2-21, 2-40 directives 4-35
C boîtes groupe 2-32 directives de
boutons radio 2-28 compilation 4-35
.CAB, fichiers 47-20 en-têtes de colonne 25-25 fichiers 4-43
cabinets (définition) 47-20 entrées incorrectes 5-15 jeux de caractères
CacheBlobs, propriété 18-35 grilles de décision 26-14 étendus 4-36
CachedUpdates, libellés 2-35 manipulation 4-25
propriété 18-34, 24-3 caractères 32-2 mélange et conversion de
calendriers 40-1–40-13 caractères accentués 11-9 types 4-33
ajout de dates 40-5–40-10 caractères d’espacement paramètres variables 4-35
définition des propriétés et exécution de requêtes sur position de départ 6-11
événements 40-2, 40-6, des 21-6 présentation des types 4-26
40-11 caractères étendus renvoi 32-9
en lecture seule 41-3–41-4 routines de bibliothèque routines
manipuler 40-10, 40-13 d’exécution 4-29 bibliothèque
redimensionnement 40-4 caractères larges 11-3 d’exécution 4-29
sélection du jour en caractères spéciaux distinction minuscules/
cours 40-10 requêtes et 21-6 majuscules 4-30
CanBePooled 49-6 carrés, dessin 39-9 localisation Windows 4-30
Cancel, méthode 18-6, 18-7, CaseInsFields, propriété 14-14 support des caractères
18-8, 18-27 cases à cocher 2-28, 25-2 multi-octets 4-30
Cancel, propriété 2-27 activation 25-17 taille 6-11
CancelRange, méthode 20-17 orientées données 25-16 traduction 11-2, 11-8, 11-10
CancelUpdates, méthode 18-35, cassettes vidéo 8-5 tri 11-9
24-9 cbsAuto, constante 25-23 tronquer 11-3
canevas 30-7, 35-2, 35-3 CDaudio, disques 8-5 variables locales 4-34
affichage du texte 7-26 CellDrawState, fonction 26-14 chaînes courtes 4-26
ajout de formes 7-11–7-12, CellRect, méthode 2-37 chaînes de caractères
7-15 Cells, fonction 26-14 larges 46-10
dessin 7-2 Cells, propriété 2-37 chaînes longues 4-27
dessin de lignes 7-10, 7-29– CellValueArray, fonction 26-14 champ, objets 19-1
7-30 Center, propriété 2-38 affectation de valeurs 19-23,
gestionnaires cercles, dessin 39-9 19-24
d’événements 7-27 CGI, programmes 3-11, 28-4, affichage seulement 19-8
dessin des lignes 7-11 28-5 ajout 19-1–19-5, 19-7
lignes dessinées 7-5 création 28-6 dynamiques ou
changement de la largeur débogage 28-27 persistants 19-3, 19-4
du crayon 7-6 chaîne, champs événements 19-20
outils de dessin par saisie de données 19-18 propriétés 19-3, 19-14–19-19
défaut 39-5 taille 19-8 exécution 19-16
palettes 35-5–35-6 suppression 19-14
Index I-7
client, sockets 29-3, 29-6–29-7 codes caractères sur deux interfaces 43-3
affectation d’hôtes 29-4 octets 11-2 ajout aux bibliothèques de
connexion aux serveurs 29-9 cohérence types 48-31
demande de services 29-6 transactions 49-7 décompte de
gestion d’événements 29-9 ColCount, propriété 25-32 références 43-4
identification des colonnes 2-36, 25-19 définition 43-2
serveurs 29-6 accès aux 19-2 dérivation 43-4
messages d’erreur 29-8 affectation de valeurs 25-21, identificateurs de
propriétés 29-6 25-23, 25-24 répartition 46-8
socket Windows, objets 29-6 état par défaut 25-19, 25-26 implémentation 43-6
utilisation de threads 29-12 grilles de décision 26-13 informations de
ClientExecute, méthode inclusion dans les tables type 43-12
TServerClientThread 29-14 HTML 28-24 interfaces doubles 46-7
clients de base 49-2, 49-15 modification de valeurs 25-29 marshaling 43-8
ClientType, propriété 29-11, persistantes 25-19, 25-20– objets Automation 46-7
29-12 25-21 optimisation 43-14
Clipboard ajout de boutons pointeur d’interface 43-4
objets graphiques 7-5 aux 25-24 présentation 43-1
test des images 7-24 création 25-22–25-26 proxy 43-7
Clipbrd, unité 6-10, 6-11 insertion 25-22 recensement 3-11
clips AVI 2-39 modification de spécification 43-1, 43-2
clonage de curseurs 23-16 l’ordre 25-23, 25-29 technologies 43-10
CloneCursor, méthode 23-16 suppression 25-20, 25-22, threads et 9-14
Close, méthode 25-23 types de serveurs 43-5
connexions de base de propriétés 25-20, 25-24 COM, objets
données 16-8 réinitialisation 25-26 gestion de la durée de
ensembles de données 18-6 colonnes persistantes 25-19, vie 4-18
requêtes 21-8 25-20–25-21 COMCTL32.DLL 5-27
sessions 16-6 ajout de boutons aux 25-24 commandes utilisateur 5-35,
tables 20-4 création 25-22–25-26 5-37
CloseDatabase, méthode 16-8 insertion 25-22 Commit, méthode 14-7
CLSID 43-5, 43-6, 43-13, 45-7 modification de l’ordre 25-23, CommitUpdates,
CM_EXIT, message 41-12 25-29 méthode 18-35, 24-7
CMExit, méthode 41-12 suppression 25-20, 25-22, CommonAVI, propriété 2-39
CoClasses 43-6 25-23 communication entre
ajout aux bibliothèques de Color, propriété 2-20, 2-38 niveaux 15-5, 15-9, 15-27
types 48-32 crayons 7-6 CORBA 15-10, 15-30
CLSID 43-6 en-têtes de colonne 25-25 DCOM 15-9, 15-28
éditeur de bibliothèques de grilles de décision 26-14 OLE 15-30
types 48-15, 48-27 grilles de données 25-25 OLEnterprise 15-10
instanciation 43-6 pinceaux 7-8 TCP/IP 15-9, 15-29
code 2-6, 34-4 Cols, propriété 2-37 communications 29-1
optimisation 7-16 Columns, propriété 2-30, 25-22 normes
code exemple grilles 25-19 OMG 27-1
interfaces 4-20 ColWidths, propriété 2-37, 6-17 protocoles 28-1, 29-2
Code Insight COM 43-1 connexion,
modèles de applications 43-16 composants 13-12, 15-5
programmation 3-9 composantes 43-2 réseaux 17-8
code source distribuées 3-11 UDP et TCP 27-3
édition clients 43-3, 43-8 standards 28-1
gestionnaires CORBA et 27-1 CompareBookmarks,
d’événements 2-47 experts 43-16, 43-18, 44-1, méthode 18-15
visualisation 44-2 composant enveloppe 42-2
événements partagés 2-46 extensions 43-2, 43-9 composants 2-8–2-9, 31-1, 32-3
gestionnaires d’événe- comparaison des abstraits 30-3
ments spécifiques 2-45 technologies 43-10 accès 2-10
Index I-9
connexions persistantes 16-7, controles 2-8–2-9 propriétés 47-3, 47-9, 47-10
16-8 changement 30-3 liaison 47-12
conseils 2-36 défilement 2-24 publication 47-17
conseils d’aide 2-36 déplacement parmi 2-21 recensement 3-11, 44-6, 47-18
conservation dessin 39-7, 39-9, 40-4 test 44-6, 47-18
mémoire 31-10 dessinés par le contrôles animation 2-39, 8-1–
ressources système 30-4 propriétaire 6-14 8-3
console, applications dessin 6-17 exemple 8-2
CGI 28-5 styles 6-15 contrôles d’édition 25-2, 25-10
constantes d’état fenêtrés 30-4 formats d’édition de texte
mises à jour en mémoire forme 39-3, 39-7, 39-9 formaté 25-11
cache 24-12 génération de contrôles multiligne 25-10
constantes d’état de ActiveX 47-3 sélection de texte 6-10
données 18-4 graphiques 35-4 contrôles d’édition de texte
CONSTRAINT, contrainte 15-25 événements 35-7 formaté 25-11
ConstraintBroker Manager 12-6 options d’affichage 2-20 alignement du texte 6-8
ConstraintErrorMessage, palettes et 35-5–35-6 saisie de texte 6-8–6-14
propriété 19-15, 19-26 personnalisés 30-4 sélection de texte 6-11
Constraints, propriété 5-4, 15-26 position 2-20 contrôles d’entrée 2-24
constructeur de requêtes 21-7 pour modifier les contrôles de saisie 2-13, 2-22–
constructeurs 2-16, 30-13, 32-11, données 41-8–41-13 2-23
34-3, 40-3, 40-4, 41-6 pour scruter les données 41-2 masque 2-22
multiples 5-8 réception de la contrôles de texte
objets ayant un propriétaire focalisation 30-4 multiligne 25-10, 25-11
et 39-5, 39-7 redimensionnement 35-7, contrôles dessinés par le
surcharge 38-2 40-4 propriétaire 2-56, 6-14
Content, méthode regroupement associé 2-32 boîtes liste 2-30
générateurs de page 28-19 scruter les données 41-7 dessin 6-17
Content, propriété taille 2-20 événements 6-17, 6-18
réponse Web, objets 28-16 contrôles ActiveX 43-9, 43-12, styles 6-15
ContentFromStream, méthode 43-18 contrôles éditeur de texte
générateurs de page 28-19 à partir de contrôles formaté 2-22, 2-23
ContentFromString, méthode VCL 47-3 propriétés 2-22
générateurs de page 28-19 à partir de fiches VCL 47-6 contrôles en-tête 2-34
ContentStream, propriété applications Web 43-12 contrôles forme 39-1
réponse Web, objets 28-16, bibliothèques de types 43-13, dessin 39-7, 39-9
28-17 47-3, 48-34 types de propriété 39-3
Contenus, liste (paquets) 10-8, compression de fichiers contrôles graphiques 30-4, 39-1–
10-10 CAB 47-22 39-10
contexte, numéros (aide) 2-36 création 47-1 comparés aux bitmaps
contextes d’objet 49-7 dates de validité 47-25 vs. 39-3
transactions 49-9 déploiement Web 47-18 création 30-4, 39-3
contextes de périphérique 7-2, éléments 47-2 dessin 39-3–39-10
30-7, 35-1 expert 47-2, 47-4 enregistrement des
contraintes 15-25, 15-34, 19-25– fichiers associés 47-24 ressources système 30-4
19-26 gestion d’événements 47-9, événements 35-7
contrôles 5-3–5-4 47-11 contrôles haut-bas 2-25
création 19-25 informations de type 48-2 contrôles onglets 2-33
désactivation 15-34 informations de contrôles orientés
contrat de licence 12-12, 12-13 version 47-22 données 13-12, 19-21, 25-1,
ContrôleBD, page (palette des méthodes 47-9, 47-10 41-1
composants) 2-19, 13-12, 25-2 options 47-5 affichage de données 21-17,
contrôles orientés données 47-9 25-5–25-6
graphiques pages de propriétés 47-12, dans les grilles 25-19,
création 30-4 47-14, 47-16, 47-17 25-20, 25-24, 25-31
Index I-11
D parcours 20-6, 20-9
requêtes 21-18
Netscape, serveurs 28-26
objets MTS 49-22
Data, propriété transactions locales 14-10 Personal Web, serveur 28-26
ensembles de données DBChart, composant 13-14 Decision Cube, page (palette
client 23-15 DBCheckBox, composant 25-2, des composants) 2-19, 13-14
data/heure, champs 19-18 25-16 déclarations
Database, composants 17-1 DBCLIENT.DLL 12-6, 14-12, classes 31-10, 39-5
Database, propriété 18-32 15-3, 23-1 protégées 31-6
DatabaseName, propriété 14-3, DBComboBox, composant 25-2, publiques 31-6
17-5, 18-32, 18-33, 20-2 25-13 publiées 31-7
DataChange, méthode 41-11 DBCtrlGrid, composant 25-2, gestionnaires
DataField, propriété 25-13, 25-31–25-32 d’événements 33-6, 40-12
25-16, 41-5, 41-6 propriétés 25-32 gestionnaires de
DataSet, composant 18-2 DBEdit, composant 25-2, 25-10 messages 36-5, 36-7
DataSet, propriété 25-7 DBGrid, composant 25-2, 25-18 méthodes 7-16, 34-4
fournisseurs 15-17 événements 25-30 dynamiques 31-10
grilles de données 25-19 propriétés 25-25, 25-27 publiques 34-3
DataSetCount, propriété 17-10 DBGridColumns, statiques 31-8
DataSetField, propriété composant 25-19 virtuelles 31-9
ensembles de données DBHandle, propriété 18-32 nouveaux types de
client 23-4 DBImage, composant 25-2, composants 31-3
DataSets, propriété 17-10 25-12 objets 2-4, 2-9, 2-12, 2-16
DataSource, composant DBListBox, composant 25-2, propriétés 32-3, 32-4–32-7,
ajout 25-6, 25-7 25-13 32-8, 32-12, 39-4
événements 25-8 DBLocale, propriété 18-32 stockées 32-12
propriétés 25-6–25-8 DBLookupComboBox, types définis par
DataSource, propriété 2-63, 25-2, composant 25-2, 25-14–25-16 l’utilisateur 39-3
25-16, 25-35 DBLookupListBox, variables 2-4
contrôles orientés composant 25-2, 25-14–25-16 exemple 2-14
données 41-6 DBMemo, composant 25-2, déclarations de type
grilles de données 25-19 25-10 modules de données 2-61
requêtes 21-11 DBNavigator, composant 25-2, objets et 2-5, 2-11, 2-14, 2-16
DataSource, propriété 25-33–25-36 propriétés 39-3
contrôles orientés DBRadioGroup, types énumérés 7-13
données 41-5 composant 25-2, 25-17 déclencheurs 13-6
date, champs 19-18 DBRichEdit, composant 25-11 DECnet 29-1
formatage des valeurs 19-19 DBSession, propriété 18-32 décompte de références
dates DBText, composant 25-2, 25-9 COM interfaces 43-4
internationalisation 11-9 DCOM 43-7 objets COM 43-4
DateTimePicker, applications déconnexion 16-8, 17-9
composant 2-32 multiniveaux 15-9 default
DAX 43-2 connexion au serveur directive 32-11, 38-3
Day, propriété 40-5 d’applications 15-28 mot réservé 32-8
DB/2, pilote distribution Default, propriété 2-27
déploiement 12-6 d’applications 3-11 éléments d’action 28-11
dBASE, tables 20-2, 20-3 MTS 49-15 DEFAULT_ORDER 23-7
accès aux données 20-5, 21-4 .DCP, fichiers 10-2, 10-14 DefaultColWidth, propriété 2-37
ajout d’enregistrements 18-26 .DCR, fichiers 37-4 DefaultDrawing, propriété 2-36,
création d’alias 16-12 .DCU, fichiers 10-2, 10-14 25-30, 25-31
DatabaseName 14-3 débogage DefaultExpression,
index 20-10 applications serveur propriété 19-25
mémo, champs 25-10, 25-11 Web 28-25–28-28 DefaultHandler, méthode 36-3
niveaux d’isolement 14-9 contrôles ActiveX 44-6, 47-18 DefaultRowHeight,
ouverture des Microsoft IIS, serveur 28-26 propriété 2-37
connexions 16-7
Index I-13
données DriverName, propriété 17-5 interfaces CORBA 27-6
affichage 19-21 droits d’accès 20-5 interfaces de
dans les grilles 25-19, DropConnections, méthode 16-9 répartition 48-13, 48-27
25-20, 25-24, 25-31 DropDownCount, modules 48-20, 48-30
désactivation de propriété 2-31 ouverture de
l’affichage 25-5 DropDownMenu, propriété 5-34 bibliothèques 48-31
ensembles de données DropDownRows, page Attributs 48-5
multiples 25-35 propriété 25-16, 25-25 page Indicateurs 48-6
intervalles de dsBrowse, constante 18-6 page Texte 48-6
rafraîchissement 25-5 dsEdit, constante 18-7 page Utilise 48-7
valeurs en cours 25-10 dsFilter, constante 18-10 pages d’informations de
affichage seulement 25-9 DsgnIntf, uniét 37-7 type 48-5
analyse 13-14 dsInsert, constante 18-8 Pascal Objet ou IDL 48-22,
enregistrement 18-27 dsSetKey, constante 18-9 48-24
établissement de durabilité serveurs d’applications 15-39
rapports 13-16 dispenseurs de syntaxe 48-6, 48-22, 48-24
formats, ressources 49-12 types énumérés 48-16, 48-28
internationalisation 11-9 transactions 49-8 unions 48-19, 48-29
impression 13-16 dynamic, directives 31-10 vérification de la
modification 18-24, 18-28, syntaxe 48-34
25-4 E volet liste des objets 48-4
transactions et 14-10 éditeur de champs 19-5
représentation E/S de fichier application d’attributs de
graphique 13-14 types 4-40 champ 19-17
saisie de 18-25, 18-26 EAbort 4-13 création de champs
synchronisation 20-27 écran persistants 19-6
sur plusieurs fiches 25-7, rafraîchissement 7-4 définition d’ensembles
25-8 écriture des paramètres de d’attributs 19-17
valeurs par défaut 19-25, propriété 32-7, 32-9, 37-9 modification de l’ordre des
25-12 EDBEngineError, type 24-30 colonnes 25-29
valeurs prédéfinies 25-13 Edit, méthode 18-7, 18-24, 37-10, suppression d’ensembles
données affichage 37-11 d’attributs 19-18
seulement 25-9 éditeur d’action suppression d’objets
données en lecture seule ajout d’actions 28-9 champ 19-14
ensembles de données changement d’actions 28-10 éditeur de code
client 23-5 éditeur de bibliothèques de affichage 37-16
données membres classe types 48-2 gestionnaires d’événements
déclaration 39-5 ajout d’interfaces 48-31 et 2-44, 2-45
données membres de classe ajout de CoClasses 48-32 ouverture des paquets 10-9
nommer 33-3 ajout de méthodes 48-31 éditeur de collection de
double identificateurs 2-11 ajout de propriétés 48-31 paquets 10-15
double-clics ajout de types éditeur de colonne
composants 37-13 énumérés 48-32 suppression de
réponse aux 37-15–37-16 alias 48-17, 48-28 colonnes 25-23
Down, propriété 2-27 attributs d’aide 48-6 éditeur de colonnes
turboboutons 5-29 barre d’état 48-4 création de colonnes
.DPC, fichiers 10-14 barre d’outils 48-3 persistantes 25-22
.DPK, fichiers 10-2, 10-8 CoClasses 48-15, 48-27 définition des listes de
.DPL, fichiers 10-2, 10-14 création de bibliothèques de choix 25-24
DragCursor, propriété 2-21 types 48-22 modification de l’ordre des
DragMode, propriété 2-21, 6-1 éléments principaux 48-2 colonnes 25-23
grilles 25-29 enregistrements 48-18, 48-29 éditeur de cube de décision 26-8
Draw, méthode 7-2, 35-3, 35-7 erreurs 48-4 éditeur de masque de
DrawShape 7-16 informations de type 48-6 saisie 19-18
interfaces 48-8, 48-26
Index I-15
Enregistrer comme modèle, obtention des valeurs ensembles de données multiples
commande (menu précédentes 24-12, 24-31 mise à jour 24-6
Concepteurr) 5-21 orientés BDE 18-31 ensembles de données
Enregistrer sous, ouverture 18-3 personnalisés 13-16
commande 14-14 sur serveurs distants 16-7 ensembles de résultat
ensemble de données, parcours 18-6, 25-33 lecture seule 24-25
champs 13-16, 19-31 personnalisés 13-16 mise à jour 21-19, 24-25
ensembles de données recherche 18-9, 18-16–18-18 ensembles de résultat 21-14,
client 23-4 référencement 24-28 21-17–21-19
ensembles 32-2 sources de données et 25-6 curseurs et 21-17
ensembles d’attributs 15-34 suppression édition 21-18
ensembles d’onglets 2-33 d’enregistrements 18-27 mise à jour 21-19
ensembles de données 13-14, test de l’état 16-5 obtention à l’exécution 21-14
18-2 ensembles de données ensembles de résultat en lecture
accès aux 18-31, 25-7 client 13-15, 15-3, 23-1–23-23 seule
activation 17-10 ajout d’index 23-10 mise à jour 24-25
affichage de plusieurs 25-35 annulation des ensembles de résultat
ajout d’enregistrements 18-8, modifications 23-6 modifiables 21-18, 21-18–21-19
18-25–18-26, 18-28 champs calculés 23-10
application des mises à jour constraintes 23-4 mise à jour 24-25
en mémoire cache 24-6, copie de données 23-14, restrictions 21-18, 21-19
24-7 23-15 en-têtes
association aux sessions 16-3, création de tables 23-21 HTTP, requêtes 28-2
17-4 données linéaires 23-21– en-têtes de colonnes 2-34, 25-21,
composants d’aide à la 23-23 25-25
décision 26-5–26-7 édition 23-5 en-têtes de message
copie 20-24 enregistrement des (HTTP) 28-1, 28-2
création 14-13 modifications 23-6 en-têtes de réponse 28-16
déplacement dans les 18-10– fournisseurs et 23-16–23-20 en-têtes de requête 28-13
18-14, 18-23 fusion des enveloppes 30-5, 42-2
édition 18-7 modifications 23-22 initialisation 42-3
en tant que tables index 23-7–23-10 enveloppes de composant 30-5
logiques 13-14 ajout 23-8 EOF, marqueur 4-44
état par défaut 18-4 lecture seule 23-5 EOF, propriété 18-12, 18-13
états 18-3 limitation des EPasswordInvalid 4-15
modification 25-8 enregistrements 23-3, 23-18 EReadError 4-43
fermeture 16-6, 17-9, 18-3, mise à jour de données 23-20 erreurs
18-5 mises à jour en mémoire actions groupées 20-26
sans déconnexion 17-10 cache 24-3 fournisseurs de
sur serveurs distants 16-7 navigation 23-2 données 15-24
filtrage paramètres 23-17 mises à jour en mémoire
d’enregistrements 18-10, partage de données 23-16 cache 24-28–24-31
18-19–18-22 permutation d’index 23-8 précaution 24-28
gestion d’événements 18-29 regroupement des override, directive et 31-9
HTML, documents 28-24 données 23-9 sockets 29-9
imbriqués 13-16 relations maître/détail 23-3 erreurs de compilation
mise à jour 24-13, 24-24, requête de données 23-18 override, directive et 31-9
24-25, 24-28 spécification des ErrorAddr, variable 4-15
modes 18-3 fournisseurs 23-16 et commercial (&),
modification 18-24, 25-8 suppression d’index 23-8 caractère 5-17
modification des synthèse des données 23-11– événement, objets 9-10
données 18-24, 18-28, 25-4 23-14 événements 2-45, 25-6, 30-7,
obtention de la valeur en ensembles de données de 33-1–33-10
cours 24-31 décision 26-6 accès 33-6
Index I-17
principale 5-1 suppression 4-37 FillRect, méthode 7-3, 35-3
propriétés de requête taille 4-44 Filter, propriété 18-19, 18-20
exemple 5-9 types Filtered, propriété 18-19
récupération des données E/S 4-40 filtres 18-10, 18-19–18-22, 20-12
depuis 5-8–5-12 sans type 4-41 activation/
référencement 5-2 texte 4-41 désactivation 18-19
synchronisation des typés 4-41 définition à l’exécution 18-22
données 20-27 types incompatibles 4-41 ensembles de données
sur plusieurs 25-7, 25-8 fichiers d’application 12-2 client 23-3
transmission d’arguments fichiers d’index 20-10 requêtes et 18-19
aux 5-7–5-8 fichiers d’index non requêtes ou 21-2
utilisation des variables productifs 20-10 filtres de données 18-10, 18-19–
locales pour créer 5-7 fichiers de collection de 18-22, 20-12
variable globale pour 5-5 paquet 10-14 activation/
fiches détail fichiers de contrôle réseau 16-14 désactivation 18-19
mises à jour en mémoire .DLL, fichiers 12-4 définition à l’exécution 18-22
cache et 24-8 fichiers exécutables requêtes et 18-19
fiches maître/détail 20-28 internationalisation 11-11, requêtes ou 21-2
mises à jour en mémoire 11-13 finally, mot réservé 35-7, 42-5
cache et 24-8 serveurs COM 43-6 FindClose, procédure 4-37
fiches modales 5-7 fichiers INI 2-58 FindDatabase, méthode 16-9
fiches multiples 25-7, 25-8 fichiers linéaires 23-21–23-23 FindFirst, fonction 4-37
fichier agentaddr 27-20 chargement 14-16, 23-21 FindFirst, méthode 18-23
fichier IDL 27-6 enregistrement 14-16, 23-22 FindKey, méthode 18-9, 20-6,
exportation à partir de la tables imbriquées et 23-4 20-8
bibliothèque de types 27-7 fichiers palette des bitmaps 37-4 EditKey ou 20-9
exportation depuis une fichiers ressource précaution d’utilisation 20-6
bibliothèque de types 48-34 chargement 5-26 FindLast, méthode 18-23
recensement 27-9 fichiers ressource FindNearest, méthode 18-9,
fichier localaddr 27-21 et bibliothèques de 20-6, 20-8
fichiers 4-36–4-45 types 43-14 précaution d’utilisation 20-6
attributs 4-39 fichiers source FindNext, fonction 4-37
chaînes 4-43 paquets 10-2, 10-8, 10-9, FindNext, méthode 18-23
copie 4-40 10-14 FindPrior, méthode 18-23
copie d’octets depuis 4-45 fichiers unité FindResourceHInstance,
déplacements 4-44 nommer 2-60 fonction 11-12
écriture vers 4-43 FieldByName, méthode 19-24, FindSession, méthode 16-18
envoi par le Web 28-17 20-15 First Impression 12-3
graphiques 7-20–7-22 FieldCount, propriété First, méthode 18-11
graphiques et 35-4 champs persistants 25-21 FixedColor, propriété 2-37
handles 4-40, 4-41, 4-42 FieldKind, propriété 19-15 FixedCols, propriété 2-37
lecture depuis 4-43 FieldName, propriété 19-8, FixedOrder, propriété 2-29, 5-33
manipulation 4-36, 4-37– 19-15 FixedRows, propriété 2-37
4-40–4-45 champs persistants 25-21 FixedSize, propriété 2-29
modes 4-42 grilles de décision 26-14 FlipChildren, méthode 11-7
position 4-44 grilles de données 25-23, FloodFill, méthode 7-3, 35-3
recherche 4-37 25-25 flux
renommer 4-39 Fields, propriété 19-23 utilisation 2-58
ressource 5-26–5-27 FileAge, fonction 4-40 flux de fichier 4-41–4-45
routines FileExists, fonction 4-37 création 4-42
bibliothèque FileGetDate, fonction 4-40 E/S de fichier 4-41–4-45
d’exécution 4-37 FileName, propriété exceptions 4-43
date-heure 4-40 client, ensembles de fin de marqueur 4-44
Windows API 4-41 données 14-16 mécanisme de flux de la
routines date-heure 4-40 FileSetDate, fonction 4-40 VCL 4-41
Index I-19
GetDriverNames, modèles 26-18 graphiques indépendants des
méthode 16-10 options d’affichage 26-17 périphériques 35-1
GetDriverParams, personnalisation 26-17–26-19 graphiques, objets
méthode 16-10 présentation 26-15 threads 9-5
GetFieldByName, Graphic, propriété 7-19, 7-22, GridLineWidth, propriété 2-37
méthode 28-13 35-4 grille de données 25-2
GetFloatValue, méthode 37-9 graphiques 25-12, 35-1 grilles 2-36–2-37, 25-2, 40-1,
GetIDsOfNames, méthode 46-8 affichage 2-38–2-39 40-2, 40-5, 40-11
interfaces vtable et 46-9 ajout au document affichage des données 25-19,
GetIndexNames, méthode 20-10 HTML 28-18 25-20, 25-24, 25-31
GetMethodValue, méthode 37-9 ajout de contrôles 7-18 ajout de lignes 18-25
GetOptionalParam, changement des images 7-21 dessin 25-30
méthode 15-19 chargement 7-20, 35-4, 35-5 édition 25-29
GetOrdValue, méthode 37-9 coller 7-24 édition des données 25-5
GetPalette, méthode 35-6 complexes 35-6 état par défaut 25-19
GetPassword, méthode 16-16 conteneurs 35-4 restauration 25-26
GetProperties, méthode 37-11 contrôle de leur gestion des
GetProviderNames, apparition 7-4 événements 25-30
méthode 15-8 contrôles dessinés par le insertion de colonnes 25-22
GetSessionNames, propriétaire 6-14 modification de l’ordre des
méthode 16-18 copie 7-23 colonnes 25-23, 25-29
GetStoredProcNames, dessin 7-2 obtention des valeurs 25-19,
méthode 16-10 dessin d’images 35-7 25-20
GetStrValue, méthode 37-9 dessin de lignes 7-10–7-11, à l’exécution 25-21
GetTableNames, méthode 16-10 7-29–7-30 options à l’exécution 25-27
GetValue, méthode 37-9 gestionnaires orientées données 13-13,
GetVersionEx, fonction 12-12 d’événements 7-27 25-31
glisser-déplacer 2-21, 6-1–6-4 enregistrement 7-21 personnalisation 25-20–25-22
début de l’opération 6-1 exemple "rubber propriétés 25-32
événements 39-2 banding" 7-24–7-30 saisie de données 25-23,
exemple 2-15 fichiers 7-20–7-22 25-24
fin de l’opération 6-4 fonctions, appel 35-1 suppression des
obtention d’informations formats de fichiers 7-5 colonnes 25-20, 25-22, 25-23
d’état 6-4 indépendants 35-3 grilles de chaînes 2-37
personnalisation 6-4 internationalisation 11-9 grilles de couleurs 7-6
glisser-empiler 6-5–6-8 lignes dessinées 7-5 grilles de décision 26-12–26-14
propriétés 2-21 changement de la largeur affichage des données 26-13
Glyph, propriété 2-27, 5-29 du crayon 7-6 comportements à
GotoBookmark, méthode 18-16 listes de chaînes 2-56, 6-15 l’exécution 26-21
GotoCurrent, méthode 20-27 méthodes 35-3, 35-5, 35-7 création 26-12
GotoKey, méthode 18-9, 20-7 copie d’images 35-7 états en cours des
précaution d’utilisation 20-6 palettes 35-6 pivots 26-10
GotoNearest, méthode 18-9, outils de dessin 35-2, 35-8, événements 26-14
20-7, 20-8 39-5 modification de l’ordre des
précaution d’utilisation 20-6 changement 39-7 colonnes/lignes 26-13
Graph Custom Control 12-3 présentation 35-1–35-3 présentation 26-12
graphes de décision 26-15–26-20 présentation de la propriétés 26-14
changement du type de programmation 7-1–7-5 grilles de dessin 2-36
graphe 26-19 redimensionnement 7-22, grilles de données 13-13, 25-2,
comportements à 25-12, 35-7 25-31
l’exécution 26-21 remplacement 7-21 affichage des champs
création 26-15 stockage 35-4 ADT 25-26
définition des séries de suppression 7-23 affichage des champs
données 26-19–26-20 types d’objets 7-4–7-5 tableau 25-26
états en cours des graphiques défilables 7-18 affichage des données 25-19-
pivots 26-10 25-20, 25-24, 25-31
Index I-21
IDL (Interface Description index 20-10–20-12, 32-9 Insérer depuis la ressource,
Language) 43-15 actions groupées et 20-24, commande (menu
IDL, compilateur 43-15 20-25 Concepteur) 5-21, 5-26
idl2ir 27-9 client, ensembles de Insérer depuis le modèle,
IETF, protocoles et données 14-14 commande (menu
standards 28-1 ensembles de données Concepteur) 5-21, 5-23
IID 43-3 client 23-7–23-10 Insert, commande (Menu
Image, balise HTML extraction 20-10, 20-11 Concepteurr) 5-21
(<IMG>) 28-18 recherche sur des clés INSERT, instructions 21-14,
ImageIndex, propriété 5-31, partielles 20-8 21-15, 24-13
5-33, 5-38 regroupement des Insert, méthod
ImageMap , balise HTML données 23-9 chaînes 2-52
(<MAP>) 28-19 secondaires 20-9, 20-10 Insert, méthode 2-30, 18-8, 18-26
images 2-38, 7-18, 25-2, 35-3, tri sur des portées 20-14, Append et 18-25
35-3–35-6 20-15, 20-16 menus 5-25
ajout 7-18 index primaires 20-10 insertion
ajout aux menus 5-19 actions groupées et 20-24, d’enregistrements 18-8, 18-26,
boutons outils 5-31 20-25 20-24
changement 7-21 index secondaires 20-9, 20-10 Insertion de modèle, boîte de
chargement 7-20 recherche avec des 20-8 dialogue 5-23
contrôles 7-17 index, mot réservé 40-7 Insertion depuis la ressource,
contrôles pour 7-4 Index, propriété 19-15 boîte de dialogue 5-26
défilement 7-18 IndexFieldCount, InsertRecord, méthode 18-28
dessin 35-7, 39-8 propriété 20-12 InsertSQL, propriété 24-13
effacement 7-23 IndexFieldNames, inspecteur d’objets 32-2, 37-7
enregistrement 7-21 propriété 20-9, 20-11 affichage des propriétés 2-40,
internationalisation 11-9 IndexName ou 20-11 2-41
pinceaux 7-9 IndexFields, propriété 20-12 définition des
réaffichage 7-4 IndexFiles, propriété 20-10 propriétés 2-40, 2-41, 2-42
remplacement 7-21 IndexName, propriété 20-9, écriture des gestionnaires
renforcement du contrôle 20-10, 20-11 d’événements 2-44
des 6-16 IndexFieldNames ou 20-11 modification des propriétés
Images, propriété IndexOf, méthode 2-51 de tableau 32-3
boutons outils 5-31 indicateurs 41-4 inspecteur d’objets
IMalloc, interface 4-15 .INF, fichiers 47-21 aide sur 37-4
IMarshal, interface 46-9 INFINITE, constante 9-11 sélection des menus 5-22
IME 11-8 information de type Installer composant,
ImeMode, propriété 11-8 exécution 31-7 commande 2-67
ImeName, propriété 11-8 informations d’état 2-35 Installer paquet,
implémentation événements souris 7-25 commande 2-67
d’événements 33-2 informations de type 43-13 InstallShield Express 12-1
implements, mot clé 4-20, 4-21 informations de version déploiement de MIDAS 12-7
$IMPLICITBUILD, directive de contrôles ActiveX 47-5, 47-8 déploiement de paquets 12-3
compilation 10-11 informatique nomade 14-17 déploiement de SQL
importation de données 20-21 Informix, pilotes Links 12-6
ImportedConstraint, déploiement 12-6 déploiement des
propriété 19-15, 19-26 Informix, serveurs 21-4 applications 12-2
$IMPORTEDDATA, directive INI, fichiers déploiement du moteur de
de compilation 10-11 Win-CGI, programmes 28-5 bases de données
Importer une bibliothèque de initialisation Borland 12-5
types, commande 45-2 composants 32-12, 39-7, 41-6 instanciation
impression de texte 2-23 méthodes 32-12 modules de données
Indent, propriété 2-31, 5-29, threads 9-3 CORBA 15-16
5-31, 5-33 modules de données
distants 15-14
Index I-23
ItemHeight, propriété 2-30 Kind, propriété liens de données 20-28, 41-5–
boîtes à options 25-14 boîtes de défilement 2-34 41-7
boîtes liste 25-13 boutons bitmap 2-27 initialisation 41-6
ItemIndex, propriété 2-30 liens hypertextes
Items, propriété 2-30, 2-32 L ajout au document
boîtes à options 25-13 HTML 28-18
boîtes liste 25-13 label 30-4 lignes 2-36, 18-25
contrôles radio 25-18 LargeChange, propriété 2-24 dessin 7-10, 7-10–7-11, 7-29–
ITypeComp, interface 43-14 Last, méthode 18-11 7-30
ITypeInfo, interface 43-14 Layout, propriété 2-27 dessin de gestionnaires
ITypeLib, interface 43-14 -LEpath, directive de d’événements 7-27
IUnknown, interface 4-18, 4-23, compilation 10-13 dessinées 7-5
43-3, 43-4, 43-17, 43-18, 46-8 lecteurs de cassettes audio- changement de la largeur
implémentée dans numériques 8-5 du crayon 7-6
TInterfacedObject 4-18 lecteurs multimédia 8-3–8-6 effacement 7-30
exemple 8-5 grilles de décision 26-13
J lecture des changements non lignes de séparation
validés 14-8 (menus) 5-17
jeux de caractères 4-29, 11-2, lecture des paramètres de limites
11-2–11-4 propriété 32-9, 37-9 portées de données 20-16
ANSI 11-2 lecture seule limites des rectangles 7-11
conversions sur 2 octets 11-2 propriétés 31-6 Lines, propriété 2-22, 32-9
OEM 11-2 lecture seule, champs 25-4 LineSize, propriété 2-25
ordres de tri lecture seule, LineTo, méthode 7-3, 7-8, 7-10,
internationaux 11-9 enregistrements 18-8 35-3
par défaut 11-2 lecture seule, ensembles de Link, balise HTML (<A>) 28-18
jeux de caractères sur deux résultats 21-19 List, propriété 16-19
octets 11-2 Left, propriété 2-20, 5-3 liste Contient (paquets) 37-17
jointures 21-16 LeftCol, propriété 2-37 liste Nécessite (paquets) 37-17
mises à jour en mémoire Length, fonction 4-32 listes 2-29–2-31
cache et 24-26 liaison à l’avance 27-12 propriétés 2-30
jointures hétérogènes 21-16 liaison anticipée 15-33 utilisation dans les
journal de modifications 23-5, liaison de fiche 5-2 threads 9-5
23-22 liaison de vtable listes à défilement 25-13
annulation des liaison immédiate listes d’action 5-35–5-44
modifications 23-6 COM 43-13 listes de chaînes 2-50–2-57, 6-18
enregistrement des liaison différée accès aux chaînes 2-57
modifications 23-6 Automation 46-9 ajout d’objets 2-56–2-57, 6-15
juste à temps, activation 15-7 liaison dynamique 15-33, 27-13 allocation de la mémoire
CORBA 27-14–27-16 pour 2-54
K liaison retardée 27-13 contrôles dessinés par le
CORBA 27-4 propriétaire 6-16
K, notes de bas de page DII 27-4 conversions minuscules/
(système d’aide) 37-5 liaison statique 15-33, 27-12 majuscules 2-51
KeepConnection, propriété 16-6, COM 43-13 copie 2-53
17-8 liaison tardive 15-33 copie des variables
KeepConnections, libellés 2-35, 11-9, 25-2 locales 2-53
propriété 16-6 colonnes 25-21 création 2-54
TSession, composant 14-4 libération des ressources 42-5 déplacement 2-52
KeyDown, méthode 41-10 libération mémoire 2-17 dessinées par le
KeyExclusive, propriété 20-8, libre, modèle de thread 44-5 propriétaire 6-15
20-16 licence de conception insertion de chaînes 2-57
KeyField, propriété 25-16 contrôles ActiveX 47-5, 47-7 itération 2-51
KeyFieldCount, propriété 20-8 liens 20-28 manipulation des
KeyViolTableName,
chaînes 2-50–2-51
propriété 20-27
Index I-25
définis 36-2 déclaration 7-16, 34-4 MIDAS (Multi-tier Distributed
définis par l’utilisateur 36-5, dynamiques 31-10 Application Services
36-7 publiques 34-3 Suite) 15-2, 15-3
enregistrements statique 31-8 MIDAS, page (palette des
types, déclaration 36-6 virtuelles 31-9 composants) 2-19, 15-3, 15-27
gestion 36-5 dessin 39-8, 39-9 MIDI, fichiers 8-5
gestionnaires 36-1, 36-3, 40-4 destructeur 2-17 MIDL
création 36-5–36-8 exposition à génération des fichiers d’en-
déclarations 36-5, 36-7 l’Automation 46-4 tête 43-15
par défaut 36-3 gestion de génération du code proxy/
surcharge 36-4 messages 36-1, 36-4 stub 43-15
identificateurs 36-6 gestionnaires MIME, messages 28-4
souris 41-9 d’événements 33-3, 33-5, Min, propriété
messages d’erreur 24-30 33-6 barres de défilement 2-24
internationalisation 11-10 surcharge 33-6 barres de progression 2-35
messages de la souris 41-9 graphiques 35-3, 35-5, 35-7 barres graduées 2-24
messages de réponse 28-7 palettes 35-6 contrôles haut-bas 2-25
contenu 28-16, 28-17–28-25 héritées 33-6 MinSize, propriété 2-26
création 28-15–28-17, 28-17– initialisation 32-12 MinValue, propriété 19-15
28-25 interruption 18-30 mise à jour d’enregistrements
envoi 28-12, 28-17 nommer 34-2 clients multiniveaux 23-20
informations d’en-tête 28-15– objets et 2-3, 2-5, 2-9, 2-11 opérations groupées 20-24
28-16 propriétés et 32-5–32-7, 34-1, mise à jour des données
informations de base de 34-2, 39-4 applications
données 28-21–28-25 protégées 34-3 multiniveaux 15-18, 15-23
informations de statut 28-15 publiques 34-3 filtrage des mises à
réponse aux 28-16 redéfinition 31-9 jour 15-24
messages de requête 28-7 répartition 31-8 procédures stockées 15-21
contenu 28-15 suppression des delta, paquets 15-22
éléments d’action 28-10 gestionnaires d’événements mise à jour des
HTTP, présentation 28-3– et 2-47 enregistrements 25-8
28-4 surcharge 2-11, 31-9, 36-3, clients multiniveaux 15-35
informations d’en-tête 28-13– 40-11 ensembles de données
28-15 virtuelles 31-9, 34-4 multiples 24-6
répartition 28-9 méthodes dynamiques 31-10 régularisation des mises à
réponse aux 28-12, 28-15 méthodes graphiques jour 15-36, 23-20
traitement 28-9 palettes 35-6 requêtes et 21-19
types 28-14 méthodes statiques 31-8 mise à jour, objets 24-13
messages du clavier 41-9 méthodes virtuelles 31-9 mise en correspondance des
messages souris 36-2 MethodType, propriété 28-10, types de données 20-25
métadonnées 20-24 28-14 mise en mémoire cache des
obtention auprès des Microsoft threads 9-12, 29-15
fournisseurs 23-19 ATL (Active Template mises à jour en cascade 15-19
métafichiers 2-38, 7-2, 7-17, 7-20, Library) 43-2 mises à jour en mémoire
35-4 Microsoft IIS, serveur cache 18-34, 24-1
metafile débogage 28-26 activation/désactivation 24-3
quand les utiliser 7-5 Microsoft Server, DLL 28-5 annulation 24-9–24-10
Method, propriété 28-14 création 28-6 application 24-5
méthodes 7-16, 30-7, 34-1, 40-10 messages de requête 28-7 constantes de type
accès 2-11, 2-12 Microsoft SQL Server, pilote d’enregistrement 24-11
appel 33-6, 34-3, 39-4 déploiement 12-6 en suspens 24-4
Automation et 46-7 MIDAS 12-12, 15-2, 15-3 ensembles de données client
champ, objets 19-20 DBCLINT.DLL 12-6 et 24-3
constructeur 2-16 déploiement 12-6, 12-13 extraction
contrôles ActiveX 47-9, 47-10 fichiers 12-7 d’enregistrements 24-4
licences serveur 15-3
Index I-27
MouseToCell, méthode 2-37
.MOV, fichiers 8-5
N NOT NULL, contrainte 15-25
notes de dernière minute 12-13
Move, méthode Name, propriété 2-40, 2-60, notification d’événements 33-8
chaînes 2-52, 2-57 19-15, 25-7 Nouveau champ, boîte de
MoveBy, méthode 18-12 navigateur 18-11, 18-12, 25-2, dialogue 19-8
MoveCount, propriété 20-26 25-33–25-36 définition de champs 19-10,
MoveFile, fonction 4-40 activation/désactivation des 19-13
MovePt 7-29 bouton 25-34 Nouveau champ,boîte de
MoveTo, méthode 7-3, 7-8, 35-3 activation/désactivation des dialogue
.MPG, fichiers 8-5 boutons 25-34 définition de champs 19-11
MTS 3-12, 43-2, 43-9, 49-1 boutons 25-33 définition des champs 19-9
activités 49-18 édition et 18-25 Nouveau module de données,
administration des panneaux commande (Fichier) 2-59
objets 49-23 d’information 25-35 nouveau tri des champs 20-11
applications de base de suppression de Nouveau, commande 30-11
données multiniveaux 15-8 données 18-27 Nouveaux éléments, boîte de
callbacks 49-20 navigateur de base de dialogue 2-63, 2-65
clients de base 49-2, 49-15 données 18-11, 18-12, 25-2, ajout de modèles
composants 49-2 25-33–25-36 personnalisés 2-64
contextes d’objet 49-7 activation/désactivation des sélection des modèles de
exigences 49-4 boutons 25-34 projets 2-66
interface IProvider et 15-5 boutons 25-33 Nouvel objet thread, boîte de
libération des ressources 49-6 édition et 18-25 dialogue 9-2
paquets 49-14 panneaux NSAPI, applications 3-11, 28-5
pooling des connexions aux d’information 25-35 création 28-6
bases de données 49-5 suppression de débogage 28-25
pooling des objets 49-6 données 18-27 messages de requête 28-7
précaution d’utilisation lors navigation dans les ensembles null, valeurs 18-28
de la connexion aux bases de données 18-10–18-14 18-23 Null, variable 45-7
de données 15-7 Nécessités, liste (paquets) 10-8, NumGlyphs, propriété 2-27
références aux objets 49-19 10-10
regroupement des NetBEUI, protocole 17-8 O
connexions de base de NetFileDir, propriété 16-14
données 15-7 Netscape Server, DLL 28-5 OAD 27-4, 27-9
sécurité 49-12 création 28-6 annulation du recensement
transactions 49-5, 49-7 messages de requête 28-7 d’objets 27-11
attributs 49-8 Netscape, serveurs exécution 27-10
contrôlées par le débogage 28-26 recensement des
client 49-10 NewValue, propriété 24-31 serveurs 27-10–27-12
temporisations 49-11 Next, méthode 18-12 oadutil 27-11
Multiline, propriété 2-33 niveaux 15-1 Object , balise HTML
multimédia 8-1–8-6 niveaux d’isolement 14-8–14-9 (<OBJECT>) 28-19
multiniveaux, ODBC, pilotes 14-9 Object Activation Daemon
applications 18-34 nom de démarrage du (OAD) 27-4, 27-9
architecture 15-4 service 3-8 annulation du recensement
Multi-niveaux, page (Nouveaux nombres 32-2 d’objets 27-11
éléments, boîte de formatage 19-19 exécution 27-10
dialogue) 15-3 internationalisation 11-9 recensement des
multipages, boîtes de valeurs de propriété 32-11 serveurs 27-10–27-12
dialogue 2-33 noms d’hôte 29-4 Object Management Group
MultiSelect, propriété 2-30 IP, adresses ou 29-4 (OMG) 27-1
multithread, applications 9-1 noms de pilote 17-5 Object Request Broker
multitraitement non modales, fiches 5-5 (ORB) 27-1, 27-16
threads 9-1 non visuels, objets 2-16–2-17 ObjectContext
mutuellement exclusifs, NOT NULL UNIQUE, exemple 49-21
options 5-29 contrainte 15-25
Index I-29
OnDecisionExamineCell, OnMouseDown, OpenDatabase, méthode 16-5,
événement 26-14 événement 7-25, 33-5, 41-9 16-7
OnDisconnect, événement paramètres transmis à 7-25 OpenSession, méthode 16-18,
client, sockets 29-7 OnMouseMove, 16-19
OnDragDrop, événement 6-3, événement 7-25, 7-27, 33-5 OpenString 4-28
25-31, 33-5 paramètres transmis à 7-25 opérateurs
OnDragOver, événement 6-2, OnMouseUp, événement 7-15, filtres de données 18-21
25-31, 33-5 7-25, 7-26, 33-5 opérateurs de
OnDrawCell, événement 2-36 paramètres transmis à 7-25 comparaison 18-21
OnDrawColumnCell, OnNewDimensions, opérateurs logiques 18-21
événement 25-30, 25-31 événement 26-10 opérations avec effet 35-7
OnDrawDataCell, OnPaint, événement 2-39, 7-4 opérations groupées 20-21
événement 25-31 OnPassword, événement 16-16, ajout de données 20-24
OnDrawItem, événement 6-18 17-2 copie d’ensembles de
OnEditButtonClick, OnPopup, événement 2-48, 6-14 données 20-24
événement 25-31 OnRead, événement définition 20-22–20-23
OnEndDrag, événement 6-4, client, sockets 29-11 exécution 20-26
25-31, 33-5 OnReconcileError, gestion des erreurs 20-26
OnEnte, événement 25-31 événement 15-36 mise à jour de données 20-24
OnEnter, événement 25-35, OnRefresh, événement 26-8 mise en correspondance des
25-36, 33-5 OnResize, événement 7-4 types de données 20-25
OnError, événement OnScroll, événement 2-24 mode d’importation 20-21
sockets 29-9 OnSetText, événement 19-19, modes 20-23
OnExit, événement 25-31 19-20 suppression
OnFilterRecord, OnStartDrag, événement 25-31 d’enregistrements 20-25
événement 18-10, 18-19, 18-21 OnStartup, événement 16-5, optimisation des ressources
OnGetdataSetProperties, 16-6 système 30-4
événement 15-19 OnStateChange, optimisation du code 7-16
OnGetSocket, événement événement 18-5, 25-8 interfaces 4-23
serveur, sockets 29-10 OnSummaryChange, Options de déploiement Web,
OnGetText, événement 19-19, événement 26-10 boîte de dialogue 47-19
19-20 OnTerminate, événement 9-6 options de projet 3-3
OnGetThread, événement 29-10 OnThreadStart, événement par défaut 3-3
onglets serveur, sockets 29-10 Options du projet, boîte de
draw-item, événements 6-18 OnTitleClick, événement 25-31 dialogue 3-3
styles dessinés par le OnUpdateData, Options, propriété 2-37
propriétaire 6-15 événement 15-22, 25-8 fournisseurs 15-19
OnHTMLTag, événement 28-19, OnUpdateError, grilles de décision 26-14
28-20, 28-21 événement 15-24, 18-35, 24-11, grilles de données 25-27,
OnKeyDown, événement 25-31, 24-28 25-29
33-5, 41-10 OnUpdateRecord, Oracle, pilotes
OnKeyPress, événement 25-31, événement 18-35, 24-28, 24-30 déploiement 12-6
33-5 mises à jour en mémoire Oracle8
OnKeyUp, événement 25-31, cache 24-26 limites dans la création de
33-5 objets mise à jour 24-13, tables 20-20
OnLayoutChange, 24-22, 24-23, 24-26 Oracle8, tables 13-16
événement 26-10 OnValidate, événement 19-20 limites à la création de 14-12
OnListen, événement OnWrite, événement ORB 27-1, 27-16
serveur, sockets 29-10 client, sockets 29-11 ORDER BY, clause 20-11
OnLogin, événement 17-3, 17-7 Open, méthode Ordre de création,
OnLookup, événement bases de données 17-8 commande 2-59
client, sockets 29-9 ensembles de données 18-3 ordre de tabulation 2-21
OnMeasureItem, requêtes 21-14, 21-15 ordre de tri 11-9
événement 6-17 serveur, sockets 29-7 index 14-14, 23-7, 23-8
sessions 16-6 spécification 20-11
tables 20-4
Index I-31
événements souris 7-25, 7-26 Pie, méthode 7-3 ports 29-5
gestionnaires pilotes de base de données 13-2 client, sockets 29-6
d’événements 33-3, 33-8 pinceaux 7-8, 39-5 connexions multiples 29-5
HTML, balises 28-18 bitmap, propriété 7-9 domaines ORB 27-20
interfaces doubles 46-10 changement 39-7 serveur, sockets 29-7
messages 36-2, 36-6 couleurs 7-8 services et 29-2
paramètres de propriété 32-7 styles 7-9 Position, propriété 2-24, 2-25,
propriétés de tableau 32-9 pistes sonores 2-39 2-35
paramètres d’entrée 22-11 pivots de décision 26-11 Post, méthode 18-6, 18-8
paramètres de la ligne de comportement à Edit et 18-25
commande l’exécution 26-20 pourtours
Automation 45-8 propriétés 26-11 dessiner 7-5
paramètres de propriété de Pixel, propriété 7-2, 35-3 Precision, propriété 19-16
lecture 32-7 pixels Prepare, méthode 21-8, 21-15,
paramètres de sortie 22-11 lecture et définition 7-10 22-5
paramètres facultatifs 15-20, Pixels, propriété 7-5, 7-10 Presse-papiers 6-10, 6-11, 25-11
23-14 PlainText, propriété 2-23 effacement de la
Params, propriété 17-6, 17-7 plans bitmap 2-39 sélection 6-12
requêtes 21-11 pmCopy, constante 7-30 formats
Parent, propriété 30-14 pmNotXor, constante 7-30 ajout 37-13, 37-16
ParentColor, propriété 2-20 pointeurs graphiques et 7-23–7-24
ParentCtrl3D, propriété 2-20 Automation 46-8 objets graphiques 25-12
ParentFont, propriété 2-20 classe 31-10 sélection de texte 6-10, 6-11
ParentShowHint, propriété 2-36 méthode 33-3 test du contenu 6-13
partage des événements 2-46 valeurs de propriété par PRIMARY KEY,
partagées, propriétés 2-40, 2-41 défaut 32-11 contrainte 15-26
partie publiée des classes 31-7 pointeurs de méthode 33-2, 33-3 principales 27-17
Pascal Objet points de suspension (...) Prior, méthode 18-12
présentation 2-1 boutons dans les grilles 25-24 priorités
PasswordChar, propriété 2-22 dans la colonne des utilisation de threads 9-1, 9-3
PasteFromClipboard, valeurs 2-41 Priority, propriété 9-3
méthode 6-11, 25-11 points de terminaison 29-5 private, directive standard 2-11–
graphiques 25-12 Polygon, méthode 7-3, 7-12 2-12
PathInfo, propriété 28-10 polygones 7-12 PrivateDir, propriété 16-14
pbmByName, constante 22-17 dessin 7-12 privilèges 20-5
pbmByNumber, constante 22-17 polylignes 7-10, 7-11 ProblemCount, propriété 20-26
PChar 4-28 dessin 7-10 ProblemTableName,
conversions chaîne 4-33 PolyLine, méthode 7-3, 7-11 propriété 20-26, 20-27
PDOXUSRS.NET 16-14 pooling des objets 49-6 procédures 30-7, 33-3
Pen, propriété 7-2, 7-5, 35-3 pooling des ressources 49-5 modules de données et 2-61
PenPos, propriété 7-2, 7-8 PopupMenu, composant 5-13 nommer 34-2
PENWIN.DLL 10-13 PopupMenu, propriété 6-13 paramètres de
perforation, fiches 13-14 Port, propriété propriété 37-12
périphériques de média 8-3 client, sockets 29-6 procédures stockées 13-6, 13-15
perluète (&), caractère 2-21 serveur, sockets 29-7 ajout 22-4
Personal Web, serveur TSocketConnection 15-29 création 22-5
débogage 28-26 portée exécution 22-5
personnalisation des objets 2-9–2-13 mise à jour dans les
composants 30-3, 32-1 portées 20-12 applications
personnalisés application 20-16 multiniveaux 15-21
composants 2-67 filtres ou 20-12 paramètres 22-11
PickList, propriété 25-24, 25-25 limites 20-16 performances 22-2
picture, objets 7-5 modification 20-17 préparation 22-5
Picture, propriété 2-38, 7-18 spécification 20-14 surchargées 22-19
Index I-33
R RecordCount, propriété 20-26
Rectangle, méthode 7-3, 7-11,
Register, méthode 7-5
Register, procédure 30-12, 37-2
raccourcis 35-3 RegisterComponents,
accès aux valeurs de rectangles procédure 10-7, 30-12, 37-2
propriétés 2-41 dessin 7-11, 39-9 RegisterPropertyEditor,
ajout aux menus 5-17 rectangles à coins arrondis 7-12 procédure 37-12
raccourcis clavier 2-26 récupération d’enregistrements RegisterTypeLib, fonction
accès aux valeurs de en mémoire cache 24-10–24-11 bibliothèques de types 43-15
propriétés 2-41 redéclaration des registre 2-58
ajout aux menus 5-17 propriétés 32-11, 33-6 registre système 2-58
raise, mot réservé 4-14 redéfinition des méthodes 31-9 registres 11-9
rapports 13-16 redéfintion des méthodes 31-9 règles d’entreprise 15-2
.RC, fichiers 5-26 redimensionnement de regroupement de
Read, méthode contrôles composants 2-32–2-34
TFileStream 4-43 graphiques 35-7 REGSERV32.EXE 12-3, 12-7
read, méthode 32-7 redimensionnement des régularisation des
read, mot réservé 32-9, 39-4 contrôlels 40-4 données 23-20
ReadBuffer, méthode redimensionnement des relations maître/détail
TFileStream 4-43 contrôles 12-9 ensembles de données
README.TXT 12-12, 12-13 références client 23-3
ReadOnly, propriété 2-22, 41-3, bibliothèques de types 48-7 intégrité référentielle 13-6
41-10 fiches 5-2 multiniveaux,
contrôles d’édition de texte objets COM 45-7 applications 23-4
formaté 25-11 paquets 10-4 tables imbriquées 23-3
contrôles orientés références circulaires 5-2 Release, méthode 4-18, 4-22,
données 19-16, 25-4 références croisées 26-2–26-3, 4-23
grilles de données 25-25, 26-12 IUnknown 43-4
25-29 à plusieurs dimensions 26-3 TCriticalSection 9-7
mémo, champs 25-10 à une dimension 26-3 Remote DataBroker 12-6
tables 20-5 définition 26-2 RemoteServer, propriété 15-27
réalisation de palettes 35-5, 35-6 valeurs récapitulatives 26-3 RemovePassword,
ReasonString, propriété 28-16 références croisées à plusieurs méthode 16-16
recensement dimensions 26-3 RenameFile, fonction 4-39, 4-40
composants 30-12 référentiel renommer
contrôles ActiveX 3-11, 47-18 d’implémentation 27-4 composants 2-5–2-6
éditeurs de référentiel d’interfaces 27-4 répertoires
composants 37-16 ajout d’interfaces 27-9 fichiers temporaires 16-15
éditeurs de propriétés 37-12– exécution 27-9 répertoires privés 16-15
37-13 recensement des interfaces Repetitions, propriété 2-39
interfaces CORBA 27-8 CORBA 27-8, 27-9–27-10 réponse aux événements 41-7
objets COM 3-11 suppression d’entrées 27-10 RepositoryID, propriété 15-30
recherche référentiel d’objets 2-63–2-67 Request for Comment (RFC),
d’enregistrements 18-9 accès aux éléments 2-65 documents 28-1
réitération de recherches 20-9 ajout d’éléments 2-64 RequestLive, propriété 21-18,
recherche de données 18-9 conversion d’applications 24-25
clés partielles et 20-8 serveur Web 28-27 requête, composants 13-15, 21-1
recherches liens vers le module de ajout 21-4
incrémentales 25-16 données 2-59 requête, objets
réitération de recherches 20-9 spécification du répertoire informations d’en-tête 28-8
recherche de texte 2-23 partagé 2-64 requête, partie (URL) 28-2
recherche incrémentales 25-16 Refresh 5-41 requêtes 13-15, 18-3, 21-1
recherches indexées 18-9, 18-17, Refresh, méthode 25-5 caractères d’espacement
18-18, 20-6 RefreshLookupList, et 21-6
RecNo, propriété propriété 19-13 caractères spéciaux et 21-6
ensembles de données RefreshRecord, méthode 15-38
client 23-2
Index I-35
sécurité 17-7 messages d’erreur 29-8 Service, propriété
applications socket Windows, objets 29-7, client, sockets 29-6
multiniveaux 15-2 29-8 serveur, sockets 29-7
bases de données 13-3 spécification 29-6 services 3-4–3-8
dBase, tables 14-4 utilisation de threads 29-12 annuaire 27-2, 27-3
MTS 15-6, 15-9, 49-12 serveurs ActiveX code exemple 3-4, 3-6
Paradox, tables 14-4 bibliothèques de types 43-12 CORBA 27-1
segments de ligne optimisation 43-15 demande de 29-6
connectés 7-10, 7-11 vérification de type 43-14 implémentation 29-1–29-2,
SELECT, instructions 21-14, serveurs Automation 43-9, 29-7
21-18 43-10, 43-18 ports et 29-2
SelectAll, méthode 2-23 accès aux objets 46-8 propriétés de nom 3-8
SelectCel,l méthode 41-4 création 46-1 réseau, serveurs 29-1
SelectCell, méthode 40-13 exécution 45-7 Session, composant 16-1, 16-2
Sélection de menu, boîte de test 46-6 Session, propriété 17-4
dialogue 5-22 serveurs COM 43-2, 43-5, 43-18 SessionName, propriété 16-4,
Selection, propriété 2-37 distants 43-6 17-4, 18-33, 28-22
Sélectionner un menu, en processus 43-6 sessions 14-4, 16-1, 16-2, 17-10
commande (menu hors processus 43-6 activation 16-5, 16-6
Concepteur) 5-21, 5-22 serveurs COM et CORBA création 16-3–16-4, 16-18,
SelEnd, propriété 2-24 combinés 27-5 16-19
Self, paramètre 30-13 serveurs d’applications 15-1, décompte 16-18
SelLength, propriété 2-23, 6-11 15-11 dénomination 16-4, 28-22
SelStart, propriété 2-23, 2-24, extension des désactivation des
6-11 interfaces 15-39 connexions 16-6
SelText, propriété 2-23, 6-11 fournisseurs de état en cours 16-5
Sender, paramètre 2-46 données 15-17–15-26 gestion des alias 14-4
exemple 7-7 identification 15-28 modes de
séparateurs 2-26 modules de données configuration 16-11
séparateurs de classeur 2-33 distants 2-62 multiples 16-2, 16-3, 16-18
séquences vidéo 8-1 multiniveaux 18-34 noms d’alias et 16-11
server, applications threads 9-13 obtention
extraction de données 21-3 serveurs de base de d’informations 16-10
ServerType, propriété 29-10, données 21-3 par défaut 16-2
29-11, 29-12 serveurs de bases de redémarrage 16-6
serveur, applications données 17-7 test des associations 16-13
architecture 15-5 serveurs de bases de données Web, applications 28-21,
contraintes de données 15-25 distants Voir serveurs distants 28-22
extraction de données 21-16, serveurs de messagerie Sessions, propriété 16-19
21-19 threads 9-13 SetAbort 49-5, 49-6, 49-10
interfaces 29-2 Voir aussi applications SetBrushStyle, méthode 7-9
multiniveaux 15-1, 15-5, serveur Web SetComplete 49-5, 49-6, 49-9
15-11 serveurs distants 13-3, 16-7, SetComplete, méthode
fournisseurs de 21-4, 43-6 modules de données
données 15-26 accès aux données 24-1 MTS 15-43
recensement 15-11, 15-12 accès non autorisé 17-7 SetData, méthode 19-21
services 29-1 attachement 17-8–17-9 SetEvent, méthode 9-10
transactions 14-9 documents Active et 43-16 SetFields, méthode 18-28
serveur, connexions 29-2, 29-3 noms 15-28 SetFloatValue, méthode 37-9
numéros de port 29-5 serveurs en processus 43-6 SetKey, méthode 18-9, 20-7
serveur, sockets 29-7–29-8 ActiveX 43-12 EditKey ou 20-9
acceptation de clients 29-10 serveurs hors processus 43-6 SetLength, procédure 4-32
acceptation de requêtes service SetMethodValue, méthode 37-9
client 29-7 threads 3-6 SetOrdValue, méthode 37-9
gestion d’événements 29-10 service d’annuaire 27-3 SetParams, méthode 24-22
Index I-37
STDVCL40.DLL 12-6 synchronisation des spécification du type 20-3
StepBy, propriété 2-35 données 20-27 suppression 20-18
StepIt, méthode 2-35 sur plusieurs fiches 25-7, 25-8 suppression
stockage Synchronize, méthode 9-4 d’enregistrements 20-18
propriétés 32-11 interaction avec WaitFor 9-9 précaution 20-18
StopFrame, propriété 2-39 système d’aide 37-4 synchronisation 20-27
stored, directive 32-12 boutons outils 5-34 tri de données 20-10–20-12
StoreDefs, propriété 20-20 fichiers 37-4 avec des index
StoredProcName, propriété 22-4 mots clés 37-5 secondaires 20-10
StrByteType 4-30 Système, page (palette des vidage 20-18
Stretch, propriété 2-38, 25-12 composants) 2-19 tables en lecture seule 20-5
StretchDraw, méthode 7-3, 35-3, systèmes de gestion de bases de tables imbriquées 13-16, 19-31,
35-7 données 15-1 20-29
string, mot réservé 4-27 systèmes de gestion de bases de client, ensembles de
type par défaut 4-26 données relationnelles 13-3 données 15-42
VCL, types de propriété 4-27 fichiers linéaires 23-4
Structured Query T maître/détail, relations 15-42
Language 13-3 tables non indexées 18-26, 18-28
stThreadBlocking, TabHeight, propriété 2-33 parcours 20-6
constante 29-10 Table , balise HTML tables Oracle 22-19
stubs 27-2, 27-2–27-3, 27-8, (<TABLE>) 28-18 tables problématiques 20-26
27-12, 27-13–27-14 table, composants 13-15, 20-2 TableType, propriété 20-3
création 27-13 TableAttributes, propriété 28-23 TabOrder, propriété 2-21
marshaling 27-2 tableau, champs 19-29–19-30 TabStop, propriété 2-21
Style, propriété 2-30, 2-31, 2-38 tableaux 32-3, 32-9 TabWidth, propriété 2-33
boîtes à options 25-13 sécurisés 48-24 TAction 5-35
boutons outils 5-32 tableaux de variants 45-9 TActionLink 5-35
crayons 7-6 à une dimension 45-11 TActionList 5-35
pinceaux 7-9 redimensionnement 45-10 TActiveXControl 47-2
variants dessinés par le verrouillage 45-13 TADTField 19-1
propriétaire 6-15 tableaux sécurisés 45-9 Tag, propriété 19-16
substitution des paramètres TableName, propriété 20-3 TAny 27-14
(SQL) 24-17, 24-22 tables 13-15, 20-1 création de types
Subtotals, propriété 26-14 affichage dans les structurés 27-15
Supplément, page (palette des grilles 25-19 TArrayField 19-1
composants) 2-19 ajout 20-2–20-4 TAutoIncField 19-1
Suppression de modèles, boîte changement de nom 20-18 TBatchMove
de dialogue 5-23 composants d’aide à la gestion des erreurs 20-26
suppression des dépendances décision et 26-3 TBCDField 19-1
de composant 30-5–30-6 création 14-12, 14-13, 20-19 TBDEDataSet 18-31, 18-34
suppressions en cascade 15-19 définitions des champs et des TBitmap 35-4
Supprimer les modèles, index 20-20 TBlobField 19-2
commande (menu dénomination 20-3 TBooleanField 19-1
Concepteur) 5-21, 5-23 droits d’accès 20-5 tbsCheck, constante 5-32
Supprimer, commande (menu en lecture seule 20-5 TBytesField 19-2
Concepteurr) 5-21 extraction de données 20-12, TCalendar 40-1
surcharge 20-21, 21-1 TCGIApplication 28-5
méthodes 2-11, 31-9, 36-3, insertion TCGIRequest 28-5
40-11 d’enregistrements 18-25– TCGIResponse 28-5
Suspend, méthode 9-12 18-26, 18-28 TCharProperty, type 37-8
Sybase, pilote maître/détail, relations 20-29 TClassProperty, type 37-8
déploiement 12-6 mise à jour des données avec TClientDataSet 23-1
synchronisateur à écriture des 24-24 applications linéaires 14-12
exclusive et à lecture ouverture 20-4 TClientSocket 29-6
multiple 9-8 parcours des 20-5–20-9 TClientWinSocket 29-6
précaution d’utilisation 9-8 restructuration 14-12 TColorProperty, type 37-8
Index I-39
attente d’événements 9-10 TIcon 35-4 tpTimeCritical, constante 9-3
attente de 9-9 tiDirtyRead, constante 14-8 TQuery 21-1
bibliothèques 9-15 TImageList 5-31 ajout 21-4
blocage de l’exécution 9-7 timers 2-39 ensembles de données de
boucle des messages et 9-5, Timers, propriété 2-39 décision et 26-6
9-14 TIntegerField 19-2 TQueryTableProducer 28-25
client, sockets 29-12, 29-13– TIntegerProperty, type 37-8, traduction 11-8
29-14 37-10 traduction de chaînes de
COM 9-14 TInterfacedObject 4-22 caractères 11-2, 11-8, 11-10
coordination 9-4, 9-7–9-11 dérivation de 4-19 conversions sur 2 octets 11-3
CORBA 9-14 implémentation de traitement distribué des
création 9-11 IUnknown 4-18 données 15-2
engorgement 9-9 liaison dynamique 4-19 transaction
espace de processus 9-4 tiReadCommitted, attributs
éviter les accès constante 14-8 objets MTS 49-17, 49-19
simultanés 9-7 tiRepeatableRead, transactions 13-4, 14-5–14-11
exécution 9-11 constante 14-8 abandon 14-8
graphiques, objets 9-5 TISAPIApplication 28-5 applications
identificateurs 9-16 TISAPIRequest 28-5 multiniveaux 15-41
initialisation 9-3 TISAPIResponse 28-5 changements non validés
ISAPI/NSAPI, Title, propriété et 14-8
programmes 28-7, 28-22 grilles de données 25-25 contrôles 14-6–14-10
libération 9-3 TKeyPressEvent, type 33-4 démarrage 14-7
limites du nombre de 9-11 TLabel 30-4 durée 14-7
mise en mémoire cache 9-12, .TLB, fichiers 43-14, 48-35 implicites 14-6
29-15 TLIBIMP 43-15 locales 14-10
objets distribués 9-14 TListBox 30-3 mises à jour en mémoire
priorités 9-1, 9-3 TMemoField 19-2 cache et 24-2, 24-5
redéfinition 9-11 TMessage 36-4, 36-6 modules de données
renvoi de valeurs 9-9 TMetafile 35-4 MTS 15-15
sections critiques 9-7 TMethodProperty, type 37-8 MTS 15-7, 15-41, 49-5, 49-7
serveur, sockets 29-12, 29-14– TMsg 5-4 attributs 49-8
29-15 TMTSDataModule 15-6 contrôlées par le
serveurs de messagerie 9-13 TMultiReadExclusiveWriteSync client 49-10
serveurs en processus 9-15 hronizer 9-8 temporisations 49-11
sessions de base de données TNotifyEvent 33-8 niveaux d’isolement 14-8–
et 14-5, 16-3 TNumericField 19-2 14-9
utilisation avec des sockets TObject 31-4 support côté client 49-21
client 29-14 TObject, type 2-9 support côté serveur 49-21
utilisation avec des sockets Top, propriété 2-20, 5-3, 5-29 utilisation des bases de
serveur 29-15 TopRow, propriété 2-37 données 14-7
utilisation de listes 9-5 TOrdinalProperty, type 37-8 validation 14-7, 14-8
VCL, thread 9-4 touches d’accès rapide 2-26 transactions implicites 14-6
verrouillage des objets 9-7 TPageProducer 28-18 transactions locales 14-10
threads de service 3-6 TPanel 5-27 transfert d’enregistrements 42-2
threads en cours tpHigher, constante 9-3 TransIsolation, propriété 14-8
changement des 9-16 tpHighest, constante 9-3 Transliterate, propriété 19-16,
threads en suspens 9-12 TPicture, type 35-4 20-23
threads multiples tpIdle, constante 9-3 Transparent, propriété 2-35
attente de 9-10 tpLower, constante 9-3 transtypage 6-18
threadvar 9-5 tpLowest, constante 9-3 TReader 4-41
THTMLTableAttributes 28-23 tpNormal, constante 9-3 TReferenceField 19-2
THTMLTableColumn 28-24 TPopupMenu 5-34 TRegSvr 12-3, 43-15
TickMarks, propriété 2-24 TPropertyAttributes 37-11 TRemoteDataModule 15-5
TickStyle, propriété 2-25 TPropertyEditor, classe 37-7
Index I-41
UpdatesPending, valeurs récapitulatives 26-21 vérification du type 5-17
propriété 18-34, 24-4 agrégats maintenus 23-13 verrouillage des objets
UpdateSQL, éditeur 24-16 graphes de décision 26-17 imbrication des appels 9-7
UpdateStatus, propriété 18-35, références croisées 26-3 threads 9-7
24-12 validation verrous 20-5
UpdateTarget, méthode 5-40 d’enregistrements 25-5 verrous exclusifs 20-5
URI grilles de données 25-29 verticales, barres graduées 2-25
URL ou 28-2 validation des saisies de vidéo analogique 8-5
URL 28-2 données 19-20 vidéo, séquences 8-3
IP, adresses 29-4 validation des transactions 14-7, violations d’accès
noms d’hôte 29-4 14-8 chaînes 4-32
URI ou 28-2 Value, propriété 19-21 violations de clé 20-26
Web, navigateurs 28-3 ValueChecked, propriété 25-17 virtual
URL, propriété 28-13 Values, propriété 25-18 directive 31-9
USEPACKAGE, macro 10-8 ValueUnchecked, tables de méthode 31-9
uses, clause propriété 25-17 virtuelles
ajout de modules de var, mot réservé méthodes 31-9, 34-4
données 2-62 gestionnaires propriétés comme 32-2
éviter les références d’événements 33-4 éditeurs de
circulaires 5-2 VarArrayCreate, fonction 45-10 propriété 37-10
inclusion de paquets 10-4 VarArrayDimCount, éditeurs de
usInserted, constante 24-12 fonction 45-11 propriétés 37-9
usModified, constante 24-12 VarArrayHighBound, Visible, propriété 19-16
usUnmodified, constante 24-12 fonction 45-11 barres d’outils 5-34, 5-35
utilisateur, interfaces 13-12– VarArrayLock, fonction 45-12 barres multiples 5-34
13-16 VarArrayLowBound, menus 5-25
enregistrement unique 13-13 fonction 45-11 VisibleButtons, propriété 25-34,
enregistrements VarArrayOf, fonction 45-10, 25-35
multiples 13-13 45-11 VisibleColCount, propriété 2-37
isolement 13-8 VarArrayRedim, fonction 45-10 VisibleRowCount,
Utiliser unité, commande VarArrayUnlock, fonction 45-12 propriété 2-37
(Fichier) 2-62, 5-2 varEmpty, constante 45-7 VisiBroker ORB 15-13
variables 21-7 VisualSpeller Control 12-3
V déclaration Voir comme texte,
exemple 2-4, 2-14 commande 2-59
$V, directive de objets et 2-14–2-16 volets 2-33
compilation 4-35 variables d’environnement ajout de turboboutons 5-28
valeurs 32-2 CORBA 27-18 aligné sur le haut de la
booléennes 32-2 variables locales aux threads 9-5 fiche 5-28
default, propriété 32-11 OnTerminate, événement 9-6 multiples 5-27
données par défaut 19-25, variants 18-17, 18-18, 19-23 turboboutons 2-27
25-12 CORBA 27-14 volets biseautés 2-33
null 18-28, 20-14 et objets COM 45-6, 45-9 vtable 43-4
propriété par défaut 32-8 non assignés 45-7 vtables
redéfinition 38-2, 38-3 null 45-7 pointeur d’interface
test 32-7 tableaux 45-9 COM 43-4
valeurs booléennes 32-2, 32-11, TAny 27-14 vues arborescentes 2-31
41-4 VarType, fonction 45-6
valeurs de référence 25-21 VCL 30-1–30-2 W
valeurs des axes 26-17 présentation 2-1
valeurs littérales 19-25 propriétés de type WaitFor, méthode 9-9, 9-10
valeurs logiques 25-2, 25-16 chaîne 4-27 interaction avec
valeurs null thread principal 9-4 Synchronize 9-9
portées et 20-14 VCL30, paquet 10-1, 10-10 WaitForData, méthode 29-13
valeurs par défaut PENWIN.DLL 10-13 WantReturns, propriété 2-23
options de projet 3-3
Index I-43
I-44 Guide du développeur