|
Delphi 8 Windows Forms - John COLIBRI.
|
- abstract:présentations de Windows Forms et portage d'unités d'affichage
et log.
- mots clé:tutorial - Delphi 8- Vcl.Net - Windows Forms - affichage et
journal disque
- logiciel utilisé: Windows XP, Delphi 8
- matériel utilisé: Pentium 1.400Mhz, 256 M de mémoire
- champ d'application: Delphi 8 sur Windows .Net Framework
- niveau: débutant Delphi
- plan:
1 - Introduction
J'ai choisi de présenter à Borcon 2004 les différents moyens d'utiliser
Interbase:
- pour Delphi 5 à 6, les API, le BDE et Sql Links, Interbase Express,
dbExpress et Ado
- pour Delphi 8, dbExpress.Net, Ibx.Net, Ado.Net et le BDP
J'ai donc commencé à utiliser Delphi 8. Avec cette nouvelle version qui
travaille fondamentalement en utilisant C# en non plus Win32, nous avons
fondamentalement deux modes:
- le mode Windows Forms qui utilise les gadgets C#
- le mode VCL.NET qui est une librairie créée par Borland pour nous
permettre de travailler pratiquement comme en Delphi 6 avec Win32
Les articles d'utilisation de la Vcl.Net (présentation, Interbase Express,
dbExpress) ont rendu compte de l'emploi de cette librairie.
Nous allons ici présenter quelques commentaires sur Windows Forms et les
modifications que nous avons dû apporter à nos unités d'affichage et de log
pour qu'elles fonctionnent dans ce mode-ci.
2 - Livres sur Delphi 8
Avant de me jeter à l'eau, j'ai fait un petit tour en librairie. Deux livres:
- Le meilleur livre, et de loin, est le livre de PACHECO:
Xavier PACHECO (et autres auteurs)
Delphi for .NET - Developper's Guide
Sams - ISBN 0 672 32443 - 1 - 2004
- Dans la droite lignée de toute la série des "Developper's Guide"
que nous connaissons depuis Delphi 1. Des développeurs qui sont
plus "concept et code" que "clic et coloriage".
Sans faire la présentation détaillée du livre, mentionnons que
- le point de vue est résolument Windows Forms (plutôt que
VCL.NET)
- le livre se veut exhaustif: il part de VAR, FOR etc.
Heureusement que cette partie représente moins de 5% du livre.
Le reste aborde l'utilisation de Windows Forms pour dessiner,
les entrées sorties, une belle partie sur les bases de données,
puis Asp.Net
- j'ai aussi feuilleté un livre en Français sur Delphi 8: un ramassis de
tables de propriétés et de méthodes copiées de l'aide en ligne, un mélange
superficiel de Vcl.Net et Windows.Forms, moins de 3 pages d'index.
Le chapitre sur ECO est pratiquement la copie francisée d'un "White
Paper" Borland d'Anthony RICHARDSON (Google:
WhitePaperECOFirstApplication.pdf), sans même citer l'auteur. Très très
élégant. Ceci nous donne aussi une idée précise du "professionnalisme"
dont l'auteur se vante tant et tant.
Je suis aussi tombé sur quelques phrases ampoulées, tout à fait cruciales
pour la bonne compréhension de Delphi 8, et qui m'ont fait bien rire:
"c'est Ado.Net tel un Neptune qui règne en maître sur tous les flots de
données".
C'est certain. Et le char de l'état navigue sur un volcan. Abraham LINCOLN
dut un jour dédicacer un livre qu'il jugeait très médiocre. Il écrivit
alors:
"Pour ceux qui aiment ce genre de livre, c'est exactement celui qu'il
leur faut"
3 - Portage d'unités Delphi 6
3.1 - Introduction
Je ne parlerai plus ici de l'organisation générale de l'interface utilisateur
que est décrite dans l'article sur Delphi 8 Vcl.Net.
3.2 - Portage
Je me suis tout de suite attaché à porter ma mécanique d'affichage / log.
Les grosses surprises:
- l'affichage se fait dans des EditBox. Il s'agit d'une encapsulation de
l'Edit Windows, ayant une propriété Text, de type String
- il n'existe plus de tMemo: nous devons utiliser un EditBox en mode
multi-ligne. Nous voici bien de retour 15 ans en arrière:
- Win32 ne distingue pas les tEdit et les tMemo: chaque fenêtre a un
pChar attaché qui sert à stocker qui le titre du tButton, qui le texte
d'un tMenuItem, qui le texte d'une tListBox, qui le texte d'un tEdit
en mode mono ou multi-ligne
- c'est Delphi qui avait la gentillesse d'encapsuler en deux composants
différents l'Edit Windows, avec le tEdit et le tMemo. Le passage du
pChar au texte multi-ligne se faisait dans des procédures Inline. Il
faut dire que dans nos application, saisir un nombre dans un tEdit n'a
rien à voir à taper Autant en Emporte le Vent dans un tMemo
- pour Windows Forms cette encapsulation n'a pas été réalisée
La conséquence est que notre affichage doit être modifié:
- une première solution est de concaténer les chaînes à afficher dans
EditBox.Text. C'est ce que nous avons fait compte tenu de l'urgence du
portage
- une seconde solution serait de lire et comprendre le livre de Pacheco
pour maîtriser toutes les Interfaces et toute les collections, qui
semblent être au coeur de .NET. Nous réservons cette exploration pour
plus tard.
- les composants n'ont plus de propriété Align. La présentation de la tForm
comporte bien un aligneur intégré en haut (l'équivalent de la palette
d'alignement), mais je n'ai pas pu aligner de tMemo. Google semble
confirmer cette absence.
- les type composants sont désignés par le chemin complet de leur librairie.
Il s'agit je suppose de leur "NameSpaces". Le problème s'est posé car mon
c_display ne pouvait plus utiliser un tStrings pour stocker les chaînes,
mais une référence vers le EditBox complet. Il fallait donc:
- importer l'unité qui sait ce que c'est qu'un EditBox
- désigner ce composant comme membre de c_display et comme paramètre des
méthodes
Et voici la réponse:
- EditBox est situé dans l'unité System.Windows.Forms. Nous le savons
car si nous sélectionnons EditBox1 sur la Forme et tapons F1 nous
voyons:
- le type est désigné par System.Windows.Forms.EditBox
procedure do_display(p_c_textbox_ref: System.Windows.Forms.TextBox;
p_text: String);
begin
p_c_textbox_ref.Text:= p_c_textbox_ref.Text+ p_text;
end; // do_display
|
- le compilateur a aussi refusé, aléatoirement (à la première compilation
après le boot), le passage suivant:
function f_no_accents(const pk_string: String): String;
var l_index: Integer;
begin
Result:= pk_string;
For l_index:= 1 to Length(Result) do
Case Char(Result[l_index]) of
'à' : Result[l_index]:= 'a';
end; // case
end; // f_no_accents
|
avec un message similaire à "Incompatible type String and Char". Je me doute
bien qu'il s'agit d'une histoire de caractères ASCII / UNICODE, mais ce qui
me surprend c'est que la compilation soit refusée une fois, et que le code
soit accepté sans broncher ensuite.
3.3 - Les unités à porter
Nous souhaitions pouvoir:
- afficher dans un TextBox en appelant depuis n'importe quelle unité:
display('un texte');
- sauvegarder la suite de ces messages dans un fichier .TXT
Ces deux fonctionalités sont réalisées sous Delphi 6 par les unités
- u_strings qui contient diverses routines de manipulation
de chaînes
- u_c_basic_object qui permet de doter chaque objet
d'un nom individuel
- u_c_display qui affiche les messages dans un tMemo
- u_c_log qui stocke les messages dans un fichier .TXT
Ce sont ces routines que nous avons portées en Windows Forms. Nous savions
déjà que FILE (utilisé pour le log), les pChar, Move ou autres Fillchar
seraient refusés. Le portage sous Vcl.Net l'avait confirmé.
Nous sommes donc parti des librairies déjà portées sous Vcl.Net et avons
modifié la partie contrôle visuels. Pour éviter les conflits d'unités (en
source) j'ai choisi de préfixer toutes mes librairies Delphi 8 avec
"_win_". Voici le résultat de ce portage.
3.4 - Les unités
Voyons à présent chaque unité individuellement:
- u_c_win_basic_object, u_win_strings: rien de spécial
- u_c_win_log: tout a fonctionné avec des tFileStream et des boucles
d'écriture caractère à caractère. Mais ce n'est certainement pas la
meilleure façon de stocker des textes sur disque
- u_c_win_display:
- la seule difficulté a été la syntaxe pour utiliser une référence vers le
contrôle EditBox, et pour passer un pointeur vers ce contrôle en
paramètre (voir plus haut)
Vous trouverez le texte de ces unités dans les .ZIP téléchargeables.
3.5 - L'application de test
Décrivons succintement l'application de test qui affiche:
|
chargez Delphi 8
|
|
créez une nouvelle application par "Fichiers | Nouveau | Windows Forms"
et appelez-la "p_win_display"
|
|
sélectionnez dans la page "Windows Forms" le composant TextBox qui nous
servira à l'affichage:
et posez ce composant sur la tForm.
Sélectionnez sa propriété MultiLine et donnez-lui la valeur True
|
|
sélectionnez un second TextBox qui contiendra le texte à ajouter et
posez-le sur la Forme
|
|
sélectionnez un Button et posez-le sur la Forme. Créez son événement
OnClick et faites-lui ajouter au texte de TextBox1 le contenu de
TextBox2:
procedure TWinForm.display_Click(sender: System.Object; e: System.EventArgs);
begin
display(TextBox1.Text);
end; // display_Click
|
|
|
ajoutez aux USES les importations de u_c_win_display et u_c_win_log
|
|
dans l'événement Form.OnCreate (qui existe déjà), ajoutez
l'initialisation de l'affichage et du log:
constructor TWinForm.Create;
begin
inherited Create;
//
// Required for Windows Form Designer support
//
InitializeComponent;
//
// TODO: Add any constructor code after InitializeComponent call
//
initialize_display(TextBox2);
initialize_default_log;
end; // Create
|
Notez que seule les deux dernières instructions ont été ajoutées par nos
soins.
|
|
l'ensemble ressemble à la figure suivante:
|
|
compilez et exécutez
|
|
le texte de TextBox2 est ajouté au texte de TextBox1 et le log contient
ce texte

|
4 - Evaluation
Voici quelques commentaires que me suggèrent cette première incursion dans le
monde .NET:
- Windows Forms est bien plus éloigné de Delphi 6 que ne l'est Vcl.Net.
- parmi les airs de famille de l'antique Visual Studio (version 4) que j'ai
jadis un peu pratiqué (eh oui...):
- l'apparence des contrôles sur la Forme a cet allure "ressource toolkit"
des années 90: un entourage en gros avec des plots externes
- Cela est aussi utilisé pour poser des contrôles non-visuels: ils sont
placés sous la Forme. C'est bien d'isoler ces contrôles, un peu moins
bien de ne pas les placer dans un tDataModule séparé
- j'ai été aussi un peu ennuyé par le changement des conventions:
- les types ne commencent plus nécessairement par t. Par exemple, le type
d'un TextBox est TextBox (et non pas tTextBox)
- la mécanique des nom (System.Windows.Forms.TextBox), issue de Java
est aussi un peu pénible. Comme l'expliquaient des habitués d'Oberon,
Java n'a pas la notion de "Module" (nos UNITés). Un fichier correspond
à une CLASSe. Il fallait donc trouver des techniques pour regrouper des
CLASSes, d'où tout un tas de contorsions à base d'Assemblies,
NameSpaces et autre simagrées.
- l'aide est l'aide de C#, et si déjà ils (Microsoft j'imagine) ont le culot
de nous présenter, outre la syntaxe C#, la syntaxe C++ et javascript, ils
auraient pu ajoute la syntaxe Delphi. Toutefois le TreeView affiché à
gauche du texte de l'aide est très agréable
- à un niveau bien plus fondamental, en consultant le livre de Pacheto, il
est évident que l'ensemble est pyramidé sur des Interfaces. Lorsque
Borland a ajouté COM à Delphi, de nombreuses conversations mentionnaient
que la VCL n'aurait pas eu la structure qu'elle avait si les Interfaces
avaient existé. Eh bien, nous y voilà:
- Java a les Interfaces
- C# qui n'est toujours que du java à la Microsoft les a donc aussi
- lorsqu'ils ont créé la librairie, ils (Heljsberg j'imagine) on eu les
coudées franches pour utiliser cette technique mirifique
Non pas que je ne comprenne pas l'intérêt des Interfaces: le mécanisme
qu'elles offrent au niveau conceptuel est un des piliers des Design
Patterns. Mais je ne suis pas encore convaincu que leur utilisation massive
apportera des gains énormes: il semble qu'il y ait un double apprentissage:
ce que font les Interfaces, puis pour chaque CLASSe, quelles
Interfaces elle implémente. J'avais vu des sources Delphi 6, du côté de
WebSnap, ou l'UNITé comportait des dizaines d'Interfaces en plus de
dizaines de CLASSes. Apprendre les deux avait de quoi faire reculer les
plus courageux.
Mais mon opinion à ce niveau est de peu d'importance. Ceux qui voudront
utiliser .NET devront apprendre les Interfaces utilisées à tous les
niveaux: collections, graphique, fichiers, Ado, Asp. Lorsque j'aurai
effectué ceci, il est vraissemblable que même mes unités d'affichage et log
seront modifiées.
Et c'est à ce niveau que le livre de Pacheto me semble très sain. Pour le
Borland Data Provider, par exemple, ils commencent par présenter
l'organisation des Interfaces, plutôt que de se précipiter sur les
CLASSes. Notons que c'est l'approche des White Papers de Borland sur le
BDP, mais ceci ne fait que souligner la nécessité de passer par les
Interfaces.
En résumé:
- Borland a, comme pour le mode Vcl.Net, réalisé une interface utilisateur
qui nous permet de travailler pratiquement comme en Delphi 6.
5 - Télécharger les Exemples
Le source associé à ce programme est le suivant:
Ce .ZIP comprend:
- le .DPR, la forme principale, les formes annexes eventuelles
- les fichiers de paramètres (le schéma et le batch de création)
- dans chaque .ZIP, toutes les librairies nécessaires à chaque projet (chaque
.ZIP est autonaume)
Ces .ZIP contiennent des chemins RELATIFS. Par conséquent:
- créez un répertoire n'importe où sur votre machine
- placez le .ZIP dans ce répertoire
- dézippez et les sous-répertoires nécessaires seront créés
- compilez et exécutez
Ces .ZIP ne modifient pas votre PC (pas de changement de la Base de Registre,
de DLL ou autre). Pour supprimer le projet, effacez le répertoire.
6 - Conclusion
Nous avons présenté une première application d'affichage et log utilisant
Delphi 8 en mode Windows Forms.
7 - L'auteur
John COLIBRI est surtout intéressé par la programmation en Pascal, Delphi et
Kylix. Son site contient des articles, la descriptions de ses
livres, le programme des stages qu'il anime tous les mois.
|