Vous êtes sur la page 1sur 9

Captulo 2.

Programacin del ratn (I).


1.- El Manejador del Ratn
Para comunicarse con el ratn, tenemos que emplear la interrupcin 33h. El nmero de la funcin
deseada se pasa con el registro AX y el resto de los registros se usan para pasar o recibir datos.

Mov ax,0
int 0x33

Esta sera la forma de llamar a la funcin 0 del ratn.

Algunas funciones del interfaz del ratn son las que se encuentran en el siguiente cuadro:

Funcin Uso
00h Resetea el driver del ratn.
01h Dibuja el cursor del ratn en la pantalla.
02h Oculta el cursor del ratn.
03h Devuelve la posicin del cursor y el estado de sus botones.
07h Define la zona horizontal de movimiento para el cursor.
08h Define la zona vertical de movimiento para el cursor.
09h Define el cursor del ratn para los modos grficos.
0Ah Define el cursor del ratn para los modos de texto.
0Fh Fija la velocidad de desplazamiento del cursor.

Tras esta breve exposicin del ratn a nivel hardware, comenzamos con el anlisis de las rutinas que lo
manejan.

La librera que se encarga del ratn se llama "RATON.C", y sus cabeceras estn en "RATON.H", ambos
ficheros incluidos ntegramente al final de esta seccin.

Empecemos por cambiar el cursor del ratn, tarea sencilla para empezar. Slo hay que dibujar un mapa
de bits con la forma que queramos, dibujar tambin su negativo (mscara) y luego traducir esas lneas
de binario a hexadecimal. En el fichero de cabeceras (RATON.H) podemos encontrar la siguiente
declaracin:

int cursor1 [32+32] = { // Flecha

0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, 0x03FF, 0x01FF, 0x00FF, 0x007F, 0x003F, 0x001F, 0x000F,
0x0007, 0x0007, 0xF81F, 0xFC0F, 0xFE0F,

// Mscara

0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7C00, 0x7E00, 0x7F00, 0x7F80, 0x7FC0, 0x7FE0,
0x7FF0, 0x0780, 0x03C0, 0x01E0, 0x0000 };

Y usando el siguiente procedimiento hacemos efectivo el cambio:

Void CambiaPunteroRaton(void)
{
long dir;
int dir2,dir3;
dir=(long)cursor1; dir2=(int)dir; dir3=(int)(dir>>16);
asm{
mov ax,0x9
mov bx,0
mov cx,0
mov dx,dir2
mov es,dir3
int 0x33
}
}

Ntese el uso del Ensamblador dentro del cdigo C, es decir, "Ensamblador Inmerso".

Como se ve, se ha llamado a la interrupcin 33h, al servicio 9h.

Otra funcin y la primera que debemos ejecutar cuando queremos utilizar el ratn es la deteccin del
propio ratn, ya que si ste no est, no podremos usarlo por mucho que programemos los eventos.

El procedimiento que lo hace es el siguiente:

int DetectarRaton(void)
{
int w;
asm{
mov ax,0
mov bx,0x2
int 0x33
mov w,ax
}
return(w);
}

Si DetectarRaton devuelve -1, es que el ratn est presente.

Una vez detectado la presencia del driver del ratn, hay que definir los lmites (en pxels) por los que se
podr mover.

void EstablecerLimRaton(int xi,int yi,int xf,int yf)
{
asm{
mov ax,7
mov cx,xi
mov dx,xf
int 0x33
mov ax,8
mov cx,yi
mov dx,yf
int 0x33
}
}

De esta forma, independientemente de la resolucin de la pantalla, podemos hacer que el ratn slo se
pueda mover por una zona determinada, por un rectngulo que especifican las coordenadas del
procedimiento. Esto es til cuando queremos centrar la atencin del usuario sobre una zona
determinada, no permitindole hacer otra cosa hasta que haya seleccionado algo indispensable para
continuar.

Una vez detectado el ratn y establecido su mbito de movimiento, hay que mostrar la flecha.

void MostrarRaton(void);

Algo que hay que tener en cuenta es que cuando se vaya a hacer un cambio en la pantalla tales como
escribir un texto o una lnea, hay que ocultar el ratn y volverlo a mostrar cuando acabemos, ya que si
n, aparecern incongruencias entre la mscara del ratn y la memoria de vdeo, provocando la
aparicin de rectngulos extraos que estropearn lo que veamos. Esto es debido a que el driver del
ratn continuamente usa una pequea zona de memoria para almacenar lo que haba "debajo" del cursor
antes de que alcanzase la posicin en que ahora se encuentra, de forma que al volverse a desplazar a
otra posicin se "restaura" lo que el cursor estaba "pisando". Por esto, si hacemos un cambio en una
zona en la que se encuentra el cursor, al moverlo restaurar la "antigua" zona que antes estaba, y no la
que ahora debera estar debido al cambio.

Para ocultar el ratn usaremos:

void OcultarRaton(void);

Y jugando con estos dos ltimos procedimientos, escondemos y mostramos el ratn cuando se vayan a
producir los cambios en la pantalla.

Aparte de esto, dos de los ltimos procedimientos que vamos a presentar aqu (aunque hay ms pero
son secundarios), son los que se encargan de hacer esperar a la CPU hasta que se haya pulsado un
botn (en este caso slo se reconocen las pulsaciones de los botones izquierdo y derecho. Si se quisiera
observar tambin el del botn central cuando el ratn disponga de tres, tendra que aadirse una tercera
condicin al "while": (*bot!=4)):

void EsperarPulsadoBoton(int *bot)
{
do { PulsadoBoton(bot); }
while ((*bot!=1)&&(*bot!=2));
}

y de hacerla esperar tambin hasta que se haya soltado ese botn. Los procedimientos son:

void EsperarSoltadoBoton(int bot)
{
int *boton;
do { PulsadoBoton(boton); }
while (*boton==bot);
}

Ambos procedimientos llaman al procedimiento que interacta directamente con el ratn:

void PulsadoBoton(int *bot)
{
int boton;
asm{
mov ax,3
int 0x33
mov boton,bx
}
// Si vale 1 es el izquierdo, si vale 2 es el derecho,si vale 4 el central
*bot=(int)boton;
}

Y por ltimo, el procedimiento que se encarga de leer las coordenadas:

void LeerPosRaton(int *x,int *y)
{
int xx,yy;
asm{
mov ax,3
int 0x33
mov xx,cx
mov yy,dx
}
*x=xx;
*y=yy;
}

Con esto, la exposicin de los procedimientos que se encargan del ratn termina. Por ltimo, usando
estos procedimientos podremos saber cundo el cursor se pulsa sobre una zona que nosotros hemos
decidido que sea "sensible", esto es, un botn, un men, un submen, etc.
RATON.H
// LIBRERIA DEL RATON
#include <dos.h>
// Mascara-dibujo del cursor
int cursor1 [32+32] = {
0x3FFF, 0x1FFF, 0x0FFF, 0x07FF,
0x03FF, 0x01FF, 0x00FF, 0x007F,
0x003F, 0x001F, 0x000F, 0x0007,
0x0007, 0xF81F, 0xFC0F, 0xFE0F,
0x0000, 0x4000, 0x6000, 0x7000,
0x7800, 0x7C00, 0x7E00, 0x7F00,
0x7F80, 0x7FC0, 0x7FE0, 0x7FF0,
0x0780, 0x03C0, 0x01E0, 0x0000 };
// Detecta la existencia del driver del ratn
int DetectarRaton(void);
// Muestra la flecha
void MostrarRaton(void);
// Oculta la flecha
void OcultarRaton(void);
// Establece una zona rectangular de la que el ratn no puede salir
void EstablecerLimRaton(int,int,int,int);
// Pone la flecha en una coordenada
void EstablecerPosRaton(int,int);
// Espera a que se pulse un botn determinado
void EsperarPulsadoBoton(int *);
// Espera a que se suelte el botn determinado
void EsperarSoltadoBoton(int);
// Espera a que se pulse el botn izquierdo
void EsperarPulsadoBotonI(void);
// Espera a que se suelte el botn izquierdo
void EsperarSoltadoBotonI(void);
// Espera a que se pulse el botn derecho
void EsperarPulsadoBotonD(void);
// Espera a que se suelte el botn derecho
void EsperarSoltadoBotonD(void);
// Lee la coordenada del ratn y el estado de los botones
void LeerEstadoRaton(int *,int *,int *);
// Lee slo la coordenada del ratn
void LeerPosRaton(int *,int *);
// Lee slo el estado de los botones
void PulsadoBoton(int *);
// Espera a que se pulse cualquier botn
void EsperarPulsadoCualquierBoton(int *);
// Cambia el puntero
void CambiaPunteroRaton(void);
// Inicializa el driver del ratn
void InicializaRaton(int *,int *,char *);
// Adeca la coordenada del ratn para las BGI de Borland C
void EvitaIncompRaton1(int,int);
// Guarda la coordenada actual y oculta la flecha
void AlejaRaton(int *,int *);
// Deshace el alejamiento del ratn guardando la compatibilidad con las BGI
void AcercaRaton(int,int);

RATON.C
#include "raton.h"
int DetectarRaton(void)
{
int w;
asm{
mov ax,0
mov bx,2
int 0x33
mov w,ax
}
return(w);
}
void MostrarRaton( void )
{
asm{
mov ax,1
int 0x33
}
}
void OcultarRaton( void )
{
asm{
mov ax,2
int 0x33
}
}
void EstablecerLimRaton(int xi,int yi,int xf,int yf)
{
asm{
mov ax,7
mov cx,xi
mov dx,xf
int 0x33
mov ax,8
mov cx,yi
mov dx,yf
int 0x33
}
}
void EstablecerPosRaton(int x,int y)
{
asm{
mov ax,4
mov cx,x
mov dx,y
int 0x33
}
}
void EsperarPulsadoBoton(int *bot)
{
do
{
PulsadoBoton(bot);
}
while ((*bot!=1)&&(*bot!=2));
}
void EsperarSoltadoBoton(int bot)
{
int *boton;
do
{
PulsadoBoton(boton);
}
while (*boton==bot);
}
void EsperarPulsadoBotonI(void)
{
int *bot;
*bot=1;
do
{
PulsadoBoton(bot);
}
while (*bot!=1);
}
void EsperarSoltadoBotonI(void)
{
int *bot;
do
{
PulsadoBoton(bot);
}
while (*bot==1);
}
void EsperarPulsadoBotonD(void)
{
int *bot;
// *bot=2;
do
{
PulsadoBoton(bot);
}
while (*bot!=2);
}
void EsperarSoltadoBotonD(void)
{
int *bot;
do
{
PulsadoBoton(bot);
}
while (*bot==2);
}
void LeerEstadoRaton(int *x,int *y,int *bot)
{
int xx,yy,boton;
asm{
mov ax,3
int 0x33
mov boton,bx
mov xx,cx
mov yy,dx
}
// Si vale 1 es el izquierdo, si vale 2 es el derecho,si vale 4 el central
*x=xx;
*y=yy;
*bot=(int)boton;
}
void LeerPosRaton(int *x,int *y)
{
int xx,yy;
asm{
mov ax,3
int 0x33
mov xx,cx
mov yy,dx
}
*x=xx;
*y=yy;
}
void PulsadoBoton(int *bot)
{
int boton;
asm{
mov ax,3
int 0x33
mov boton,bx
}
// Si vale 1 es el izquierdo, si vale 2 es el derecho,si vale 4 el central
*bot=(int)boton;
}
void EsperarPulsadoCualquierBoton(int *bot)
{
do
{
PulsadoBoton(bot);
}
while ((*bot==2)||(*bot==1));
}
void CambiaPunteroRaton(void)
{
long dir;
int dir2,dir3;
dir=(long)cursor1;
dir2=(int)dir;
dir3=(int)(dir>>16);
asm{
mov ax,9
mov bx,0
mov cx,0
mov dx,dir2
mov es,dir3
int 0x33
}
}
void InicializaRaton(int *posx,int *posy,char *hayraton)
{
*hayraton=DetectarRaton();
if (*hayraton==-1)
{
CambiaPunteroRaton();
EstablecerPosRaton(360,250);
// EstablecerPosRaton(650,490);
MostrarRaton();
LeerPosRaton(posx,posy);
}
}
void EvitaIncompRaton(int posx,int posy)
{
if ((posx!=650)||(posy!=490))
{
EstablecerLimRaton(0,0,630,470);
}
}
void AlejaRaton(int *posx,int *posy)
{
LeerPosRaton(posx,posy);
OcultarRaton();
}
void AcercaRaton(int posx,int posy)
{
EstablecerLimRaton(0,0,650,490);
EstablecerPosRaton(650,490);
MostrarRaton();
EstablecerPosRaton(posx,posy);
EstablecerLimRaton(0,0,630,470);
}

EJEMPLO DE USO
void main(void)
{
int bot;
DetectarRaton();
do
{
sound(700);
// Esperar pulsacin del botn izquierdo
EsperarPulsadoBoton(&bot);
// do
// {
// asm{
// mov ax,3
// int 0x33
// mov bot,bx
// }
// }
// while ((bot!=1)&&(bot!=2));
nosound();
if (bot==1) EsperarSoltadoBotonI();
if (bot==2) EsperarSoltadoBotonD();
}
while (!kbhit());
}