|
|
Artículo realizado por
Para comunicarse con el ratón, tenemos que emplear la interrupción
33h. El número de la función deseada se pasa con el registro
AX y el resto de los registros se usan para pasar o recibir datos.
mov ax,0
Esta sería la forma de llamar a la función 0 del ratón.
Algunas funciones del interfaz del ratón son las que se encuentran
en el siguiente cuadro:
José Antonio Suárez.
Capítulo 2.
Programación del ratón (I).
1.- El Manejador del Ratón
int 0x33
Función | Uso |
00h | Resetea el driver del ratón. |
01h | Dibuja el cursor del ratón en la pantalla. |
02h | Oculta el cursor del ratón. |
03h | Devuelve la posición 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 ratón para los modos gráficos. |
0Ah | Define el cursor del ratón para los modos de texto. |
0Fh | Fija la velocidad de desplazamiento del cursor. |
Tras esta breve exposición del ratón a nivel hardware, comenzamos con el análisis de las rutinas que lo manejan.
La librería que se encarga del ratón se llama "RATON.C", y sus cabeceras están en "RATON.H", ambos ficheros incluidos íntegramente al final de esta sección.
Empecemos por cambiar el cursor del ratón, tarea sencilla para empezar. Sólo hay que dibujar un mapa de bits con la forma que queramos, dibujar también su negativo (máscara) y luego traducir esas líneas de binario a hexadecimal. En el fichero de cabeceras (RATON.H) podemos encontrar la siguiente declaración:
int cursor1 [32+32] = { // Flecha
0x3FFF, 0x1FFF, 0x0FFF, 0x07FF, 0x03FF, 0x01FF, 0x00FF, 0x007F, 0x003F, 0x001F, 0x000F, 0x0007,
0x0007, 0xF81F, 0xFC0F, 0xFE0F,
// Máscara
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
}
}
Nótese el uso del Ensamblador dentro del código C, es decir, "Ensamblador Inmerso".
Como se ve, se ha llamado a la interrupción 33h, al servicio 9h.
Otra función y la primera que debemos ejecutar cuando queremos utilizar el ratón es la detección del propio ratón, 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 ratón está presente.
Una vez detectado la presencia del driver del ratón, hay que definir los límites (en píxels) 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 resolución de la pantalla, podemos hacer que el ratón sólo se pueda mover por una zona determinada, por un rectángulo que especifican las coordenadas del procedimiento. Esto es útil cuando queremos centrar la atención del usuario sobre una zona determinada, no permitiéndole hacer otra cosa hasta que haya seleccionado algo indispensable para continuar.
Una vez detectado el ratón 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 línea, hay que ocultar el ratón y volverlo a mostrar cuando acabemos, ya que si nó, aparecerán incongruencias entre la máscara del ratón y la memoria de vídeo, provocando la aparición de rectángulos extraños que estropearán lo que veamos. Esto es debido a que el driver del ratón continuamente usa una pequeña zona de memoria para almacenar lo que había "debajo" del cursor antes de que alcanzase la posición en que ahora se encuentra, de forma que al volverse a desplazar a otra posición 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 debería estar debido al cambio.
Para ocultar el ratón usaremos:
void OcultarRaton(void);
Y jugando con estos dos últimos procedimientos, escondemos y mostramos el ratón 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 más pero son secundarios), son los que se encargan de hacer esperar a la CPU hasta que se haya pulsado un botón (en este caso sólo se reconocen las pulsaciones de los botones izquierdo y derecho. Si se quisiera observar también el del botón central cuando el ratón disponga de tres, tendría que añadirse una tercera condición al "while": (*bot!=4)):
void EsperarPulsadoBoton(int *bot)
{
do { PulsadoBoton(bot); }
while ((*bot!=1)&&(*bot!=2));
}
y de hacerla esperar también hasta que se haya soltado ese botón. Los procedimientos son:
void EsperarSoltadoBoton(int bot)
{
int *boton;
do { PulsadoBoton(boton); }
while (*boton==bot);
}
Ambos procedimientos llaman al procedimiento que interactúa directamente con el ratón:
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 exposición de los procedimientos que se encargan
del ratón termina. Por último, usando estos procedimientos
podremos saber cuándo el cursor se pulsa sobre una zona que nosotros
hemos decidido que sea "sensible", esto es, un botón, un menú,
un submenú, etc.
|
|