Установить драйвер событий
На входе: AX = 000Ch;
CX = маска вызова: бит 0 - вызов при перемещении мыши; бит 1 - вызов при нажатии левой клавиши; бит 2 - вызов при отпускании левой клавиши; бит 3 - вызов при нажатии правой клавиши; бит 4 - вызов при отпускании правой клавиши; бит 5 - вызов при нажатии средней клавиши; бит 6 - вызов при отпускании средней клавиши; 7Fh - вызов при любом событии; 00h - отключение драйвера событий;
ES:DX = адрес (дальний) подключаемого драйвера событий.
На выходе: Регистры не используются.
Функция позволяет программе создать свой собственный драйвер (обработчик) событий, связанных с перемещением мыши и нажатием/отпусканием клавиш мыши.
Адрес подготовленной программы-драйвера передается при вызове функции в регистровой паре ES:DX. Драйвер должен быть оформлен в виде дальней процедуры, завершающейся командой дальнего возврата RETF. Когда драйвер получает управление, в регистрах процессора содержатся следующие значения:
AX Маска вызова, такая же, как и при вызове функции0Ch.
BX Состояние клавиш мыши:
бит 0 - левая клавиша; бит 1 - правая клавиша; бит 2 - средняя клавиша.
CX Горизонтальная координата курсора мыши.
DX Вертикальная координата курсора мыши.
SI Относительное перемещение мыши по горизонтали в миках.
DI Относительное перемещение мыши по вертикали в миках.
DS Сегмент данных драйвера мыши.
Так как регистр DS при вызове драйвера событий содержит сегмент данных драйвера мыши, ваш драйвер событий должен позаботиться о правильной установке этого регистра. Ваш драйвер событий не обязан сохранять и восстанавливать содержимое регистра DS и других регистров процессора.
Отметим, что если вам необходимо отключить драйвер, выполните повторный вызов функции 0Ch, записав в регистр CX нулевое значение. Если ваша программа, устанавливающая собственный драйвер событий, завершает свою работу и передает управление MS-DOS, предварительно она обязательно должна отключить драйвер событий.
Приведем функцию, которую мы разработали для подключения драйвера событий:
/** *.Name ms_seth *.Title Установка драйвера событий * *. Descr Эта функция выполняет установку драйвера событий. * *.Proto void ms_seth(int mask, void (far *hand)()) * *.Params int mask - маска событий; * void (far *hand)() - адрес драйвера событий * *.Return Ничего * *.Sample ms_samp8.c **/
#include <dos.h> #include <conio.h>
union REGS reg; struct SREGS segregs;
void ms_seth(int mask, void (far *hand)()) {
reg.x.ax = 0x14; reg.x.cx = mask; reg.x.dx = FP_OFF(hand); segregs.es = FP_SEG(hand);
int86x(0x33,®,®,&segregs);
}
Составление программы драйвера событий имеет некоторые особенности. Драйвер событий вызывается не из программы пользователя, а из драйвера мыши. При этом сегментный регистр DS будет указывать на сегмент данных драйвера мыши, а не на сегмент данных вашей программы.
Мы подготовили образец драйвера событий, использовав язык ассемблера:
;** ;.Name ms_handl ;.Title Драйвер событий ; ;.Descr Драйвер событий вызывается драйвером мыши, ; когда происходит какое-нибудь событие из числа ; заданных при установке драйвера событий. ; Функция не должна вызываться из программы ; пользователя, ее вызывает только драйвер мыши. ; ;.Proto void far ms_handl(void); ; ;.Params Не используются ; ;.Return Ничего ; ;.Sample ms_samp8.c ;**
DOSSEG DGROUP GROUP _DATA
_DATA SEGMENT WORD PUBLIC 'DATA' _DATA ENDS
_TEXT SEGMENT WORD PUBLIC 'CODE' ASSUME cs:_TEXT, ds:DGROUP, ss:DGROUP
; Флаг вызова драйвера событий
extrn _ms_flag:word
; Внешние переменные для записи содержимого регистров
extrn _ms_bx:word extrn _ms_cx:word extrn _ms_dx:word extrn _ms_si:word extrn _ms_di:word extrn _ms_ds:word
public _ms_handl
_ms_handl proc far
mov _ms_ds, ds
; Так как на входе в драйвер событий регистр DS указывает на ; сегмент данных драйвера мыши, устанавливаем его на сегмент ; данных программы;
push ax mov ax, DGROUP mov ds, ax pop ax
mov _ms_bx, bx mov _ms_cx, cx mov _ms_dx, dx mov _ms_si, si mov _ms_di, di
; Устанавливаем флаг вызова драйвера в 1, сигнализируя ; программе о том, что произошло событие.
mov _ms_flag, 1
ret
_ms_handl endp
_TEXT ENDS
END
Этот драйвер при вызове устанавливает глобальную переменную _ms_flag в единицу, затем переписывает содержимое всех нужных регистров в соответствующие глобальные переменные. Программа, установив драйвер событий и сбросив флаг _ms_flag, может выполнять какие-либо действия (например, вывод на экран движущегося изображения), постоянно проверяя флаг _ms_flag. Как только произойдет какое-либо событие (нажатие или отпускание клавиши мыши, перемещение мыши) драйвер событий установит флаг в единицу. Программа при этом может узнать состояние мыши, прочитав содержимое глобальных переменных _ms_bx, _ms_dx, и т.д.
Этот простейший вариант использования драйвера событий иллюстрируется следующей программой:
#include <dos.h> #include <stdio.h> #include <conio.h> #include "sysp.h"
extern void far ms_handl(void);
// Флаг драйвера событий. При вызове драйвер событий // запишет в эту переменную значение 1.
unsigned ms_flag;
// Область для содержимого регистров на входе // в драйвер событий.
unsigned ms_bx; unsigned ms_cx; unsigned ms_dx; unsigned ms_si; unsigned ms_di; unsigned ms_ds;
int botm;
main () {
ms_flag=0; // Инициализируем мышь, определяем количество клавиш
if(!ms_init(&botm)) { printf("\nМышь не установлена"); exit(-1); }
// Подключаем драйвер событий, устанавливаем маску таким образом, // чтобы драйвер вызывался при нажатии на левую или правую // клавиши мыши.
ms_seth(2 | 8, ms_handl);
// Включаем курсор
ms_on();
// Ожидаем вызова драйвера событий.
for(;;) { if(ms_flag) { ms_off();
printf("\nСостояние регистров " "на входе драйвера:" "\nms_bx: %0X" "\nms_cx: %0X" "\nms_dx: %0X" "\nms_si: %0X" "\nms_di: %0X" "\nms_ds: %0X", ms_bx, ms_cx, ms_dx, ms_si, ms_di, ms_ds);
printf("\nНажмите любую клавишу..."); getch(); exit(0); } } }
Драйвер событий может также организовать очередь событий, записывая в эту очередь состояние мыши на момент появления события и время появления события.
Прикладная программа будет затем извлекать события из очереди и анализировать их.