Управление мышью
В составе штатных поставок систем ТС, ТР и QBasic отсутствуют средства управления мышью, а без этого манипулятора на порядок снижается ценность игровых и диалоговых программ. Непосредственную работу с мышью осуществляет системная программа — драйвер мыши, — загружаемая одновременно с загрузкой операционной системы MS-DOS или входящая в состав Windows. Драйверы мыши, ориентированные на работу с манипуляторами различных конструкций, могут отличаться друг от друга, например по количеству обслуживаемых кнопок. Но в большинстве своем их главные функции одинаковы и наша программа может ими воспользоваться через механизм прерываний.
В состав прерывания 0x33 ($33) входит более 30 подфункций, обеспечивающих связь с драйвером мыши. Наиболее полный их перечень приводится в [16]. Далеко не все эти функции являются предметом первой необходимости. Поэтому познакомимся только с некоторыми из них на примере программы, отслеживающей перемещения мыши по экрану в текстовом режиме. Достаточно полные модули управления мышью вы можете найти в книге В. В. Фаронова "Turbo Pascal 7.0. Практика программирования. Учебное пособие" и в [13].
Подфункция с номером 0 осуществляет "сброс" драйвера. В результате ее работы в регистр АХ заносится состояние мыши и драйвера, а в вх — количество кнопок. Следует отметить, что обращение к этой подфункции в программе, работающей строго под управлением MS-DOS и запущенной из-под Windows 95/98, дает разные результаты. Можно, например, узнать, что на вашей трехкнопочной мыши присутствуют только две кнопки, что мышь или драйвер не установлены (АХ=0). Дело в том, что обращаемся мы к разным драйверам и их ответы не всегда идентичны. Но основные действия по инициализации мыши все драйверы выполняют одинаково. К их числу относятся перевод курсора в центр экрана и его гашение, установка стандартной формы курсора, разрешение перемещать курсор по всему рабочему полю.
Подфункция с номером 1 включает режим отображения позиции курсора. Гашение образа курсора осуществляет подфункция 2, но драйвер продолжает отслеживать перемещения и погашенного курсора.
Наиболее важной является подфункция 3, которая сообщает текущие координаты курсора в пикселах (х=CX, у=DX) и состояние кнопок мыши в момент вызова подфункции (BX=1 — нажата левая кнопка, BX=2 — нажата правая кнопка, BX=4 — нажата средняя кнопка). В принципе, значением вх может быть любая комбинация одновременно нажатых кнопок. В текстовом режиме значения координат однозначно определяются номерами текущей строки (row) и текущего столбца (col):
x=8*(col-l) y=8*(row-l)
В этом вы можете убедиться на примерах следующих программ, построенных по единой схеме. После "сброса" драйвера дается 5-секундная задержка, чтобы рассмотреть текст сообщения о состоянии драйвера и мыши (курсор в это время не виден). Затем включается режим отображения курсора. Далее 60 раз с задержкой в 1 с выполняется цикл, в котором Опрашивается и отображается на экране состояние мыши. Во время этого цикла вы можете перемещать курсор мыши, устанавливая его на пронумерованные позиции строк экрана и зажимая ту или иную кнопку. Координата х при этом меняется от 0 до 632, а координата у — от 0 до 192.
Программа 10_3.bas
' Модификация программы [7], использована первая версия подпрограммы в ' машинных кодах)
DATA &Н60,SH1E,SH0E,SH1F,&НА1,&Н18,SH00,&HCD, &H33,&H89
DATA &H1E,&H1A,&H00,&H89,SH0E,&H1C,&H00,&H89,&H16,&H1E
DATA &H00,&H1F,&H61,&HCB
DIM IntProgd T0 16) AS INTEGER
' установка сегмента для работы подпрограммы DEF
SEG=VARSEG(IntProg(1)}
' установка смещения для работы подпрограммы
Int33&=VARPTR(IntProg(1))
' Перепись подпрограммы из блока данных в массив побайтно
F0R j%=0 T0 23
READ K%: P0KE IntDos&+j%, К% NEXT j%
' Роспись экрана линейками через строку
CLS
C0L0R 7,1
F0R I=1 ТО 11
F0R j%=0 T0 79
PRINT USING "#";j% M0D 10;
NEXT j%
PRINT : PRINT NEXT I COLOR 7,0
IntProg(13)=0: ' Подфункция сброса драйвера мыши
CALL ABSOLUTE(Int33&) LOCATE 2,1
IF IntProg(13)=-1 THEN
PRINT "Работает драйвер MS-DOS ";
PRINT "Число кнопок = ";
IntProg(14);
SLEEP 5
IntProg(13)=1: ' Подфункция визуализации курсора на экране
CALL ABSOLUTE(Int33&)
IntProg(13)=3: ' Подфункция опроса состояния мыши
15:СХ=х
16:DX=y
14:ВХ=состояние кнопок:
' 1 - нажата левая,- 2 - правая, 4 - средняя
FOR j%=l TO 60
CALL ABSOLUTE(Int33&)
LOCATE 4,1
PRINT USING "x=### y=### кнопка #";IntProg(15);IntProg(16);
IntProg(14)
SLEEP 1 NEXT j%
LOCATE 6,1: PRINT "Цикл окончен. Нажмите любую'клавишу"
SLEEP DEE SEG END
Программа 10_3.с
/* Работа с мышью в текстовом режиме */
#include <dos.h>
#include <stdio.h>
#include <conio.h>
void main() (
int i,j;
union REGS r; clrscr () ;
/*Роспись экрана линейками через строку*/
cextcolor (7); textbackground (1) ;
for(1=1; i<12; i++) {
for(j=0; j<80; j++) cprintf("%d", j%10) ;
printf{"\n"); }
r.x.ax=0;
/* подфункция сброса драйвера */
int86(0x33,&r,&r);
textbackground(0);
gotoxy(1,2);
if(r.x.ax==0xFFFF) cprintf("Работает драйвер MS-DOS ");
cprintf("Число кнопок = %d",r.x.bx);
r.x.ax=l; sleep(5);
/* Подфункция визуализации курсора на экране */
int86(0x33,&r,&r); r.x.ax=3;
/* Подфункция опроса состояния мыши*/
for(j=0; j<60; j++) {
int86(0x33,&r,Sr);
gotoxy(1,4);
clreol();
cprintf("x=%d y=%d нажата кнопка %d",r.x.ex,r.x.dx,r.x.bx);
sleep(1); }
gotoxy(1,6);
cprintf("Цикл окончен. 'Нажмите любую клавишу");
getch (); }
Программа 10_3.pas
program intl; uses Crt,Dos;
var
i,j:longint;
r:Registers;
begin
clrscr; {Роспись экрана линейками через строку}
textcolor(7);
textbackground(1);
s
for i:=0 to 10 do
begin
for j:=0 to 79 do
write(j mod 10); writeln;
end;
textbackground(0);
{подфункция сброса драйвера}
r.AX:=0;
Intr($33,r);
gotoxy(l,2);
if r.AX=$FFFF then write('Работает драйвер MS-DOS ');
write('Число кнопок = ',r.ВХ);
r.AX:=l;
{ Подфункция визуализации курсора на экране }
Intr($33,r); r.AX:=3;
{Подфункция опроса состояния мыши}
for j:=1 to 60 do begin
Intr($33,r);
gotoxy(l,4);
clreol;
write('x=',r.CX, ' y=',r.DX, ' кнопка =',r.BX);
for i:=0 to 10000000 do i:=i;
end;
gotoxy(1,6); write('Цикл окончен. Нажмите Enter');
readln;
end.