u_c_display - John COLIBRI. |
- mots clé:display - mise au point - affichage de texte - Write
- logiciel utilisé: Windows 98, Delphi 5.0
- matériel utilisé: Pentium 500Mhz, 128 M de mémoire
- champ d'application: Delphi 1 à 6 sur Windows, Kylix
- niveau: débutant en Pascal et Delphi
- uses: u_c_basic_object, u_c_log, u_loaded, u_strings,
(u_types_constants, u_c_basic_file, u_c_file_name,
u_dir)
- plan:
1 - Introduction
Depuis le Pascal de l'Apple ][, je passe mon temps à afficher du texte pour mettre au point mes programmes. Lors de l'arrivé du Pascal UCSD 1.3 (vers 1981 de mémoire) j'avais même
commencé à mettre au point un débugger symbolique qui synchronise l'adresse dans le code exécutable et la ligne dans un fichier source. Puis est venu Turbo, et bien longtemps après son fabuleux débugger.
Fini les Writeln qu'il faillait péniblement insérer ici ou là et dont la triste vocation était d'être un jour virés comme des malpropres. Eh bien Que Nenni. Vingt ans plus tard, je continue à afficher du texte plutôt
que d'utiliser le débugger. Comme les discussions sur C++ vs Pascal, ou d'autres batailles entre Gnome vs Qt, ce genre de bataille frise la guerre de religion. Je donnerai simplement
ici mes raisons, sachant que ceux qui ont remplacé les Writeln par le débugger seront convaincus d'avoir raison. Pour ceux qui n'auront pas ici quitté la présentation, mes arguments sont les suivants:
- les Writeln peuvent être insérés en tenant compte de toute la puissance de Pascal. Un IF bien concocté est bien plus spécifique que toutes les conditions ajoutées au débugger
- l'affichage me permet de garder une trace de l'historique. Le débugger m'oblige à mémoriser par où je suis passé
- l'affichage peut être formatté à volonté
- l'affichage est souvent couplé à un Log sur disque qui est facilement
consultable (chaque ligne est purgée sur disque) en cas de problème grave
- ces logs peuvent d'ailleurs être multiples et hiérarchiques (liste des fichiers traités, valeurs lors de l'un des traitements etc)
1.2 - Historique
Historiquement, dans le livre 'Delphi Applis Windows Rapides', j'avais commencé à utiliser des tListbox (car elles étaient présentées avant les tMemo). Depuis, j'utilise des tMemo, qui peuvent en outre être édités avant d'être
envoyés sur disque. L'utilisation de tMemo explique l'affichage ligne à ligne utilisé dans la première version de u_display. De plus l'affichage de la ligne provoquait
l'écriture dans le log disque, ce qui explique que je ne souhaitais pas tamponner les textes partiels (Write). Pris par le temps, l'ensemble de ces procédures a été placé dans une unité
u_display, qui a naturellement grossi à travers les ages (ajout de display_bug_stop, display_bug_halt, stop_display, restart_display etc.)
Comme je souhaite publier des articles sur mes programmes récents, la plupart utilisent ces affichages (pour la mise au point, mais pourraient aussi être utiles pour présenter le fonctionnement du programme).
Deux choix: soit virer touts les appels display, soit publier cette unité. Je ne la publierai pas dans l'état actuel car: - elle n'est pas toilettée
- elle n'est pas objet, ce qui empêche la création de plusieurs affichages
J'ai donc choisi: - d'en fournir une version allégé
- cette version est "objet": l'utilisateur peut avoir autant de display qu'il veut.
De plus pour conserver la compatibilité avec mes anciens programmes, les
primitives essentielles (display, display_line, clear_display) sont maintenue comme procédures globales et non objet, en appelant une objet c_display global. Ceci évite d'avoir à corriger la tonne de programmes
actuels en remplaçant: display('ok'); par mon_c_display.display('ok'); Bref, le meilleur des deux mondes. - la nouvelle mécanique permet l'écriture tamponnée (Write) en ajoutant
c_display.write (c_display.WriteLn étant l'affichage d'une ligne complète).
Notez que cette notation Write est un peu abusive, car nous n'avons de loin pas les fonctionalités de Write:
- redirection vers des fichiers quelconques (disque, imprimante)
Write(PRINTER, 'j''imprime'); - paramètres multiples
Write('le total est ', montant* taux); - formattage par :
Write('résultat: ', total: 12: 2, ' quantité ', quantité: 5); Peut-être Delphi permet-il de rediriger Write comme le faisait Pascal (cf l'article de Daniel GAVARIN dans Pascalissime).
Faute de temps, et comme l'affichage de mise au point ne nécessite pas ces ajouts, j'ai fait l'impasse. 1.3 - L'affichage indenté display(p_text) est la procédure fondamentale:
- l'indentation est décrémentée si la chaîne commence par <
- la chaîne est calculée à pâtir de l'indentation, la chaîne courante et le paramètre
- s'il y a un fichier log, les données y sont envoyées
- si la chaîne commence par >, l'indentation est incrémentée
2 - Utilisation 2.1 - L'interface est la suivante:
type c_display= class(c_basic_object)
public
m_do_display: Boolean;
m_indentation: Integer;
m_current_string: String;
m_c_strings: tStrings;
m_c_log: c_log;
Constructor create_display(p_name: String; p_c_strings: tStrings;
p_c_log: c_log); Virtual;
procedure clear_display;
procedure display_string(p_text: String);
procedure display(p_text: String);
procedure display_line;
function f_save_display: Boolean;
procedure restore_display(p_display: Boolean);
procedure stop(p_text: String);
procedure display_bug(p_text: String);
procedure display_bug_stop(p_text: String);
procedure display_bug_halt(p_text: String);
Destructor Destroy; Override;
end; | Pour les données:
- m_do_display: permet de bloquer l'affichage
- m_indentation: l'indentation. Gérée essentiellement en fournissant des lignes commençant par > ou <
- m_current_string: permet la construction progressive de la chaîne
- m_c_strings: le descendant de tStrings dans lequel aboutira la chaîne (en général un tMemo)
- m_c_log: le fichier dans lequel seront écrites les chaînes
Et pour les méthodes: - create_display: créé c_display, en indiquant dans quelle tStrings envoyer les chaînes et le nom du log
- pour l'affichage:
- clear_display: purge les tStrings
- display_string: ajoute une chaîne à la chaîne courante
- display: envoie la chaîne courante dans la tStrings et le log
- display_line: envoie une ligne vide dans la tStrings et le log
- l'affichage peut être temporairement désactivé:
- f_save_display: retourne la valeur de m_do_display
- restore_display: restore la valeur de m_do_display
- quelques procédures facilitent l'affichage des bugs:
- stop bloque l'exécution par un ShowMessage
- display_bug: affiche le texte avec '***' au début
- display_bug_stop: affiche le texte en bloquant l'exécution
- display_bug_halt: affiche le texte et interrompt le programme
2.2 - Répertoires
L'unité est prévue pour être placée dans: C: programs colibri_helpers classes
Vous pouvez naturellement changer cette organisation par Projet | Options | Directories 2.3 - Directives de compilation Les directives de compilation sont: - R+ (vérification des intervalles)
- S+ (vérification de la pile)
- pas d'optimisation
3 - Programmation Cette classe utilise essentiellement le fait que les tMemo.Lines sont des
descendants de tStrings: en ajoutant une ligne au tStrings de u_c_display, nous affichons dans le tMemo. L'affichage fonctionne ainsi:
- l'utilisateur appelle initialize_display qui stocke dans un pointeur privé de c_display l'adresse de mon_memo.Lines.
- toutes les unités qui utilisent par USES u_c_display peuvent ainsi
afficher dans mon_memo, sans avoir à importer la tForm qui contient le tMemo
4 - Améliorations La syntaxe actuelle est historique:
- display affiche une ligne, et display_strings une chaîne.
- une autre solution aurait été d'utiliser "display" pour une chaîne et display_line pour une ligne
Une autre possiblité aurait été de détourner les sorties des fichiers ASCII, ce qui aurait permis les possibilités de conversion et de formatage de Write.
Mentionnons aussi que les unités telles que WinCrt, ou autre dérivées de CRT offrent aussi ces possibilités d'affichage de mise au point. L'inconvénient à mes yeux est qu'une autre fenêtre est utilisée pour l'affichage, alors que
u_c_display permet l'affichage dans la fenêtre principale. 5 - Télécharger Vous pouvez télécharger: Avec les mentions d'usage:
- j'apprécie tous les commentaires, remarques ou critiques
- signalez-moi les bugs que vous trouverez.
L'auteur John COLIBRI est passionné par le développement
Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le
conseil (composants, architecture, test) et la
formation. Son site contient des articles
avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et
UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client. |