Outils pour utilisateurs

Outils du site


issue112:tutoriel2

In this series of articles, I will be building a text-based application with Free Pascal, using its text-based interface for user interaction. This will be combined with other, more modern, technologies such as database access using SQL and Web access with HTTP. The final aim of the project is to demonstrate how Pascal can be used to build a modern application, while avoiding the overhead associated with a graphical interface that uses a widget set such as GTK or Qt. In the first part of this series we installed the required compiler software and developer’s interface. We compiled a simple console-based program and a first Free Vision application. In this second part we will be tuning our Free Vision interface and making it respond to commands.

Dans cette série d'articles, je construirai avec FreePascal une application en mode texte, en utilisant son interface mode texte pour l'interaction avec l'utilisateur. Celle-ci sera combinée avec d'autres technologies, plus modernes, comme l'accès aux bases de données en utilisant SQL ou l'accès Web avec HTTP. Le but final de ce projet est de démontrer comment Pascal peut être utilisé pour construire une application moderne, tout en évitant le surpoids associé à une interface graphique qui utilise un jeu de gadgets telle que GTK ou Qt.

Dans la première partie de cette série, nous avons installé l'indispensable logiciel de compilation et l'interface développeur. Nous avons compilé un programme simple en console et une première application Free Vision. Dans cette seconde partie, nous ajusterons notre interface Free Vision pour qu'elle réponde aux commandes.

Fleshing up the menu Let us now create a bespoke menu and make it responsive. To do so, we will overwrite two separate procedures of the standard TApplication object. The first is procedure InitMenuBar which, as its name suggests, populates the menu bar at the top of the screen. The other is the procedure that handles window events, in which we will be defining how our application needs to respond to button presses and suchlike. So our application object derives from the standard TApplication, with the addition of these two procedures. They are declared as “virtual” (top right)since they overwrite existing methods. We will be putting in a very basic menu bar with two submenus: a “File” menu with some standard options, and a “Help menu” with an option to open up the traditional “About” dialog (see box below). As readers accustomed to Turbo Pascal will have noticed, this is exactly the same syntax. In fact, I would not be surprised to learn that one of my projects from back then would just compile under Free Pascal. That is, if I manage to dig out the 3½” diskettes and a disk drive that still works. Just to refresh memories, let us note that “~” is used to indicate key accelerators, hcNoContext is the null Help Context, kbF2 is the code for keyboard key F2, and cmOpen is a 16-bit unsigned integer (word) code for standard command “Open”. The rest should be quite easy to figure out.

Étoffer le menu

Créons un menu sur mesure et rendons-le interactif. Pour ce faire, nous écraserons deux procédures différentes de l'objet standard TApplication. La première est la procédure InitMenuBar qui, comme son nom le suggère, installe la barre de menu en haut de l'écran. L'autre est la procédure qui manipule les événements de fenêtre, dans laquelle nous définirons comment nos applications doivent répondre au clic sur des boutons et autres. Ainsi, notre objet application dérive de TApplication standard, avec l'ajout de ces deux procédures. Elles sont déclarées « virtuelles » (en haut à droite), car elles écrasent des méthodes existantes.

Nous insérerons une barre de menu basique avec deux sous-menus : un menu « File » (Fichier) avec quelques options standards et un menu « Help » (Aide) avec une option qui ouvrira la traditionnelle boîte de dialogue « About » (À propos) (voir le code ci-dessous).

Comme les lecteurs accoutumés à Turbo Pascal l'auront remarqué, c'est exactement la même syntaxe. En fait, je ne serais pas surpris d'apprendre qu'un de mes vieux projets se compilerait normalement sous Free Pascal. C'est-à-dire, si j'arrive à retrouver mes disquettes 3“ 1/2 et un lecteur de disquettes qui fonctionne encore. Juste pour vous rafraîchir la mémoire, notons que « ~ » est utilisé pour indiquer des raccourcis clavier, hcNoContext est le contexte Help vide, kbF2 est le code pour la touche F2 du clavier et cmOpen est un code en entier non signé 16-bit (un mot) pour la commande standard « Open » (Ouvrir). Le reste devrait être facile à comprendre.

Responding to events The menu prepared above will actually respond to some buttons, but not to others. The difference is that TApplication’s default HandleEvent method knows what to do when the cmQuit command is issued (it simply quits). But it has not been programmed to respond to other events, such as the cmHelp command we put into the Help > About menu item. This is why we will be replacing the existing HandleEvent with our own. For example: It is especially important to include the original HandleEvent with the “inherited” command, since it handles the cmQuit command and we still want that to work. To respond to the cmHelp command, we are using a simple if structure to set up a MessageBox. This is a fast way of creating a message dialog box, that can be of several different types (Information, Alert, Error…). We do not get to personalize it much, since the final parameter can only hold flags to set up the dialog title, and the choice of the “OK” and/or “Cancel” buttons. To create a more interesting dialog window, we would need to write our own class (inheriting from TWindow or TDialog), which, though feasible, would be slightly more work. See the third article in the series for more details.

Répondre aux événements

Le menu préparé au-dessus répondra bel et bien à certains boutons, mais pas à d'autres. La différence vient de ce que la méthode par défaut HandleEvent de TApplication sait quoi faire quand arrive la commande cmQuit (elle sort, tout simplement). Mais elle n'a pas été programmée pour répondre à d'autres événements, tels que la commande cmHelp que nous avons mise dans l'élément de menu Help > About.

C'est pourquoi nous remplacerons la méthode HandleEvent existante par la nôtre. Par exemple :

Il est particulièrement important d'inclure l'original de HandleEvent avec le commande « héritée », car elle manipule la commande cmQuit et nous voulons que celle-là fonctionne toujours.

Pour répondre à la commande cmHelp, nous utilisons une simple procédure if pour paramétrer une MessageBox. C'est une façon rapide de créer une boîte de dialogue de message, qui peut être de différents types (Information, Alerte, Erreur…). Nous n'allons pas la personnaliser beaucoup, car le paramètre final ne peut contenir que les flags pour déclarer le titre du dialogue et le choix des boutons « OK » et/ou « Cancel » (Annuler). Pour créer une boîte de dialogue plus sophistiquée, nous aurions à écrire notre propre classe (héritée de TWindow ou TDialog), qui, bien que faisable, demanderait un peu plus de travail. Plus de détails dans le troisième article de la série.

Setting up a file input box There are also other, predefined, dialog types available. To take a classic example, in our programs we sometimes need to prompt the user to enter a file through the typical File Open dialog. Free Vision does things in the very same way as Turbo Vision. We will modify our HandleEvent to respond to cmOpen. To do so, we will need several variables: var FileName: String; result : integer; pOpen : PFileDialog; FileName is a string to save the user-inputted filename, result will contain the command code of the button chosen (cmOpen or cmCancel), while pOpen is a pointer to the new dialog to be created. Now, within HandleEvent, let us reply to cmOpen in the same way we handled cmHelp (see box top right).

Paramétrer une boîte de dialogue de saisie de fichier

Il y a aussi d'autres types de boîtes de dialogue disponibles et prédéfinis. Pour prendre un exemple classique, dans nos programmes, nous avons souvent besoin de solliciter l'utilisateur pour saisir un fichier via une boîte de dialogue d'ouverture de fichier. Free Vision fait les choses exactement comme Turbo Vision. Nous modifierons notre HandleEvent pour répondre à cmOpen. Pour ce faire, nous aurons besoin de plusieurs variables :

var

FileName: String;
result : integer;
pOpen : PFileDialog;

FileName est une chaîne de caractères pour sauvegarder le nom de fichier saisi par l'utilisateur, result contiendra le code de commande du bouton choisi (cmOpen ou cmCancel), tandis que pOpen est un pointeur vers la nouvelle boîte de dialogue à créer. Maintenant, dans HandleEvent, répondons à cmOpen de la même façon que nous avons opéré pour cmHelp (voir le cadre en haut à droite).

We have created a new FileDialog object, specifying that we wish to filter files with the ’*.txt’ pattern. When executed, the command chosen by the user is stored in variable result, and can then be examined to control subsequent actions. The dialog produced has nothing special to it as it is standard in Turbo and Free Vision. It just works and is very responsive. However, there are a couple of points to be noted since the last time I stared at one of these, back in the days of MS-DOS. The first is that it seems to handle well a POSIX file system, with the “/” file separator instead of MS-DOS’s idiosyncratic “C:” and “\”. The user can easily navigate through a standard Ubuntu home directory. On the other hand, we can also see that Unicode characters in filenames that do not appear in the common ASCII codepage (codes up to 127) have been altered, specifically the accents in “Música” and “Públic”. This may be a minor problem for some, or major for others if the intended end user’s environment is mostly in a non-latin script.

Nous avons créé un objet FileDialog, en spécifiant que nous souhaitons filtrer les fichiers avec le motif « *.txt ». À l'exécution, la commande choisie par l'utilisateur est stockée dans la variable result et peut ensuite être analysée pour piloter les actions qui en découlent.

La boîte de dialogue obtenue n'a rien de spécial car elle est standard dans Turbo et Free Vision. Elle fonctionne tout simplement et est très réactive.

Cependant, depuis la dernière fois que j'en ai contemplé une, du temps de MS-DOS, il y a deux points à noter. Le premier est qu'elle semble manipuler correctement un système de fichiers POSIX, avec le séparateur de fichier « / » à la place des « C: » et « \ » spécifiques à MS-DOS. L'utilisateur peut facilement naviguer dans le répertoire home habituel d'Ubuntu. D'autre part, nous pouvons aussi voir que les caractères Unicode dans les noms de fichiers qui n’apparaissent pas dans la page de code ASCII ordinaire (codes jusqu'à 127) sont modifiés, particulièrement les accents dans « Música » et dans « Públic ». C'est peut-être un problème mineur pour certains, ou pour d'autres un problème majeur, si l'environnement visé pour un utilisateur final est principalement en écriture non latine.

By this point, we have been using several of Free Vision’s library units, which must be included at the beginning of our program file: uses App, Objects, Menus, Drivers, Views, Dialogs, MsgBox, StdDlg; The complete code for this example is available at http://pastebin.com/ZTbN7Eft, in which the reader can see the points covered in this part of the series: personalizing the Free Vision menu bar, responding to commands, and using default message boxes and dialogs. In the next part, we will see how to connect our application to a modern database such as Sqlite3.

À ce stade, nous avons utilisé plusieurs unités de la bibliothèque de Free Vision, qui doivent être incluses au début de notre fichier de programme :

uses App, Objects, Menus, Drivers, Views, Dialogs, MsgBox, StdDlg;

Le code complet de cet exemple est sur http://pastebin.com/ZTbN7Eft, où le lecteur peut voir les points couverts dans cette partie de la série : personnaliser la barre de menu de Free Vision, répondre aux commandes et utiliser les boîtes de messages et les dialogues par défaut. Dans la prochaine partie, nous regarderons comment connecter notre application à une base de données moderne comme Sqlite3.

issue112/tutoriel2.txt · Dernière modification : 2016/09/02 15:20 de andre_domenech