[Back to MOUSE SWAG index] [Back to Main SWAG index] [Original]
{ AUTEUR : AVONTURE Christophe
BUT DE L'UNITE : FOURNIR LES FONCTIONS DE GESTION DE LA SOURIS
DATE DE REDACTION : 8 MARS 1996
DERNIERE MODIF. : 8 MARS 1996 }
UNIT uMouse;
INTERFACE
TYPE
cgCoord = (cgPixel, cgCharacter);
CONST
{ Nombre de Handle actuellement associ‚ au Handler de la souris }
cgCurrentProc : Byte = 0;
{ Autorise l'appel aux diff‚rentes proc‚dures cr‚‚es par les Handler ou
interdit leur appel. }
cgEnableMouseProc : Boolean = True;
{ D‚finit si les coordonn‚es sont … consid‚rer comme ‚tant relatifs … des
pixels ou bien relatifs … des caractŠres }
cgCoordonnees : cgCoord = cgPixel;
TYPE
{ Constantes Boutons enfonc‚s }
cgMouse_Key = (cgMouse_None, cgMouse_Left, cgMouse_Right, cgMouse_Both);
{ Structure permettant d'associer une proc‚dure lorsque le clic de la
souris se fait dans le rectangle d‚limit‚ par
(XMin, YMin) -------------- (XMax, YMin)
: :
: :
(XMin, YMax) -------------- (XMax, YMax) }
TProcedure = PROCEDURE;
TMouseHandle = RECORD
XMin, XMax, YMin, YMax : Word;
Adress_Proc : TProcedure;
END;
{ Lorsque l'utilisateur clic en un certain endroit, si cet endroit est
compris dans le rectangle sp‚cifi‚ ci-dessus, alors il faudra ex‚cuter
une certaine proc‚dure.
On va pouvoir sp‚cifier autant de surfaces diff‚rentes. La seule
restriction sera la m‚moire disponible.
Ainsi, on pourra dessiner un bouton OK, un bouton CLOSE, ... et leur
associer un ‚vŠnement qui leur est propre.
Cela sera obtenu par la gestion d'un liste chaŒn‚e vers le haut. }
TpListMouseHandle = ^TListMouseHandle;
TListMouseHandle = RECORD
Next : TpListMouseHandle;
Item : TMouseHandle;
END;
VAR
{ Liste chaŒn‚e des diff‚rents handles associ‚s au handler de la souris }
MouseProc : TpListMouseHandle; { Zone de travail }
MouseProcFirst : TpListMouseHandle; { Tout premier ‚vŠnement }
MouseProcOld : TpListMouseHandle; { Sauvegarde de l'ancien ‚vŠnement }
{ True si un gestionnaire de souris est pr‚sent }
bMouse_Exist : Boolean;
{ Coordonn‚es du pointeur de la souris }
cgMouse_X : Word;
cgMouse_Y : Word;
{ Correspondant du LastKey. Contient la valeur du dernier bouton
enfonc‚ }
cgMouse_LastButton : cgMouse_Key;
{ Lorsque le clic ne se fait pas dans une des surfaces couvertes par les
diff‚rents handlers (voir AddMouseHandler); on peut ex‚cuter une
certaine proc‚dure. }
hClicNotInArea : Pointer;
PROCEDURE Mouse_Show;
PROCEDURE Mouse_Hide;
PROCEDURE Mouse_GoToXy (X, Y : Word);
PROCEDURE Mouse_Window (XMin, XMax, YMin, YMax : Word);
PROCEDURE Mouse_AddHandler (XMin, XMax, YMin, YMax : Word; Adress : TProcedure);
PROCEDURE Mouse_RemoveHandler;
PROCEDURE Mouse_Handle;
PROCEDURE Mouse_Flush;
FUNCTION Mouse_Init : Boolean;
FUNCTION Mouse_Pressed : cgMouse_Key;
FUNCTION Mouse_InArea (XMin, XMax, YMin, YMax : Word) : Boolean;
FUNCTION Mouse_ReleaseButton (Button : cgMouse_Key) : Boolean;
{ ------------------------------------------------------------------------ }
IMPLEMENTATION
{ Teste si un gestionnaire de souris est pr‚sent }
FUNCTION Mouse_Init : Boolean;
BEGIN
ASM
Xor Ax, Ax
Int 33h
Mov Byte Ptr bMouse_Exist, Ah
END;
END;
{ Cache le pointeur de la souris }
PROCEDURE Mouse_Hide; ASSEMBLER;
ASM
Mov Ax, 02h
Int 33h
END;
{ Montre le pointeur de la souris }
PROCEDURE Mouse_Show; ASSEMBLER;
ASM
Mov Ax, 01h
Int 33h
END;
{ Retourne une des constantes ‚quivalents aux boutons enfonc‚s. Retourne 0
si aucun bouton n'a ‚t‚ enfonc‚ }
FUNCTION Mouse_Pressed : cgMouse_Key; ASSEMBLER;
ASM
Mov Ax, 03h
Int 33h
{ Bx contiendra 0 si aucun bouton n'a ‚t‚ enfonc‚
1 bouton de gauche
2 bouton de droite
3 bouton de gauche et bouton de droite
4 bouton du milieu }
Mov Ax, Bx
Mov cgMouse_X, Cx
Mov cgMouse_Y, Dx
Mov cgMouse_LastButton, Al
END;
{ Positionne le curseur de la souris }
PROCEDURE Mouse_GoToXy (X, Y : Word); ASSEMBLER;
ASM
Mov Ax, 04h
Mov Cx, X
Mov Dx, Y
Int 33h
END;
{ D‚finit la fenˆtre dans laquelle le curseur de la souris peut ‚voluer }
PROCEDURE Mouse_Window (XMin, XMax, YMin, YMax : Word); ASSEMBLER;
ASM
Mov Ax, 07h
Mov Cx, XMin
Mov Dx, XMax
Int 33h
Mov Ax, 08h
Mov Cx, YMin
Mov Dx, YMax
Int 33h
END;
{ Teste si le curseur de la souris se trouve dans une certaine surface }
FUNCTION Mouse_InArea (XMin, XMax, YMin, YMax : Word) : Boolean;
BEGIN
IF NOT bMouse_Exist THEN
Mouse_InArea := False
ELSE
BEGIN
{ Les coordonn‚es sont-elles … consid‚rer comme pixels ou comme
caractŠres }
IF cgCoordonnees = cgPixel THEN
BEGIN
IF NOT (cgMouse_X < XMin) AND NOT (cgMouse_X > XMax) AND
NOT (cgMouse_Y < YMin) AND NOT (cgmouse_y > YMax) THEN
Mouse_InArea := True
ELSE
Mouse_InArea := False
END
ELSE
BEGIN
{ Il s'agit de caractŠres. Or un caractŠre fait 8 pixels de long.
Donc, lorsque l'on programme (0,1,0,1, xxx), il s'agit du
caractŠre se trouvant en (0,0) qui se trouve en r‚alit‚ en
0..7,0..15 puisqu'il fait 8 pixels de long sur 16 de haut. }
IF NOT (cgMouse_X Shr 3 < XMin ) AND
NOT (cgMouse_X Shr 3 > XMax ) AND
NOT (cgMouse_Y Shr 3 < YMin ) AND
NOT (cgmouse_y Shr 3 > YMax ) THEN
Mouse_InArea := True
ELSE
Mouse_InArea := False;
END;
END;
END;
{ Ajoute un ‚vŠnement. }
PROCEDURE Mouse_AddHandler (XMin, XMax, YMin, YMax : Word; Adress : TProcedure);
BEGIN
IF bMouse_Exist THEN
BEGIN
{ On peut ajouter un ‚vŠnement pour autant qu'il reste de la m‚moire
disponible pour le stockage du pointeur sur la proc‚dure et de la
sauvegarde des coordonn‚es de la surface d‚limit‚e pour son action. }
IF MemAvail > SizeOf(TListMouseHandle) THEN
BEGIN
Inc (cgCurrentProc);
IF cgCurrentProc = 1 THEN
BEGIN
{ C'est le tout premier ‚vŠnement. Sauvegarde du pointeur
pour pouvoir ensuite fabriquer la liste. }
New (MouseProc);
MouseProcFirst := MouseProc;
{ Sauvegarde du pointeur courant pour pouvoir fabriquer la
liste. }
MouseProcOld := MouseProc;
{ Etant donn‚ que le liste se rempli de bas en haut -le
premier introduit est le moins prioritaire, ...-; seul le
premier aura un pointeur vers NIL. Cette m‚thode permettra
… un ‚vŠnement de recouvrir une surface d‚j… d‚limit‚e par
un autre objet. }
MouseProc^.Next := NIL;
END
ELSE
BEGIN
{ Ce n'est pas le premier. Il faut que je cr‚e le lien avec
le pointeur NEXT de l'‚vŠnement pr‚c‚dent. }
MouseProcOld := MouseProc;
New (MouseProc);
MouseProc^.Next := MouseProcOld;
MouseProcFirst := MouseProc;
END;
{ Les liens cr‚‚s, je peux en toute s‚curit‚ sauvegarder les
donn‚es. }
MouseProc^.Item.XMin := XMin;
MouseProc^.Item.XMax := XMax;
MouseProc^.Item.YMin := YMin;
MouseProc^.Item.YMax := YMax;
MouseProc^.Item.Adress_Proc := Adress;
END;
END;
END;
{ Cette proc‚dure retire le tout dernier ‚vŠnement introduit tout en
conservant la coh‚rence de la liste. }
PROCEDURE Mouse_RemoveHandler;
BEGIN
IF bMouse_Exist THEN
BEGIN
IF NOT (MouseProc^.Next = NIL) THEN
BEGIN
MouseProcFirst := MouseProc^.Next;
Dispose (MouseProc);
MouseProc := MouseProcFirst;
Dec (cgCurrentProc);
END;
END;
END;
{ Examine si le clic s'est fait dans une surface d‚limit‚e par un ‚vŠnement.
Si c'est le cas, alors appel de l'‚vŠnement en question. }
PROCEDURE Mouse_Handle;
VAR
bFin : Boolean;
bNotFound : Boolean;
BEGIN
IF bMouse_Exist THEN
BEGIN
{ Il doit y avoir un process uniquement si on a associ‚ des ‚l‚ments au
handler de la souris. ET SEULEMENT SI LES APPELS AUX DIFFERENTES
PROCEDURES SONT AUTORISES OU NON. }
IF cgEnableMouseProc AND (cgCurrentProc > 0) THEN
BEGIN
bFin := False;
{ bNotFound sera mis sur True lorsque le clic s'est fait dans une
surface non couverte par un handler. }
bNotFound := False;
{ Pointe sur le tout premier ‚vŠnement }
MouseProcOld := MouseProcFirst;
REPEAT
IF Mouse_InArea (MouseProcOld^.Item.XMin, MouseProcOld^.Item.XMax,
MouseProcOld^.Item.YMin, MouseProcOld^.Item.YMax) THEN
BEGIN
{ Le clic s'est fait dans une surface … surveiller. Appel
de l'‚vŠnement ad'hoc. }
MouseProcOld^.Item.Adress_Proc;
bFin := True;
END
ELSE
IF (MouseProcOld^.Next = NIL) THEN
BEGIN
bNotFound := True;
bFin := True
END
ELSE
MouseProcOld := MouseProcOld^.Next;
UNTIL bFin;
{ IF bNotFound THEN
ASM
Call hClicNotInArea;
END;}
END;
END;
END;
{ Retourne TRUE lorsque l'utilisateur maintien le bouton xxx enfonc‚ et
renvoi FALSE lorsque ce bouton est relƒch‚. }
FUNCTION Mouse_ReleaseButton (Button : cgMouse_Key) : Boolean; ASSEMBLER;
ASM
Mov Ax, 06h
Mov Bx, 01h
Int 33h
END;
{ Cette proc‚dure va attendre jusqu'… ce que le dernier bouton enfonc‚ ne
le soit plus; autrement dit jusqu'… ce que l'utilisateur relƒche ce mˆme
bouton. Ce qui aura pour effet de vider le buffer de la souris. }
PROCEDURE Mouse_Flush;
BEGIN
IF bMouse_Exist THEN
REPEAT
UNTIL NOT (Mouse_ReleaseButton(cgMouse_LastButton));
END;
{ Initialisation }
BEGIN
{ Initialise le boolean d'existence d'un gestionnaire de souris }
Mouse_Init;
{ Positionne le curseur de la souris en (0,0) }
Mouse_GotoXy (0,0);
END.
[Back to MOUSE SWAG index] [Back to Main SWAG index] [Original]