Практика программирования (Бейсик, Си, Паскаль)

       

Управление мышью


В составе штатных поставок систем ТС, ТР и 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.




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