| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
Как ясно из заголовка, сегодня мы будем писать mouse.h для твоих лабораторных работ на Turbo C/C++.
Если ты работаешь не на PC, можешь сразу закрывать окно с этой статьей - мы работаем только с писюками по прерыванию 33h. С предупреждениями вроде бы все. Пора браться за дело. Сначала рассмотрим само прерывание 33h. Как и у многих других прерываний, связанных с "железом", вызываемая функция зависит от входных параметров (записываются в аккумулятор - AX).
INT33h:
Вход: AX=0000h
Инициализация драйвера мыши. Возвращается статус драйвера.
Если указатель мыши был виден на экране, он исчезает. Все пользовательские установки
(реакция на движение, нажатие кнопок и т.д.) заменяются настройкой "по умолчанию".
Выход:
Если инициализация прошла успешно
AX=FFFFh
BX=число кнопок у мыши
Если использование мыши невозможно
AX=0000h
Вход: AX=0001h
Показывает указатель мыши на экране.
Выход:
Нет
Вход: AX=0002h
Скрывает указатель мыши на экране.
Выход:
Нет
Вход: AX=0003h
Получение координат мыши и статуса кнопок.
Выход:
BX=битовая маска (кнопка нажата, если бит установлен как 1)
0й бит левая кнопка
1й бит правая кнопка
2й бит средняя кнопка
3-15й бит зарезервировано (установлено в 0)
CX=горизонтальная координата
DX=вертикальная координата
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0004h
CX=горизонтальная координата
DX=вертикальная координата
Установка координат указателя мыши.
Выход:
Нет
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0005h
BX=идентификатор кнопки мыши
0 = левая кнопка
1 = правая кнопка
2 = средняя кнопка
Возвращает текущий статус всех кнопок мыши, а также позицию
последнего клика и количество нажатий (с момента последнего вызова этой функции)
выбранной кнопки мыши.
Выход:
AX=битовая маска (кнопка нажата, если бит установлен как 1)
0й бит левая кнопка
1й бит правая кнопка
2й бит средняя кнопка
3-15й бит зарезервировано (установлено в 0)
BX=количество нажатий кнопки
CX=горизонтальная координата последнего клика
DX=вертикальная координата последнего клика
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0006h
BX=идентификатор кнопки мыши
0 = левая кнопка
1 = правая кнопка
2 = средняя кнопка
Возвращает текущий статус всех кнопок мыши, а также позицию последнего отпускания
кнопки и количество отпусканий (с момента последнего вызова этой функции) выбранной
кнопки мыши.
Выход:
AX=битовая маска (кнопка отпущена, если бит установлен как 1)
0й бит левая кнопка
1й бит правая кнопка
2й бит средняя кнопка
3-15й бит зарезервировано (установлено в 0)
BX=количество отпусканий кнопки
CX=горизонтальная координата последнего клика
DX=вертикальная координата последнего клика
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0007h
CX=минимальная горизонтальная координата
DX=максимальная горизонтальная координата
Устанавливает горизонтальные границы для указателя мыши.
Выход:
Нет
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0008h
CX=минимальная вертикальная координата
DX=максимальная вертикальная координата
Устанавливает вертикальные границы для указателя мыши.
Выход:
Нет
ВАЖНО!
Координаты отсчитываются в пикселах от левого верхнего угла.
Вход: AX=0009h
BX=координата "горячей точки" по горизонтали
CX=координата "горячей точки" по вертикали
ES:DX=сегмент:смещение указателя на буфер с изображением курсора
Устанавливает изображение курсора в графическом режиме.
Выход:
Нет
ВАЖНО!
"Горячая точка" - точка указателя мыши, которой производится сам клик.
Координаты "горячей точки" отсчитываются от левого верхнего угла изображения курсора.
Буфер с изображением курсора имеет длину 64 байта. Первые 32 байта содержат битовую маску,
которая поANDена с картинкой экрана, остальные 32 байта - маску, поXORенную с картинкой экрана.
Вход: AX=000Ah
BX=идентификатор курсора
0 = software курсор
1 = hardware курсор
CX=поANDенная маска курсора (при BX=0); стартовая линия для курсора (при BX=1)
DX=поXORенная маска курсора (при BX=0); финишная линия для курсора (при BX=1)
Устанавливает изображение курсора в текстовом режиме.
Выход:
Нет
ВАЖНО!
Если выбрано BX=0, то маска состоит из следующих полей:
0-7й бит код символа
8-10й бит цвет текста
11й бит яркость шрифта
12-14й бит цвет фона
15й бит мерцание
Если выбрано BX=1, то значения из CX и DX являются первой и последней линиями мерцающего
курсора, генерируемого видеоадаптером (максимальное значение зависит от видеоадаптера и
текущего видеорежима).
Вход: AX=000Bh
Возвращает путь указателя мыши (примерно 1/200 дюйма за единицу на счетчике) с момента
последнего вызова этой функции.
Выход:
CX=горизонтальный путь
DX=вертикальный путь
Вход: AX=000Ch
CX=маска событий (событие включено, если установлено в 1)
0й бит движение мыши
1й бит нажатие левой кнопки
2й бит отпускание левой кнопки
3й бит нажатие правой кнопки
4й бит отпускание правой кнопки
5й бит нажатие средней кнопки
6й бит отпускание средней кнопки
7-15й бит зарезервировано (установлено в 0)
ES:DX=сегмент:смещение указателя на процедуру обработки
Устанавливает пользовательские обработчики событий мыши.
Выход:
Нет
ВАЖНО!
Обработчики сбрасываются при вызове функции 00h прерывания 33h.
Вход: AX=000Dh
Включение эмуляции светового пера IBM PC.
Выход:
Нет
ВАЖНО!
Перо считается опущенным на поверхность экрана при нажатии левой и правой кнопок мыши одновременно.
Вход: AX=000Eh
Выключение эмуляции светового пера IBM PC.
Выход:
Нет
Вход: AX=000Fh
CX=горизонтальный коэффициент (по умолчанию 8)
DX=вертикальный коэффициент (по умолчанию 16)
Изменение коэффициентов подсчета пройденного пути (на каждые 8 пикселов по горизонтали или вертикали).
Одна единица равна примерно 1/200 дюйма.
Выход:
Нет
ВАЖНО!
Коэффициент должен лежать в диалазоне от 1 до 32767.
Вход: AX=0010h
CX=левая верхняя X координата
DX=левая верхняя Y координата
SI=правая нижняя X координата
DI=правая нижняя Y координата
Установка региона, где курсор не отображается.
Выход:
Нет
ВАЖНО!
Изменяется другим вызовом этой функции. Сбрасывается при вызове функций 00h и 01h прерывания 33h.
Вход: AX=0013h
DX=скорость мыши в единицах (1/200 дюйма) в секунду
Установка скорости перемещения указателя мыши на экране.
Выход:
Нет
Вход: AX=0014h
CX=маска событий
0й бит движение мыши
1й бит нажатие левой кнопки
2й бит отпускание левой кнопки
3й бит нажатие правой кнопки
4й бит отпускание правой кнопки
5й бит нажатие средней кнопки
6й бит отпускание средней кнопки
7-15й бит зарезервировано (установлено в 0)
ES:DX=сегмент:смещение указателя на процедуру обработки
Устанавливает пользовательские обработчики событий и возвращает маску и адрес обработчика событий.
Выход:
CX=маска событий
0й бит движение мыши
1й бит нажатие левой кнопки
2й бит отпускание левой кнопки
3й бит нажатие правой кнопки
4й бит отпускание правой кнопки
5й бит нажатие средней кнопки
6й бит отпускание средней кнопки
7-15й бит зарезервировано (установлено в 0)
ES:DX=сегмент:смещение указателя на процедуру обработки
Этого, наверное, достаточно на первых порах...
Теперь займемся написанием самой библиотеки (или заголовочного файла) mouse.h
/*
Библиотека для работы с мышью.
Автор: Egyptian Vulture
Все замечания и предложения просьба присылать на vulture@mailgate.ru
Создано специально для проекта GPF (http://gpf.h10.ru)
(c)Egyptian Vulture 2003
*/
//Список глобальных переменных библиотеки
int mouseerror=0;
int numberofbtn=0;
int isleftpressed=0;
int isrightpressed=0;
int iscenterpressed=0;
int isleftreleased=0;
int isrightreleased=0;
int iscenterreleased=0;
int x=0;
int y=0;
int xway=0;
int yway=0;
int lastleftclickx=0;
int lastleftclicky=0;
int lastrightclickx=0;
int lastrightclicky=0;
int lastcenterclickx=0;
int lastcenterclicky=0;
int lastleftreleasex=0;
int lastleftreleasey=0;
int lastrightreleasex=0;
int lastrightreleasey=0;
int lastcenterreleasex=0;
int lastcenterreleasey=0;
unsigned int leftclick=0;
unsigned int rightclick=0;
unsigned int centerclick=0;
unsigned int leftrelease=0;
unsigned int rightrelease=0;
unsigned int centerrelease=0;
void far *lclk,*rclk,*cclk,*lrel,*rrel,*crel,*mmov;
//Константы для назначения обработчиков событий
const L_PRESSED=1;
const L_RELEASED=2;
const R_PRESSED=3;
const R_RELEASED=4;
const C_PRESSED=5;
const C_RELEASED=6;
const M_MOVED=7;
//Инициализация мыши
void resetmouse(){
unsigned int xax,xbx;
asm{
mov AX,0000h;
int 33h;
mov xax,AX;
mov xbx,BX;
}//asm
if (xax==0) mouseerror=1;
numberofbtn=xbx;
}
//Показать указатель мыши
void showmouse(){
asm{
mov AX,0001h;
int 33h;
}//asm
}
//Скрыть указатель мыши
void hidemouse(){
asm{
mov AX,0002h;
int 33h;
}//asm
}
//Чтение статуса мыши
void getmousestatus(){
unsigned int xbx,xcx,xdx;
asm{
mov AX,0003h;
int 33h;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftpressed=xbx%2;
isrightpressed=xbx%4-xbx%2;
iscenterpressed=xbx%8-(xbx%4)*2-xbx%2;
x=xcx;
y=xdx;
}
//Установка координат мыши
void setmousecoords(int xcoord, int ycoord){
asm{
mov AX,0004h;
mov CX,xcoord;
mov DX,ycoord;
int 33h;
}//asm
}
//Статус левой кнопки мыши
void getleftbtnstatus(){
int xax,xbx,xcx,xdx;
asm{
mov AX,0005h;
mov BX,0h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftpressed=xax%2;
isrightpressed=xax%4-xax%2;
iscenterpressed=xax%8-(xax%4)*2-xax%2;
leftclick=xbx;
lastleftclickx=xcx;
lastleftclicky=xdx;
asm{
mov AX,0006h;
mov BX,0h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftreleased=xax%2;
isrightreleased=xax%4-xax%2;
iscenterreleased=xax%8-(xax%4)*2-xax%2;
leftrelease=xbx;
lastleftreleasex=xcx;
lastleftreleasey=xdx;
}
//То же для правой кнопки
void getrightbtnstatus(){
int xax,xbx,xcx,xdx;
asm{
mov AX,0005h;
mov BX,1h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftpressed=xax%2;
isrightpressed=xax%4-xax%2;
iscenterpressed=xax%8-(xax%4)*2-xax%2;
rightclick=xbx;
lastrightclickx=xcx;
lastrightclicky=xdx;
asm{
mov AX,0006h;
mov BX,1h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftreleased=xax%2;
isrightreleased=xax%4-xax%2;
iscenterreleased=xax%8-(xax%4)*2-xax%2;
rightrelease=xbx;
lastrightreleasex=xcx;
lastrightreleasey=xdx;
}
//То же для средней кнопки
void getcenterbtnstatus(){
int xax,xbx,xcx,xdx;
asm{
mov AX,0005h;
mov BX,2h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftpressed=xax%2;
isrightpressed=xax%4-xax%2;
iscenterpressed=xax%8-(xax%4)*2-xax%2;
centerclick=xbx;
lastcenterclickx=xcx;
lastcenterclicky=xdx;
asm{
mov AX,0006h;
mov BX,2h;
int 33h;
mov xax,AX;
mov xbx,BX;
mov xcx,CX;
mov xdx,DX;
}//asm
isleftreleased=xax%2;
isrightreleased=xax%4-xax%2;
iscenterreleased=xax%8-(xax%4)*2-xax%2;
centerrelease=xbx;
lastcenterreleasex=xcx;
lastcenterreleasey=xdx;
}
//Установить горизонтальные границы для курсора
void sethorisontallimits(int minx, int maxx){
asm{
mov AX,0007h;
mov CX,minx;
mov DX,maxx;
int 33h;
}//asm
}
//То же с вертикальными границами
void setverticallimits(int miny, int maxy){
asm{
mov AX,0008h;
mov CX,miny;
mov DX,maxy;
int 33h;
}//asm
}
//Разбираемся с курсором в графическом режиме
void setgraphiccursor(int hotx, int hoty, void far *p){
unsigned int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,0009h;
mov BX,hotx;
mov CX,hoty;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
//Разбираемся с курсором в текстовом режиме - software курсор
void setsofttextcursor(int ANDmask, int XORmask){
asm{
mov AX,000Ah;
mov BX,0h;
mov CX,ANDmask;
mov DX,XORmask;
int 33h;
}//asm
}
//Разбираемся с курсором в текстовом режиме - hardware курсор
void sethardtextcursor(int startline, int endline){
asm{
mov AX,000Ah;
mov BX,1h;
mov CX,startline;
mov DX,endline;
int 33h;
}//asm
}
//Смотрим сколько мышка пробежала
void getmouseway(){
int xcx,xdx;
asm{
mov AX,000Bh;
int 33h;
mov xcx,CX;
mov xdx,DX;
}//asm
xway=xcx;
yway=xdx;
}
//Если мышка двигается - установка события
void onmousemove(void far *p){
unsigned int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,1h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
//Событие - нажали левую кнопку
void onleftpressed(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,2h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
//Событие - отпустили левую кнопку
void onleftreleased(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,4h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
void onrightpressed(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,8h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
void onrightreleased(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,10h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
void oncenterpressed(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,20h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
void oncenterreleased(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,40h;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
//Ставим один обработчик для всех событий
void onallevents(void far *p){
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,7Fh;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
//А теперь - обработка всех событий индивидуальными обработчиками
//Определяем, какой процедурой будем обрабатывать каждое событие
void setallmouseevents(int param, void far *p){
switch (param){
case L_PRESSED: lclk=p; break;
case L_RELEASED: lrel=p; break;
case R_PRESSED: rclk=p; break;
case R_RELEASED: rrel=p; break;
case C_PRESSED: cclk=p; break;
case C_RELEASED: crel=p; break;
case M_MOVED: mmov=p; break;
}//switch
}
//Выполняем процедурки-обработчики событий
void processmouseevents(){
getleftbtnstatus();
if (isleftpressed!=0) {
asm call lclk;
return;
}
if (isleftreleased!=0) {
asm call lrel;
return;
}
getrightbtnstatus();
if (isrightpressed!=0) {
asm call rclk;
return;
}
if (isrightreleased!=0) {
asm call rrel;
return;
}
getcenterbtnstatus();
if (iscenterpressed!=0) {
asm call cclk;
return;
}
if (iscenterreleased!=0) {
asm call crel;
return;
}
asm call mmov;
return;
}
//Устанавливаем мультиобработчик событий
void onallmouseevents(){
void far *p=&processmouseevents;
int xseg,xofs;
xseg=FP_SEG(p);
xofs=FP_OFF(p);
asm{
mov AX,000Ch;
mov CX,7Fh;
mov ES,xseg;
mov DX,xofs;
int 33h;
}//asm
}
Можно написать пустую процедурку void empty(){} для того, чтобы игнорировать ненужные события мультиобработчиком. Заметь, что нужно определить все указатели на части мультиобработчика иначе программа в даун упадет.
Вот и все. Все баги репортируй мне на ящик - vulture@mailgate.ru (а про один баг я уже догадываюсь :).
|
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |