Программирование игр для Windows. Советы профессионала

Мышь


Изобретение мыши, безусловно, было событием в компьютерной истории. Появившись в результате исследований в центре Xerox PARK в Калифорнии, она завоевала сердца миллионов пользователей. Мышь позволила наглядно работать с экраном и легко общаться с интересующими объектами. Обычно мышь подсоединяется к последовательному порту компьютера или DIN коннектору на лаптопе. Существующая bus mice

требует специальной платы, поэтому не получила широкого распространения (это понятно — мало кто хочет просто так вскрывать свой компьютер для установки одной платы).

На сегодняшний день существуют как механические, так и оптические мыши. В обоих случаях перемещение мыши кодируется в последовательность импульсов, которая преобразуется в пакет, содержащий информацию о движении мыши и состоянии кнопок. Этот пакет посылается в серийный порт, к которому подсоединяется мышь, а затем интерпретируется программой.

Вообще-то, написание драйвера мыши — не самое скучное занятие, но мы этого делать не будем. К счастью, Microsoft и другие фирмы написали кучу подобных драйверов. Поэтому мы не станем самостоятельно декодировать мышиные пакеты, а воспользуемся более удобным программным интерфейсом.

Мы будем использовать только минимум функций для определения позиции мыши и статуса кнопок. В таблице 3.3 перечислены эти функции.

Замечание

Микки (mickey) — это самое маленькое расстояние, которое отслеживается мышью. Оно примерно равно 1/200 дюйма.

Таблица 3.3. Функции драйвера мыши.

Bios INT 33h

Функция 00h - инициализировать драйвер мыши

Вход:     AX:         0000h

Выход: AX:         FFFFh в случае успеха,

0000h при неудаче



ВХ - количество кнопок мыши

Функция 01h

- включить курсор мыши

Вход:  AX: 0001h

Выход: Ничего

Функция 02h - выключить курсор мыши

Вход:   AX: 0002h

Выход: Ничего

Функция 03h - возвратить позицию курсора и статус клавиш

Вход:   АХ:000Зh

Выход: ВХ - статус кнопок

Бит 0 - левая кнопка: 1 - нажата, 0 - не нажата

Бит 1 - правая кнопка: 1 - нажата, 0 - не нажата




Бит 2 - центральная кнопка: 1 - нажата, 0 - не нажата

СХ -  Х-координата курсора

DX - Y-координата курсора

Функция 0Bh - возвратить относительную позицию мыши

Вход:     AX: 000Bh

Выход:  СХ - относительное горизонтальное движение в mickey

DX - относительное вертикальное движение в mickey

Функция 1Ah - установить чувствительность

Вход: AX: 00lAh

Выход: ВХ - чувствительность по оси Х (0-100)

СХ - чувствительность по оси Y (0-100)

DX - значение скорости, при которой чувствительность возрастает в 2 раза (0-100)

Как видите, функции драйвера вызываются через прерывание 33h. Мы записываем параметр в регистр АХ .и получаем результат в регистрах АХ, ВХ, СХ и DX. Я написал простую функцию для работы с мышью, она называется Squeeze_Mouse(). Эта функция может выполнять много действий — все зависит от передаваемых параметров. Прототип функции:

int Squeeze_Mouse(int command, int *x, int *y, int *buttons) ;

Кроме этого, я сделал несколько описаний, чтобы упростить работу с ней:

#define MOUSE_INT             0х33 // номер

прерывания

#define MOUSE_RESET           0х00 // сброс

мыши

#define MOUSE_SHOW            0х01 // показать

мышь

#define MOUSE_HIDE            0х02 // погасить

мышь

#define MOUSE BUTT_POS        0х03 // возвратить координаты

//и количество кнопок

#define MOUSE_SET_SENSITIVITY 0x1A // установить

//чувствительность

//в пределах 0-100

#define MOUSE_MOTION_REL      0x0B // установить

// относительную

// чувствительность

Таким образом, если мы хотим получить координаты мыши, то должны написать следующее:

Squeeze Mouse(MOUSE_BUTT_POS, &mouse_x, &mouse_y, &mouse_buttons);

где mouse_x, mouse_y и mouse_buttons - локальные переменные для сохранения результатов.

Теперь обратим внимание на два способа, используемые для передачи координат мыши:

§          Драйвер мыши может возвращать абсолютные координаты. В этом случае значения Х и Y являются координатами мыши на экране.


К примеру, если мышь находится в левом верхнем углу экрана, функция возвращает (0,0);

§          Драйвер мыши может возвращать относительные координаты. При этом возвращается разница координат от предыдущей посылки. Например, если мышь подвинулась на 20 микки по оси Х и на 10 по оси Y, то эти значения и будут возвращены. Для чтения в относительном режиме используйте константу MOUSE_MOTION_REL.

Еще несколько слов о мыши. Вы можете менять ее чувствительность к передвижению, используя константу MOUSE_SET_SENSITIVITY. Для этого подберите для переменных Х и Y значение от 1 до 100 и вызовите Squeeze_Mouse. Чувствительность мыши определяется как отношение пиксельного перемещения курсора мыши к одному микки.

Листинг 3.8 содержит демонстрационную программу, которая показывает использование мыши. Эта программа позволяет рисовать на экране, нажимая на левую кнопку мыши и менять цвет, используя правую кнопку.

Листинг 3.8. Работа с мышью (MOUSE.C).

// ВКЛЮЧАЕМЫЕ ФАЙЛЫ ///////////////////////////////////////

#include <dos.h>

#include <bios.h>

#include <stdio.h>

#include <math.h>

#include <conio.h>

#include <graph.h>

// ОПРЕДЕЛЕНИЯ ///////////////////////////////////////////

// вызовы функций мыши

#define MOUSE_INT             0х33 // Номер прерывания мыши

#define MOUSE_RESET           0х00 // Инициализация драйвера

#define MOUSE_SHOW            0х01 // Показать курсор мыши

#define MOUSE_HIDE            0х02 // Спрятать курсор мыши

#define MOUSE_BUTT_POS        0х03 // Получение полного статуса

#define MOUSE_SET_SENSITIVITY Ox1A // Установка

чувствительности

#define MOUSE_MOTION_REL      ОхОВ // Получить значение счетчика

     // микки

#define MOUSE_LEFT_BUTTON     0х01 // левая

кнопка

#define MOUSE_RIGHT_BUTTON    0х02 // правая

кнопка

#define MOUSE_CENTER_BUTTON   0х04 // средняя

кнопка

// ФУНКЦИИ ////////////////////////////////////////////////

int Squeeze_Mouse(int command, int *x, int *y,int *buttons)



{

// Мы будем использовать _int86 вместо встроенного ассемблера

// Почему? И сам не знаю

union _REGS inregs, outregs;

switch(command) {

case MOUSE_RESET:

{

inregs.x.ax = 0х00; // подфункция 0 – инициализация

_int86(MOUSE_INT, &inregs, &outregs};

*buttons = outregs.x.bx; // возвратить количество кнопок

return(outregs.x.ax);    // возвратить общий результат

} break;

case MOUSE_SHOW:

     {

// эта функция инкрементирует счетчик драйвера. Когда значение

// счетчика становится больше или равно 0, курсор появляется

// на экране

inregs.х.ах = 0х01; // подфункция 1 - показать курсор

_int86(MOUSE_INT, &inregs, &outregs);

return (1);

} break;

case MOUSE_HIDE:

{

// эта функция декрементирует счетчик драйвера; когда его

// значение становится меньше 0, курсор исчезает с экрана

inregs.х.ах = 0х02; // подфункция 2 - спрятать курсор

_int86(MOUSE_INT, &inregs, &outregs);

return(1);

} break;

case MOUSE_BUTT_POS:

{

// эта функция  позволяет получить полный статус состояния мыши,

// включая абсолютную позицию курсора в координатах (х,у) и

// состояние кнопок

inregs.х.ах = 0х03; // подфункция 3 - получить статус мыши

_int86(MOUSE_INT, &inregs, &outregs);

// извлечь информацию и вернуть ее через указатели

*х       = outregs.х.сх;

*у       = outregs.x.dx;

*buttons = outregs.x.bx;

return(1);

} break;

case MOUSE_MOTION_REL:

{

// эта функция позволяет получить относительное изменение

// координат мыши с момента последнего вызова

inregs.х.ах = 0х03; // подфункция 1 – получить

  // относительную позицию

_int86(MOUSE_INT, &inregs, &outregs);

// результат при помощи указателей помещается в переменные х и у

*х       = outregs.x.cx;

*у       = outregs.x.dx;

return(1);

} break;

case MOUSE_SET_SENSITIVITY:

{

// эта функция устанавливает чувствительность мыши. Перед

// вызовом необходимо установить переменные х и у в значения

// из диапазона 1-100. Переменная "buttons" используется для

// установки значения порога удвоения скорости



// (из диапазона 1-100)

inregs.x.bx = *х;

inregs.x.cx = *у;

inregs.x.dx = *buttons;

inregs.x.ax = 0x1A; // подфункция 26 - установка

  //  чувствительности

_int86(MOUSE INT, &inregs, &outregs);

return(1);

} break;

default:break;

} // конец оператора switch

} // конец функции

// ОСНОВНАЯ ПРОГРАММА /////////////////////////////////////////////////////////////////////////////

void main(void)

{

int x,y,buttons,num_buttons;

int color=l;

_setvideomode(_VRES16COLOR};  // 640х480, 16 цветов

// инициализация драйвера мыши

Squeeze_Mouse(MOUSE_RESET,NULL,NULL,&num_buttons);

//показать

курсор

Squeeze_Mouse(MOUSE_SHOW,NULL,NULL,NULL);

while(!kbhit())

{

_settextposition(2,0);

Squeeze_Mouse(MOUSE_BUTT_POS,&x,&у,&buttons);

printf("mouse x=%d y=%d buttons=%d    ",х,у,buttons) ;

// рисование

if (buttons==1)

{

_setcolor(color) ;

_setpixel(x-1,y-2);

_setpixel(х,y-2) ;

_setpixel(x-1,y-1);

_setpixel(х,y-1);

} // конец обработки нажатия левой кнопки

// выбор

цвета

if (buttons==2)

{

if (++color>15) color=0;

// ждем отпускания правой кнопки

while(buttons==2)

{

Squeeze_Mouse(MOUSE_BUTT_POS,&x,&y,&buttons) ;

} // конец ожидания

} // конец графической работы

} // конец цикла while

// назад в текстовый режим

_setvideomode(_DEFAULTMODE);

} // конец функции main


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