|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Après avoir vu le traitement des erreurs et défauts d'un programme ARexx, nous pouvons nous lancer dans l'utilisation de deux bibliothèques, la rexxarp.library et la rexxmathlib.library. Bien que ce ne soit pas la vocation d'ARexx, il a été muni par Willy Langeveld, de ces deux bibliothèques qui permettent d'une part de profiter des avantages d'Intuition (écrans, fenêtres, menus et gadgets de toutes sortes) et d'autre part, de calculer l'inverse de la tangente hyperbolique sans trop se casser la tête. La bibliothèque graphique - ou du moins visuelle - est moins riche qu'Intuition, mais elle permet de réaliser des écrans passablement conviviaux, c'est-à-dire ergonomiques, même si la variété, par exemple des gadgets, est assez limitée. Quant à la bibliothèque mathématique, elle est, elle, plutôt riche. Trois bibliothèques spécifiques doivent être présentes dans le répertoire Libs: pour que l'on puisse espérer modeler la visualisation à son gré : rexxsupport.library, rexxmathlib.library et rexxarplib.library. Il est recommandé de tester leur présence dès le début du programme :
0, -30 et 0 correspondent respectivement à la priorité, l'offset (ou décalage) et à la version ; on les laisse traditionnellement à cette valeur, surtout l'offset ! Cet exemple doit être étendu à chacune des bibliothèques précitées. Dans le cas présent, le test regarde si la bibliothèque a été effectivement ajoutée au traitement résident, sinon il annonce le défaut pendant "DELAY 100" avant de quitter le programme. Dès que tout est en ordre on peut se lancer. Écrans publics Ces écrans sont réputés publics parce qu'on peut les adresser et agir sur eux par leur nom, qui est connu. Ce pourra être l'écran que l'on va définir ou un autre dont on connaît le nom (l'adresse, en fait !). Cette définition d'écran n'est pas utile si l'on veut se servir de l'écran courant uniquement. On rappelle ici qu'un écran ne définit que le mode graphique : nombre de plans de bits (correspondant au nombre maximal de couleurs) et résolution en lignes et colonnes. Un écran doit suivre des règles précises, en particulier pour ce qui est de la superposition des écrans de résolution différentes. Dans le cas présent, la seule liberté qui nous est laissée est la hauteur à laquelle commence l'écran, à partir du haut. Pour ouvrir un écran, on utilise la séquence suivante :
Enfin, un écran doit être fermé après emploi :
En cas de défaut, il se peut que le programme se termine sans passer par la fermeture des écrans publics qu'il aura ouverts. Or, il n'est plus possible de réouvrir cet écran après rectification du ou des défauts ; il faut d'abord le fermer. Une solution est de se rappeler le nom de l'écran et à partir de la console taper :
OpenScreen et CloseScreen s'appliquent indifféremment à tous les écrans publics ouverts par vous ou par une autre application. La seule connaissance nécessaire est celle du nom de l'écran considéré. Paramètres d'un écran Il peut être intéressant ou utile de connaître les caractéristiques d'un écran public que l'on veut utiliser et que l'on n'a pas défini soi-même. Quatre fonctions spéciales effectuent ce travail :
Position relative d'un écran Lorsqu'un écran est créé, on peut le placer à volonté devant tous les autres au moyen de ScreenToFront(nom), ou derrière avec ScreenToBack(nom). Ces deux fonctions retournent 1 en cas de succès et 0 dans l'autre cas. Barre d'écran La fonction ShowTitle(nom, ouinon) permet de faire apparaître le titre de l'écran ou de le cacher à volonté. Si ouinon vaut 1, la barre de titre montre le titre de l'écran nom, sinon elle le cache. C'est sur cette instruction, dont l'importance n'échappera pas aux plus attentifs de nos lecteurs, que nous fermerons le chapitre écran ! Fenêtres C'est la partie visible de la création d'un environnement. Pour pouvoir interagir avec la fenêtre, il faut créer des moyens d'accès nommés "Ports" selon l'usage en vigueur dans le système de l'Amiga. Il y a deux types d'accès à une fenêtre : l'écriture ou la lecture de quelque chose se passant dans cette fenêtre. Il va donc falloir créer deux canaux de communication, l'un allant vers la fenêtre, l'autre venant de la fenêtre. Il n'est pas nécessaire que ces deux canaux (Ports) existent simultanément : on ne crée que ceux dont on a besoin. Enfin, on ne peut créer de telles relations qu'avec un écran connu, ou le Workbench par défaut. Création des ports Il y a plusieurs façons de créer les ports.
Ce qui, traduit en quelque chose de supposé plus intelligible, veut dire : ordre à AREXX (port permanent du système) de créer un port ECRIT permettant d'écrire et un port LIT, permettant de recevoir des informations de la fenêtre qui va être créée dans l'écran : nom. De la même façon, on pourrait écrire :
Il est alors utile de patienter quelque peu, le temps de la création. Voici différentes façons de faire.
Ceci teste régulièrement la présence du port en construction ; le "FOR 50" étant là pour limiter la durée si, par hasard, il n'y avait pas d'ouverture possible. Une autre possibilité est d'utiliser la fonction :
Ou encore :
Qui donne dans retour et au bout de 10 secondes maximum, 0 si le port existe ou 5 dans le cas contraire. Il faut faire attention à respecter les majuscules et minuscules dans l'orthographe du nom du port. En règle générale, simplifier au plus le nom du port est une heureuse initiative ! Notons enfin qu'il faut ouvrir le port :
La fenêtre proprement dit Une fenêtre est caractérisée par plusieurs éléments :
On peut encore y ajouter BORDERLESS, NOCAREREFRESH, ACTIVATE ou BACKFILL, chacun de ces termes étant présent ou absent selon le besoin. IDCMP représente les messages qui seront émis par la fenêtre. Ils sont nombreux et concernent les gadgets, les menus, la position de la souris, le lecteur de disquette (pour savoir si l'on a changé la disquette), etc. On aurait par exemple :
...et bien d'autres (NDLR : on ne va tout de même pas vous refaire un cours complet sur les fenêtres, non ?). L'ouverture de la fenêtre s'effectue selon le cérémonial suivant :
De la même façon que pour les écrans, une fenêtre peut être placée devant ou derrière toutes les autres, dans son écran.
...où "nomduport" est le nom du port d'écriture dans la fenêtre. On peut également la rendre active par :
Enfin, il faut pouvoir la fermer : Close Window(nomduport), Exit(nomduport), Quit(nomduport) et Stop(nomduport) sont synonymes. Ces commandes, dont la multiplicité n'a pas de raison ouvertement avouée, ferment la fenêtre considérée, désallouent les ressources et provoquent la sortie, à l'exception de CloseWindow qui peut supporter une option CloseWindow(nomcluport, 'CONTINUE') permettant à l'hôte de rester actif tout en fermant la fenêtre. Comme dans le cas de l'écran, en cas de sortie intempestive du programme, sur défaut par exemple, la ou les fenêtres en cours ne sont pas automatiquement fermées. On peut les fermer à partir de la console par "rx 'Closewindow(nomport)". On devra fermer d'abord toutes les fenêtres d'un écran avant de lancer la fermeture de l'écran lui-même. On voit l'intérêt de se rappeler le nom des fenêtres ou celui des écrans pendant la mise au point et de ne leur donner que des noms simples. Sinon c'est le redémarrage assuré. Ce que raconte une fenêtre Nous verrons par la suite comment extraire un message issu d'une fenêtre. Pour le moment, on admet avoir reçu un message. Que contient-il ? Si rien n'a été précisé (autre que les IDCMP), le message contient par exemple : CLOSEWINDOW si CLOSEWINDOW a été sollicité, DISKREMOVED si la disquette a été retirée et l'IDCMP correspondant initialisé... A part la chaîne contenue dans le gadget et qui est retournée par les IDCMP GADGETUP et GADGETDOWN, on ne reçoit que le nom ou la classe de l'IDCMP. En particulier avec MOUSEMOVE, on ne sait qu'une seule chose : la souris a été déplacée. Cela peut suffire mais c'est plutôt la quantité dont elle a été déplacée qui est intéressante. Pour les menus c'est la même chose. Il faut donc préciser ce que l'on veut recevoir. C'est l'objet de la commande ModifyHost. Le message envoyé peut être organisé en arguments consécutifs, contenant chacun ce que l'on souhaite. Par défaut, on obtenait sans avoir rien précisé l'Arg(0), qui contenait les noms des IDCMP. Nous allons pouvoir préciser ce que l'on veut et dans quel argument (de 0 à 15), on veut le trouver. On invoque le modificateur de la façon suivante :
IDCMP est le message que l'on veut traiter. Imaginons pour l'exemple que ce soit MOUSEMOVE. La chaîne de x s'écrit :
...ce qui se traduit : dans l'argument 3, mettre la position x puis la position y de la souris. Donc, "CALL ModifyHost(nomport, MOUSEMOVE, %3%x, %y)" permettra ultérieurement (après extraction de l'argument 3) de trouver la position de la souris dans une chaîne du genre : 145 23. La précision de l'argument ne fait qu'effectuer un pré-tri pour le cas où beaucoup de messages sont possibles. On trouve de nombreuses possibilités. Par exemple, "%m" donne le numéro du menu sollicité ; "%s" permet d'obtenir le numéro de sous-menu ; "%h" permet d'obtenir la hauteur de la fenêtre alors que "%t" donne le nombre de secondes écoulées depuis le 1 janvier 1980, à l'instant où l'évènement est survenu. Il y a 16 types d'IDCMP concernant les fenêtres, la souris et ses boutons, les gadgets, les menus et sous-menus, les touches du clavier, les préférences et les disquettes. Il y a 18 modifications possibles, et 16 arguments. La souplesse s'obtient en augmentant la complexité. Alors que la réception de messages met en jeu un mécanisme compliqué, mais tout à fait conforme a celui que l'on met en oeuvre avec Intuition, l'écriture dans la fenêtre est beaucoup plus simple et très facilement manipulable. C'est peut-être une consolation. Avant de passer à des exemples plus concrets, notons encore les commandes "SetNotify(nomport,IDCMP,nouveauport)" qui permet de réaffecter le message émis à un nouveau port et "ReadHost(nomport,portreçois,texte)" qui permet de déclencher l'envoi de texte au port reçois après les modifications éventuellement effectuées par "ModifyHost".
|