КИТА unofficial
Ноябрь 23, 2024, 03:52:57 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   ПРАВИЛА Помощь WIKI PDA Войти Регистрация  


Страниц: [1]   Вниз
  Печать  
Автор Тема: Подключение "мыши" в С/С++  (Прочитано 10209 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Артем
sprata
Mодератор
Завкаф
*****

Карма: +40/-5
Offline Offline

Пол: Мужской
Сообщений: 1107


« : Май 17, 2008, 07:08:11 »

Думаю, что этот материал может понадобиться некоторым студентам потока ИУС-07, которые собираются делать в 6-ом выче пользовательский интерфейс с подключением "мыши" Улыбка

Основные теоретические сведения

На сегодняшний день на рынке персональных компьютеров имеется большое количество различных типов «мышей». Они отличаются в основном разными способами преобразования физического перемещения «мыши» в последовательность электрических сигналов, передаваемых в компьютер. Для этой цели используются всевозможные колесики, шарики и светоотражающие решетки (дифракционные решетки). Помимо «мыши», имеются также и другие устройства, которые эмулируют «мышь» программными средствами, используя в качестве источника сигналов различные джойстики, шаровые манипуляторы (trackballs), сенсорные подушечки (touch pads) и т. д.

Методика программного управления «мышью»

Для работы по управлению манипулятором прикладная программа выполняет различные функции прерывания 0x3316 (5110). Его обработчик представляет собой коллекцию функций, образующих интерфейс прикладной программы с драйвером манипулятора. Существует набор функций, единый для всех типов драйверов «мыши». Номера функций строго зарезервированы, и меняться по ходу программы не могут. Для вызова необходимой функции её номер задаётся в регистре центрального процессора АХ. Если требуются дополнительные параметры, они помещаются в другие регистры (BX, CX, DX, BL и т. д.) процессора подобным образом. Далее производится запрос на прерывание. В случае, если в результате работы функция возвращает какие либо значения, они также помещаются в регистры центрального процессора.
Одним из способов вызова функции драйвера «мыши» является метод, в котором используются промежуточные переменные, описанные в структуре REGPACK. Структура REGPACK объявлена в заголовочном файле <dos.h> следующим образом:
Код: (cpp)
struct REGPACK
  {
    unsigned r_ax, r_bx, r_cx, r_dx;
    unsigned r_bp, r_si, r_di, r_ds, r_es, r_flags;
  }
Функция, поддерживающая интерфейс для выполнения программных прерываний, которая также описана в файле <dos.h>, выглядит следующим образом:
Код: (cpp)
void intr(int intr_num, struct REGPACK *preg);
Она генерирует прерывание центрального процессора, заданное аргументом intr_num. Перед выполнением прерывания данная функция копирует значения из структуры REGPACK *preg в соответствующие регистры процессора. После завершения прерывания функция intr() переносит содержимое регистров (значения по окончанию прерывания) в структуру preg и они становятся доступны основной программе.

Основные операции для работы с «мышью»

Каждая программа, использующая в своей работе «мышь», должна выполнить ряд операций:
  • определить, работоспособен ли драйвер «мыши»;
  • задать вид и форму курсора манипулятора;
  • описать границы перемещения курсора «мыши» по экрану;
  • описать «чувствительность» курсора;
  • установить порог «удвоенной» скорости курсора «мыши»;
  • «включить» курсор манипулятора - сделать его видимым на экране;
  • задать необходимое положение курсора на экране;
и т. д.
Некоторые из вышеописанных операций могут быть проведены при инициализации, другие могут неоднократно повторяться в ходе работы прикладной программы. Рассмотрим наиболее часто встречающиеся операции и функции драйвера «мыши», при помощи которых эти операции можно осуществить.

Инициализация

Функция 0 выполняет установку драйвера «мыши» и чтение текущегоего состояния. Для выполнения этой функции в регистр АХ процессора необходимо поместить нулевое значение. Других параметров для работы функции не требуется. Если после выполнения функции в регистре АХ осталось нулевое значение, то при инициализации «мыши» произошла ошибка (проблемы с подключением аппаратной части, либо не загружен драйвер). В противном случае -«мышь» готова к работе, при этом значение в регистре BX позволяет определить режим работы манипулятора. Если BX равно двум, то активны две кнопки «мыши» (режим Microsoft mode), если - трем, то три кнопки (режим Mouse Systems mode). При успешной инициализации «мыши» функция определяет текущий режим экрана, и с учетом этого определяет начальные настройки драйвера манипулятора.

Установки драйвера «мыши» по умолчанию:

  • курсор расположен в центре экрана и «выключен»;
  • чувствительность манипулятора по вертикали равна 2 микки / пиксел, по горизонтали - 1 микки / пиксел (один «микки» обычно равен 1 / 200 части дюйма - величина чувствительности датчика перемещения);
  • порог удвоенной скорости установлен равным 64 микки / с;
  • установлена форма курсора по умолчанию;
  • левая верхняя граница перемещения курсора имеет координату (0,0), а нижняя правая равна максимальным координатам видеорежима.

Позиционирование курсора

При перемещении манипулятора по столу драйвер перемещает курсор «мыши» по экрану без участия программы. Тем не менее, прикладная программа имеет возможность управлять позицией курсора. Для этого используется функция 4, которая устанавливает курсор в позицию, заданную значениями, помещенными в регистры CX (горизонтальная координата) и DX (вертикальная координата). Новые координаты задаются для графического режима в пикселах, для текстового режима - в «виртуальных» пикселах (с учетом текстовой строки и столбца). При этом значения в регистрах CX и DX должны быть в пределах диапазона, установленного для перемещения «мыши». Например, в стандартном текстовом режиме  C80 используется видеоадаптер типа CGA, разрешение которого 640x200 "виртуальных" пикселей. При этом шаг перемещения мыши составляет 8 "виртуальных" пикселей. Таким образом получается 640/8 = 80 знакомест по горизонтали, и 200/8 = 25 знакомест по вертикали. Ниже приведен пример программы (функции) перемещающей курсор «мыши» в точку с координатами x и y.
Код: (cpp)
struct REGPACK ioregs;
void set_cursor_position(int x, int y)
  {
    ioregs.r_ax=4;
    ioregs.r_cx=x;
    ioregs.r_dx=y;
    intr(0x33,&ioregs);
}

Визуализация курсора

Достаточно часто при работе с графикой возникают ситуации, когда необходимо изменить изображение на экране. Все трансформации графической информации на экране следует выполнять с выключенным курсором во избежание непредвиденных ситуаций, так как изменения, проведенные точно под курсором, не будут «известны» драйверу и при перемещении курсора в
новую позицию экрана драйвер восстановит не новое, а прежнее значение видеопамяти.
Чтобы исключить ошибки при выполнении данной операции необходимо перед ее началом «выключить» курсор «мыши» (сделать его невидимым), а после операции вновь визуализировать курсор («включить»). Эти действия выполняют функции 2 и 1 соответственно. Функция 2 делает курсор невидимым на экране. Функция 1 делает курсор видимым. При работе с этими функциями следует помнить, что на каждое «выключение» курсора необходимо выполнить обратную операцию, т. е. визуализировать его, несмотря на то, что курсор может быть невидим на экране, продолжается отслеживание движения «мыши». При каждом переключении режима экрана функция 2 вызывается автоматически. В конце программы в обязательном порядке необходимо вызывать функцию 2 (это позволит вам быть уверенным в том, что ничего лишнего не
останется на экране по завершении работы программы).

Определение местоположения и состояния клавиш «мыши»

Для определения текущего состояния и местоположения курсора «мыши» используются функции 3, 5, 6 и 11. Функция 3 возвращает данные по текущему состоянию клавиш «мыши» и положению курсора на экране. Горизонтальная координата располагается в регистре CX, а вертикальная - в DX. В регистр ВX помещается байт состояния клавиш, в котором бит 0 отвечает за состояние левой клавиши «мыши», бит 1 - за состояние правой клавиши, а бит 2 - за состояние средней клавиши (режим Mouse Systems). Если бит имеет единичное значение, то клавиша была нажата, в противном случае нажатия клавиши не было. Функции 5 и 6 определяют соответственно количество нажатий и отпусканий клавиш «мыши». Для их выполнения необходимо сформировать запрос и поместить его в регистр BX (бит 0 отвечает за левую клавиши «мыши», биты 1 и 2 - за правую и среднюю клавиши соответственно). В результате выполнения в регистре BX появляется информация о числе нажатий (отпусканий) клавиш манипулятора с момента последнего обращения к функциям или с момента инициализации «мыши», если выполняемый запрос - первый. Счетчик числа нажатий может хранить значения в диапазоне от 0 до EFFFh. После вызова функций 5 или 6 значения счетчика обнуляются. Функция 11 возвращает число сигналов микки (минимальных приращений перемещения «мыши», регистрируемых аппаратными средствами), накопленное счетчиком с момента последнего вызова данной функции.

Границы перемещения курсора

Сразу после инициализации экрана областью допустимых перемещений курсора по умолчанию принимается весь экран. Но всегда имеется возможность ограничить перемещение курсора. Для этого программа должна использовать функции 7, 8 и 16 прерывания 0x33. Функции 7 и 8 устанавливают диапазон перемещения курсора по горизонтали и вертикали соответственно. Дополнительной входной информацией для этих функций являются минимальное и максимальное значение координатного диапазона, которые помещаются в регистры CX и DX. Если в момент
вызова функции какая либо координата курсора находилась вне указанного диапазона, курсор перемещается на соответствующую границу. Функция 16 запрещает появление курсора в специальной области.

Форма курсора

Драйвер «мыши» поддерживает работу с тремя разновидностями курсора - жестким (аппаратным) текстовым курсором, мягким (программируемым) текстовым курсором и графическим курсором. Только один курсор может присутствовать на экране в любой момент времени. Наибольший практический интерес представляет графический режим работы видеоадаптера, когда курсор имеет вид некоторого графического объекта, перемещающегося поверх изображения на экране. Этот курсор описывается некоторым блоком, имеющим прямоугольную форму. Когда такой блок перемещается по экрану и взаимодействует с пикселами изображения, находящегося «под» ним, происходит формирование фона и изображения графического курсора. Результат этого взаимодействия определяется содержимым двух массивов, размером 16 на 16 бит каждый, один из которых является маской экрана (AND-маской), другой - маской курсора (XOR-маской).
Маска экрана определяет, какая часть пикселов графического блока курсора будет формировать образ курсора, а какая часть будет фоном курсора. Маска курсора определяет те пикселы, которые будут участвовать в формировании цвета курсора. В таблице представлены варианты возможных сочетаний битов AND-маски и XOR-маски и результат их взаимодействия.

Бит AND-маски     Бит XOR-маски     Результирующий бит

       0                          0                            0
       0                          1                            1
       1                          0                    не изменится
       1                          1                    инвертируется

Для каждой поддерживаемой драйвером функции «мыши» под положением графического курсора на экране подразумевались координаты некоторой точки экрана, находящиеся под блоком курсора и носящие название «горячего пятна» (hot spot) курсора. Обычно (по умолчанию) «горячим пятном» курсора является левый верхний угол графического блока курсора с относительными координатами (0, 0), но по желанию в качестве «горячего пятна» можно выбрать любую другую точку блока. Функция, которая устанавливает цвет, форму и задает координаты «горячего пятна» графического курсора, имеет номер 9. Как уже отмечалось
выше, курсор формируется из графического блока размером 16 на 16 пикселов и определяется двумя массивами 16 на 16 бит каждый. Координаты «горячего пятна» должны находиться в диапазоне от 0 до 16. В этой связи для успешной работы функции необходимо в регистры BX и CX поместить горизонтальную и вертикальную координаты «горячего пятна» курсора, а в регистры ES:DX указатель на массивы масок (16 слов - маска экрана и 16 слов - маска курсора). Каждое слово задает значения 16 пикселов в соответствующем ряду. Младший бит соответствует крайнему правому пикселу.

Пример функции, формирующей другую форму курсора «мыши»
(стрелка из левого нижнего угла в правый верхний), представлен ниже:
Код: (cpp)
struct REGPACK ioregs;

void set_cursor_shape()
  {
    unsigned cursor[2][16];
    unsigned far *fpuns;
    unsigned far **pfpuns;
    ioregs.r_ax=9;
    ioregs.r_bx=15;
    ioregs.r_cx=0;

    cursor[1][0]=0x0001;   
    cursor[1][1]=0x0002;   
    cursor[1][2]=0x000e;   
    cursor[1][3]=0x003c;   
    cursor[1][4]=0x00fc;   
    cursor[1][5]=0x03f8;   
    cursor[1][6]=0x0ff8;   
    cursor[1][7]=0x3ff0;   
    cursor[1][8]=0xfff0;     
    cursor[1][9]=0x3fe0;   
    cursor[1][10]=0x1fe0; 
    cursor[1][11]=0x3fc0; 
    cursor[1][12]=0x78c0; 
    cursor[1][13]=0xf000;   
    cursor[1][14]=0xe000; 
    cursor[1][15]=0xc000;
    cursor[0][0]=0xfffc;
    cursor[0][1]=0xfff8;
    cursor[0][2]=0xffe0;
    cursor[0][3]=0xff81;
    cursor[0][4]=0xfe01;
    cursor[0][5]=0xf803;
    cursor[0][6]=0xe003;
    cursor[0][7]=0x8007;
    cursor[0][8]=0x0007;
    cursor[0][9]=0x800f;
    cursor[0][10]=0xc00f;
    cursor[0][11]=0x801f;
    cursor[0][12]=0x021f;
    cursor[0][13]=0x07ff;
    cursor[0][14]=0x0fff;
    cursor[0][15]=0x1fff;
   
    fpuns=(unsigned far *)cursor;
    pfpuns=&fpuns;
    ioregs.r_es=*((unsigned *)pfpuns+1);
    ioregs.r_dx=*(unsigned *)pfpuns;
    intr(0x33,&ioregs);
  }

Пример подключения драйвера "мыши" и визуализации курсора в текстовом режиме (для графического режима, перед подключением "мыши", просто включите графический режим с помощью ф-ии initgraph):

Код: (cpp)
#include <dos.h>
#include <conio.h>

struct REGPACK ioregs;

void main()
  {
   clrscr();
   
      ioregs.r_ax=0;
      intr(0x33,&ioregs);
      ioregs.r_ax=1;
      intr(0x33,&ioregs);
   
   getch();
   ioregs.r_ax=2;
   intr(0x33,&ioregs);
  }
« Последнее редактирование: Июль 28, 2008, 10:55:06 от artem90 » Записан
Alder
Администратор
Проректор
*****

Карма: +331/-16
Offline Offline

Пол: Мужской
Награды:
За II место в конкурсе поэзии (весна-2007)2 место в фотоконкурсе \За II место в фотоконкурсе \3 место в фотоконкурсе \2 место в фотоконкурсе \Лучший знаток музыки 2009Лучший знаток музыки 2010
Сообщений: 11224


just for fun


WWW
« Ответ #1 : Май 18, 2008, 03:58:22 »

А у меня вот такой файлик admouse.h был написан:
Код: (cpp)
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
union REGS rg;
typedef struct
{unsigned butt;
 unsigned x;
 unsigned y;
} MSTATE;
//инициализация мыши
int minit (int *nbutt)
{
 rg.x.ax=0;
 int86 (0x33,&rg,&rg);
 *nbutt=rg.x.bx;
 return rg.x.ax;
}
//сброс драйвера мыши
void mesc (void)
{
 rg.x.ax=0x0021;
 int86 (0x33,&rg,&rg);
}
//показать курсор мыши
void mshow (void)
{
 rg.x.ax=1;
 int86 (0x33,&rg,&rg);
}
//спрятать указатель мыши
void mhide (void)
{
 rg.x.ax=2;
 int86 (0x33,&rg,&rg);
}
//при нажатии на кнопку вычисляем x,y и какая кнопка нажата
int mquerp (MSTATE *st,int butt)
{
 rg.x.ax = 5;
 rg.x.bx = butt;
 int86(0x33,&rg,&rg);
 st->butt = rg.x.ax;
 st->x    = rg.x.cx/8;
 st->y    = rg.x.dx/8;
 return(rg.x.bx);
}
//определение текущих координат курсора
MSTATE *mquery (MSTATE *st)
{
 rg.x.ax = 3;
 int86(0x33,&rg,&rg);
 st->butt = rg.x.bx;
 st->x    = rg.x.cx/8;
 st->y    = rg.x.dx/8;
 return(st);
}
//установка курсора в тербуемую позицию
void msetcr(int x, int y)
{
 rg.x.ax = 4;
 rg.x.cx = x;
 rg.x.dx = y;
 int86(0x33,&rg,&rg);
}
Записан

"There are things known and there are things unknown, and in between are the doors..." (Jim Morrison)
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Penguins Counter Powered by MySQL Powered by PHP Powered by SMF 1.1.8 | SMF © 2006-2008, Simple Machines LLC Valid XHTML 1.0! Valid CSS! Internetmap
Страница сгенерирована за 0.176 секунд. Запросов: 28.