[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]