Oubliez tout ceux qui vous ont dit que le QBasic était un langage limité. Non, le QBasic a bien
d'autres possibilités que celles qu'on lui connaît. Il peut, comme le Pascal par exemple, inclure
des portion de langage machine, peut-être plus connu sous le nom de langage d'assemblage. Simplement,
la mise en oeuvre est peut-être un peu plus compliquée en QBasic.
Pour vous démontrer tout ceci, nous allons créer pas à pas une routine cruellement manquante au
QBasic : le support de la souris. En effet, vous aurrez beau chercher partout dans le fichier
d'aide fourni avec QBasic, jamais vous ne trouverez une quelconque allusion à l'utilisation de
ce périphérique.
Certains vous rétorqueront que l'on peut faire appel à la fonction CALL INTERRUPT. Mais
cette fonction n'est présente que dans la version 4.5 de QBasic (appellée aussi Quick Basic).
Nous allons donc utiliser un cheminement qui peu paraître un peu plus compliqué au premier abord,
mais qui donne néanmoins le même résultat, et qui à le méritte de fonctionner sur n'importe quelle
version de QBasic, dès la 1.1.
Mais il vous faut tout de même connaitre quelques notions d'assembleur. Vous pouvez pour cela
vous reporter à la section correspondante sur ce même site.
Avant de découvrir les instructions elles même, nous allons détailler celles qui nous serviront
à écrire et à executer le sous-programme en langage machine que nous allons écrire.
Notre programme sera stocké directement en mémoire. Comme vous le savez si vous avez lu le chapitre
précédent, un emplacement de la mémoire est défini par un segment et un offset.
Vu que le sous programme sera stocké dans un tableau, les premières lignes vont de soit :
DIM Asm%(0) ' Tableau INTEGER (préfixe %)
SegAsm = VARSEG(Asm%(0)) ' Segement du tableau Asm%
OffAsm = VARPTR(Asm%(0)) ' OffSet du tableau Asm%
DEF SEG = SegAsm ' On va au segment du tableau Asm%
Ensuite, on va stocker notre passage en langage machine dans des DATA (comme pour les sprites),
c'est ce qu'il y a de plus pratique après un fichier indépendant.
Pour l'instant, on va se contenter d'afficher seulement le curseur de la souris. Il faut savoir
que pour l'afficher, il faut utiliser la fonction 0001h dans le registre AX, puis
l'interruption 33h (charabia ? pas si sûr...).
Le registre AX est en fait représenté par la valeur héxadécimale B8. Pour 0001h, on écrira
01, puis 00. Pour appeler une intérruption (INT en assembleur), on écrit le code héxadécimal
CD. Ensuite, pour 33h, on écrit bêtement 33.
Vu que se sont des valeurs hexadécimal, il faut rajouter &H devant chaque terme.
Notre programme dans les DATA donnera :
' Code pour afficher le curseur de la souris
DATA &HB8, &H01, &H00, &HCD, &H33, &HCB
Le &HCB, c'est pour terminer proprement le sous-programme. Ommétez le et les conséquences
seront terribles !
Pour stocker des octets en mémoire, on utilise l'instruction POKE. La syntaxe est :
POKE OffSet, Octet%
Donc, pour stocker notre sous-programme en mémoire, on écrira :
DIM Asm%(5) ' Tableau INTEGER (préfixe %)
SegAsm = VARSEG(Asm%(0)) ' Segement du tableau Asm%
OffAsm = VARPTR(Asm%(0)) ' OffSet du tableau Asm%
DEF SEG = SegAsm ' On va au segment du tableau Asm%
FOR i% = LBOUND(Asm%, 1) TO UBOUND(Asm%, 1)
READ Octet% ' INTEGER
POKE OffAsm + i%, Octet% ' On décale d'une position à chaque fois
NEXT i%
' Code pour afficher le curseur de la souris
DATA &HB8, &H01, &H00, &HCD, &H33, &HCB
N'oubliez pas de changer la dimension du tableau, à la première ligne. Maintenant, il faut qu'il
fasse 6 !
Ensuite, pour executer le programme, on va utiliser l'instruction CALL ABSOLUTE. La syntaxe
est :
CALL ABSOLUTE([Arg, ] OffSet)
Entre crochets, ce sont les arguments (en général, les valeurs renvoyées). Ici, il n'y en a pas,
donc :
DIM Asm%(5) ' Tableau INTEGER (préfixe %)
SegAsm = VARSEG(Asm%(0)) ' Segement du tableau Asm%
OffAsm = VARPTR(Asm%(0)) ' OffSet du tableau Asm%
DEF SEG = SegAsm ' On va au segment du tableau Asm%
FOR i% = LBOUND(Asm%, 1) TO UBOUND(Asm%, 1)
READ Octet% ' INTEGER
POKE OffAsm + i%, Octet% ' On décale d'une position à chaque fois
NEXT i%
CALL ABSOLUTE(OffSeg) ' Appel du sous-programme
DEF SEG ' NE PAS OUBLIER DEF SEG
DO
LOOP UNTIL INKEY$ <> "" ' Petite boucle, pour voir ce qu'il se passe
' Code pour afficher le curseur de la souris
DATA &HB8, &H01, &H00, &HCD, &H33, &HCB
Saisissant, non ? Et attention, vous n'êtes pas encore au bout de vos surprises ! Ce n'était qu'une
simple démonstration des capactités de QBasic ce traiter le langage d'assemblage.
Maintenant que vous avez compris le fonctionnement de la gestion de la mémoire, je vais vous
donner le secret pour utiliser correctement la souris. On pourra, ainsi afficher le curseur ou le
faire disparaitre, connaitre les coordonnées X et Y, déplacer le curseur... Bref, l'indispensable.
Vu que le programme est totalement en assembleur, je ne vais pas le détailler, vu que le langage
traité dans cette rubrique est le Basic.
Voici le programme :
CONST TRUE = -1
CONST FALSE = 0
DIM SHARED SegAsm%
DIM SHARED OffAsm%
DIM Asm%(56)
SegAsm% = VARSEG(Asm%(0))
OffAsm% = VARPTR(Asm%(0))
DEF SEG = SegAsm%
FOR i% = LBOUND(Asm%, 1) TO UBOUND(Asm%, 1)
READ Octet%
POKE OffAsm% + i%, Octet%
NEXT i%
DEF SEG
' Langage machine pour la gestion de la souris
DATA &H55,&H89,&HE5,&H8B,&H5E,&H0C,&H8B,&H07,&H50,&H8B
DATA &H5E,&H0A,&H8B,&H07,&H50,&H8B,&H5E,&H08,&H8B,&H0F
DATA &H8B,&H5E,&H06,&H8B,&H17,&H5B,&H58,&H1E,&H07,&HCD
DATA &H33,&H53,&H8B,&H5E,&H0C,&H89,&H07,&H58,&H8B,&H5E
DATA &H0A,&H89,&H07,&H8B,&H5E,&H08,&H89,&H0F,&H8B,&H5E
DATA &H06,&H89,&H17,&H5D,&HCA,&H08,&H00
FUNCTION InitMouse()
'-----------------------------------------
'| |
'| Initialise la souris |
'| + TRUE si une souris est détectée |
'| + FALSE si aucune souris détectée |
'| |
'-----------------------------------------
DEF SEG = SegAsm%
ax% = 0
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
IF ax% = 0 THEN InitMouse = FALSE ELSE InitMouse = TRUE
DEF SEG
END FUNCTION
FUNCTION GetMouseX()
'-----------------------------------------
'| |
'| Renvoi les coordonnées X de la souris |
'| |
'-----------------------------------------
DEF SEG = SegAsm%
ax% = 3
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
GetMouseX = cx%
DEF SEG
END FUNCTION
FUNCTION GetMouseY()
'-----------------------------------------
'| |
'| Renvoi les coordonnées Y de la souris |
'| |
'-----------------------------------------
DEF SEG = SegAsm%
ax% = 3
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
GetMouseY = dx%
DEF SEG
END FUNCTION
FUNCTION GetMouseLButton()
'------------------------------------------------
'| |
'| Renvoi l'état du bouton gauche de la souris: |
'| + TRUE si enfoncé |
'| + FALSE si relaché |
'| |
'------------------------------------------------
DEF SEG = SegAsm%
ax% = 3
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
IF bx% = 1 OR bx% = 3 THEN GetMouseLButton = TRUE ELSE GetMouseLButton = FALSE
DEF SEG
END FUNCTION
FUNCTION GetMouseRButton()
'-----------------------------------------------
'| |
'| Renvoi l'état du bouton droit de la souris: |
'| + TRUE si enfoncé |
'| + FALSE si relaché |
'| |
'-----------------------------------------------
DEF SEG = SegAsm%
ax% = 3
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
IF bx% = 2 OR bx% = 3 THEN GetMouseRButton = TRUE ELSE GetMouseRButton = FALSE
DEF SEG
END FUNCTION
SUB ShowMouse()
'-----------------------------------
'| |
'| Affiche le curseur de la souris |
'| |
'-----------------------------------
DEF SEG = SegAsm%
ax% = 1
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
DEF SEG
END SUB
SUB HideMouse()
'----------------------------------
'| |
'| Masque le curseur de la souris |
'| |
'----------------------------------
DEF SEG = SegAsm%
ax% = 2
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
DEF SEG
END SUB
SUB MoveMouse(x%, y%)
'-----------------------------------
'| |
'| Déplace le curseur de la souris |
'| |
'-----------------------------------
DEF SEG = SegAsm%
ax% = 4
cx% = x%
dx% = y%
CALL Absolute(ax%, bx%, cx%, dx%, OffAsm%)
DEF SEG
END SUB
Bien entendu, on aurrait pu faire plus simple (on peut toujours faire plus simple). Mais le but
est de vous montrer comment fonctionne chaque fonction.
J'ai écris le nom des fonctions en English parceque je trouve que GetMouseX sonnait
mieux que DonneSourisX. Mais rien ne vous empêche de les traduire...
Les fonctions de cette ébauche de programme sont :
- InitMouse : initialise la souris. L'utilisation en est conseillée avant toute intervention
sur la souris.
- GetMouseX : renvoi les coordonnées X virtuel de la souris.
- GetMouseY : renvoi les coordonnées Y virtuel de la souris.
- GetMouseLButton : renvoi l'état du bouton gauche de la souris (TRUE si enfoncé, FALSE
si relaché).
- GetMouseRButton : renvoi l'état du bouton droit de la souris (TRUE si enfoncé, FALSE
si relaché).
- ShowMouse : affiche le curseur de la souris.
- HideMouse : masque le curseur de la souris.
- MoveMouse : déplace le curseur au coordonnées X et Y spécifiée. Le curseur doit cependant
être visible.
|