Аппаратное обеспечение IBM PC

       

Установить драйвер событий


На входе: 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,&reg,&reg,&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); } } }

Драйвер событий может также организовать очередь событий, записывая в эту очередь состояние мыши на момент появления события и время появления события.

Прикладная программа будет затем извлекать события из очереди и анализировать их.


Содержание раздела