Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : GFA Basic - Un squelette de Macro-Recorder
(Article écrit par Stéphane Schreiber et extrait d'Amiga News Tech - novembre 1990)
|
|
C'est chose courante sur Mac, sur PC et même sur Atari ST, mais encore bien rare sur Amiga. Les macro-recorders
sont ces petits programmes qui permettent d'enregistrer les mouvements de la souris et les frappes au clavier pour
les rejouer ensuite à l'infini.
Il est vrai que sur une machine multitâche, qui plus est équipée d'ARexx, le macro-recorder perd quasiment toute son
utilité. Mais imaginez quand même votre pointeur de souris se baladant tout seul sur l'écran, allant comme par
magie double-cliquer sur une icône de disque puis sur celle de votre programme préféré, pour ensuite sélectionner
dans ses menus et requêtes les fonctions et options que vous aimez. Tout est alors prêt comme vous l'aimez, vous
n'avez plus qu'à commencer à travailler...
C'est donc pour étudier ce phénomène d'un peu plus près (NDLR : et aussi pour combler une défection
d'Étienne Mouratila et de son #?#@! de moniteur de disquettes...) que nous allons voir maintenant
comment cela est possible.
Input.device
Tout se joue depuis un périphérique logique bien particulier, nommé fort à propos "input.device". C'est lui qui
se charge de collecter les différents événements en provenance des périphériques d'entrée connectés à
l'Amiga. Il collecte les informations dont il a besoin depuis le keyboard.device (pour le clavier),
le gameport.device (pour la souris et les manettes) et le timer.device (pour la durée de répétition
des touches) et les dissémine dans le système, en particulier vers la console.device et Intuition.
Ce sont d'ailleurs ces deux derniers points qui nous intéressent plus particulièrement, puisque notre
tâche (sans jeu de mots !) consistera à envoyer nos propres informations à l'input.device, qui les
redistribuera au console.device et à Intuition.
En d'autres termes, il nous suffira de lui dire
un truc du genre "hé, coco, signale à qui tu veux - mais surtout à Intuition - que la souris a bougé
de tant de pixels et qu'on a appuyé sur le bouton droit" pour que notre brave input.device s'exécute,
sans chercher à savoir si cela est vrai ou non. La conséquence sera bien évidemment celle attendue :
le pointeur de la souris se déplacera "tout seul" à l'écran, et la barre de menu sera activée.
Comment ça marche ?
Concrètement, il faut savoir que l'input.device est un périphérique logique Amiga tout à fait standard. Il s'ouvre
donc à l'aide de la fonction OpenDevice, en ayant au préalable pris soin de créer un message-port
qui nous servira à communiquer avec lui (je précise dès maintenant que le but de cet article n'est
pas de faire un cours complet sur les périphériques logiques et leur utilisation ; reportez-vous pour cela à la
littérature adéquate, et plus particulièrement à l'Amiga ROM Kernel Manual, Libraries & Devices.
Pour les curieux, signalons que l'input.device est automatiquement ouvert par le console.device au
moment de la réinitialisation du système. Enfin, comme tout périphérique logique, l'input.device fonctionne au
moyen de commandes qui lui sont fournies dans le champ io_Command de sa structure IOStdReq associée :
Commandes de l'input.device
Nom |
Valeur |
Signification |
IND_ADDHANDLER |
9 |
Ajoute un gestionnaire personnel à la liste des gestionnaires |
IND_REMHANDLER |
10 |
Enlève un gestionnaire personnel à la liste des gestionnaires |
IND_WRITEVENT |
11 |
Envoie un flux d'événements à tous les "demandeurs" |
IND_SETTHRESH |
12 |
Règle le temps avant qu'une touche ne se répète |
IND_SETPERIOD |
13 |
Règle la vitesse de répétition des touches |
IND_SETMPORT |
14 |
Définit le port de la souris |
IND_SETMTYPE |
15 |
Définit le type de périphérique connecté sur le port souris |
IND_SETMTRIG |
16 |
Définit les conditions que doit remplir la souris avant qu'un événement souris ne soit signalé |
(je vous rassure, une seule de ces commandes nous sera utile, il s'agit de IND_WRITEVENT)
Pour ceux
qui veulent en savoir plus, un "handler" est une routine appelée chaque fois qu'une liste d'événements
va être passée aux "demandeurs" et qui peut modifier le contenu de ces événements (par exemple, pour
inverser l'effet des boutons gauche et droit). Il peut avoir plusieurs handlers définis, c'est pourquoi
ils sont appelés par ordre de priorité. Intuition a une priorité de 50, le console.device de 0. Ce n'est
toutefois pas ce qui nous intéresse ici. La commande IND_WRITEVENT utilise également une structure
InputEvent, dont plusieurs champs vont nous être utiles :
Structure InputEvent
Nom |
Décalage |
Signification |
ie_Class |
4 (byte) |
Nature de l'événement (clavier, souris, etc.) |
ie_Code |
6 (word) |
Touche du clavier ou bouton de la souris concerné |
ie_Qualifier |
8 (word) |
Indique les touches spéciales actives au moment de l'événement (Alt gauche et droit, Ctrl, etc.) |
ie_X |
10 (word) |
Déplacement horizontal de la souris |
ie_Y |
12 (word) |
Déplacement vertical de la souris |
Pour résumer la manoeuvre :
- Création d'une message-port avec port%=CreatePort(0,0).
- Création d'une structure InputEvent (longueur : &H16 octets) avec event%=AllocMem(&H16,&H1).
- Création d'une structure IOStdReq avec io%=CreateExtIO(Port,&H30).
- On relit les deux ensembles par LONG{io%+&H28}=event%.
- Ouverture de l'input.device avec OpenDevice(V:device_name$,0,io%,0).
- Remplissage des structures InputEvent et IOStdReq avec les valeurs appropriées (voir ci-dessous).
- Envoi de l'événement factice avec DoIO(io%).
- Fermeture "en sens inverse" de tout ce qui a été ouvert ou alloué.
Avant que de vous laisser cogiter sur le programme, voyons de plus près quels événements on peut
ainsi créer. Ils se divisent en deux catégories : les événements clavier et les événements souris.
C'est la valeur du champ ie_Class qui décide de tout ça :
Événements clavier et souris
ie_Class |
Valeur |
Effet |
IEC_NULL |
0 |
Aucun ! |
IEC_RAWKEY |
1 |
Événement clavier ; ie_Code contient le code SCAN de la touche (bit 7=0 -> touche appuyée, relâchée sinon) |
IEC_RAWMOUSE |
2 |
Événement souris ; ie_Code contient le bouton concerné (&H68-bouon gauche, &H69-bouton droit). Si en plus ie_Qualifier contient la valeur &H8000, alors ie_X contient le déplacement en X et ie_Y le déplacement en Y |
IEC_GADGETDOWN |
7 |
Gadget appuyé |
IEC_GADGETUP |
8 |
Gadget relâché |
IEC_CLOSEWINDOW |
11 |
Fenêtre fermée |
IEC_SIZEWINDOW |
12 |
Fenêtre changée de taille |
IEC_DISKREMOVED |
15 |
Disque enlevé d'un lecteur |
IEC_DISKINSERTED |
16 |
Disque introduit dans un lecteur |
Ce sont là les plus importants dans le cadre d'un macro-recorder. Notez au passage que ces événements
ne se contentent pas seulement de porter les mêmes noms que certains drapeaux IDCMP, ils remplissent
également les champs ie_Code et ie_Qualifier de la même manière que ces derniers (reportez-vous à
la littérature sur Intuition pour en savoir plus).
Le programme du mois
Ce programme est volontairement assez court. L'honnêté m'oblige à préciser que c'est la "traduction"
parfaite en GFA Basic du programme d'exemple page 699 du "RKM Libraries & Devices". Vous remarquerez
que le GFA Basic possède toutes les fonctions nécessaires en standard (CreatePort(), CreateExtIO(),
DeletePort(), etc.) sauf DeleteExtIO(). Pourquoi ? Cela restera un mystère pour tout le monde. Du
coup, on se la tape à la main, ça rajoute 10 lignes de programme, mais tant pis. Regardez bien
comment le fonctionnement général, cela vous donnera peut-être des idées...
|