TURBO PASCAL |
Новости
|
П5. МОДУЛЬ FJMOUSE ДЛЯ РАБОТЫ С МЫШЬЮОписание модуля см. п.4.2. /_=============; UNIT F_Mouse; {=="=========.==} ^——————————————————————————————+ ] В этом модуле собраны процедуры и функции, ¦ ¦ обеспечивающие работу устройства ввода ¦ ¦ типа мышь I +————————————————.—————————————+; INTERFACE {Следующий тип используется для определения элементов, выбираемых мышью (cis.SetMouseOptlon)} type MouseItemType = record X1,Y1,X2,Y2: Integer; {Координаты области) Butt: Word; {Условия вызова} Key : Word {Скан-код клавиши! end; {Тип MouseHandlerType определяет процедуру обработки событий от мыши} type MouseHandlerType = Procedure (Mask,Buttons,X,Y,DX,DY: Integer); {Константы выбора кнопок мыши} const LeftButton =1; (Левая кнопка) RightButton =2; {Правая кнопка} CenterButton =4; {Средняя кнопка} AnyButton =7; {Любая кнопка} (Коэффициенты пересчета виртуальных координат в текстовые) const TextRatioX: Byte = 8; TextRatioY: Byte =8; ^————————————————————————————+ ¦ Инициация мыши ¦ +—————————————————————————————+; Function IsMouse: Boolean; {Возвращает TRUE, если мышь доступна} Function InitMouse: Boolean; (Инициация мыши} Procedure SetMousePage(Page: Byte); {Устанавливает страницу для указателя мыши} Function GetMousePage: Byte; {Возвращает номер страницы с указателем} Procedure SetStepToPixel(Hor,Ver: Integer); Устанавливает чувствительность мыши} Procedure GetStepToPixel(var Hor,Ver: Integer); {Возвращает чувствительность мыши} Procedure SetDoubleSpeed(Speed: Word); {Устанавливает порог удвоения скорости перемещения указателя) Function GetDoubleSpeed: Word; (Возвращает порог удвоения скорости} {+-—————————————————————————+ 1 Координаты I +——————————————————————_——————_+; Function MouseTextCooX(X: Integer): Byte; {Возвращает текстовую координату по заданной виртуальной} Function MouseTextCooYfY: Integer): Byte; {Возвращает текстовую координату по заданной виртуальной} Function MouseGraphCooXfX: Byte): Integer; {Возвращает виртуальную координату по заданной текстовой) Function MouseGraphCooY(Y: Byte): Integer; (Возвращает виртуальную координату по заданной текстовой} Procedure MouseWhereXY(var X,Y: Integer); {Возвращает виртуальные координаты мыши} Procedure MouseGotoXY(X,Y: Integer); (Переводит указатель мыши а новое положение: X,Y - виртуальные координаты} Function MouseWhereX: Byte; {Возвращает горизонтальную текстовую координату} Function MouseWhereY: Byte; {Возвращает вертикальную текстовую координату} Function MouseIn(XI,Y1,X2,Y2: Integer): Boolean; {Возвращает TRUE, если указатель находится в заданном прямоугольнике} /+—————————————————————————————+ I Состояние кнопок ¦ +—————————————————————————————-+/ Function NumButton: Byte; (Возвращает количество кнопок мыши} Procedure GetMouseState(var Butt,X,Y: Integer); ^Возвращает текущее состояние мыши: BUTT - флаг состояния кнопок; X,У - текущие виртуальные координаты} Function MousePressed: Boolean; /Возвращает TRUE, если нажата любая кнопка} Procedure MouseButtPressedtButt: Integer; var Stat,Count,X,Y: Integer); {Возвращает информацию о нажатой клавише: BUTT - флаг выбора клавиши; STAT - состояние клавиш; COUNT - количество нажатий, X,Y - координаты} Procedure MouseButtReleased(Butt: Integer; var Stat,Count,X,Y: Integer); . {Возвращает информацию об отпущенной клавише: BUTT - флаг выбора клавиши; STAT - состояние клавиш; COUNT - количество отпусканий; X,У - координаты} ^+——————————————————————————————+ I Окна 1 +—————————————————————————————+; Procedure MouseWindow(Xl,Yl,X2,Y2; Integer); {Задает координаты области перемещения указателя. XI...Y2 - виртуальные координаты} Procedure MouseScreen; {Устанавливает окно во весь экран} {+— —__-———————————————— ————————— + ¦ Форма указателя I +—————————————————————————————— +} Procedure ShowMouse; {Показать указатель мыши} Procedure HideMouse; {Убрать указатель мыши} Procedure MouseTextCursor(ScrMaslc,CurMask: Word); {Устанавливает новый вид текстового указателя} Procedure MouseBlink(YUp,YDn: Byte); {Задает аппаратный курсор нужного размера} Procedure MouseGraphCursor(var ScrCurMask;X,Y: Byte); {Задает вид графического указателя) ^————„———————————————.———————+ I Сохранение/восстановление состояния 1 +——————————————————————————————+; Function MouseBuffSize: Word; {Возвращает длину буфера для сохранения параметров} Procedure SaveMouse(var Buff); {Сохраняет в буфере текущее состояние мыши) Procedure RestoreMouse (var Buff)-; {Восстанавливает сохраненное состояние мыши} ^+_______———————————————--———————+ I Эмуляция клавиатуры 1 +—————————————————————————————+; Procedure SetMouseltemtNItem: Byte; var Items); (Устанавливает элементы для выбора мышью: NItem - количество элементов; Items - array [1..NItem] of MouseItemType; Старые установки сбрасываются} Procedure AddMouseItemdtem: MouseItemType); {Добавляет еще один элемент для выбора мышью. Старые установки сохраняются} Procedure ClearMouseItems; {Сбрасывает ранее установленные элементы} Procedure GetMouseItemfvar NItem: Byte; var Items); {Возвращает установленные элементы} • Function KeyOrMousePressed: Boolean; (Возвращает TRUE, если нажата клавиша или активна мышь) Function ReadKeyOrMouse: Char; (Возвращает символ нажатой клавиши или выбранной опции! ^+————————————————————————-.——-.——+ I Обработка событий от мыши ¦ +—————————————————————————_— —+) Procedure SetMouseHandler(Mask: Word; Proc: MouseHandlerType); {Устанавливает адрес и условия вызова обработчика} Procedure ChangeMouseHandler(Mask: Word; Proc: MouseHandlerType; var OldMask: Word; var OldProc: Pointer) (Заменяет старый обработчик новым} Procedure ClearMouseHandler; (Удаляет обработчик событий} IMPLEMENTATION ^+.—.———————————————————————————+ I Инициация мыши 1 +————————————————————————————+; Oses DOS,CRT; type Mouseltems - array [1..2*MaxInt dtv SizeOf(MouseItemType)1 of MouseItemType; PMouseIt "^Mouseltems; const MousePresent: Boolean » False; !Признак наличия мыши} ItemsList : PMouseIt " MXIi; {Массив элементов выбора} NMouseItem : Byte = 0; {Количество элементов выбора} MouseVisible: Boolean - Falser {Признак видимого указателя} xlm: Integer = 0; {Координаты области} ylm: Integer = 0; (перемещения указателя} x2m: Integer = 639; y2m: Integer =• 199; Speed2: Word - 128; {Порог удвоения скорости} VerRat: Integer » 8; {Чувствительность мыши} HorRat: Integer =8; KButton: Byte =0; {Количество кнопок мыши} var Reg: registers; Function IsMouse: Boolean; {Возвращает TRUE, если мышь доступна} var p : Pointer; k,x,y: Integer; Is : Boolean; begin if NButton=O then begin GetIntVec($33,p); Is := poiIIL; if Is then with Reg do begin ax := $3; bx :» $FFFF; Intr($33,Reg); Is := bx<>$FFFF end; MousePresent := Is end; IsMouse := MousePresent end; {IsMouse} ^———————_———————; Function InitMouse: Boolean; (Инициация ыьшшл} begin with Reg do begin ax := 0; Intr($33,Reg) ; MousePresent := ax=$FFFF; NButton :" bx end; ClearMouseItems; SetMousePage(0) ; HideMouse; MouseScreen end; {InitMouse} ^———————————————; Procedure SetMousePage(Page: Byte); {Устанавливает страницу для указателя мыши} begin with Reg do begin ax := $1D; Ы := Page; bh := 0; Intr($33,Reg) end end; {SetMousePage} ^___— — ————————„-.—} Function GetMousePage: Byte; {Возвращает номер страницы с указателем} begin with Reg do begin ax :~ $1E; Intr($33,Reg) ; GetMousePage := Ы end end; (GetMousePage} ^———^———————————; Procedure SetStepToPixel(Hor,Ver: Integer); {Ус та на влив ает чувствительность мыши} begin if IsMouse then with Reg do begin ax := $OF; ex := Hor and $7FFF; dx := Ver and $7FFF; HorRat := ex; VerRat := dx; Intr($33,Reg) end end; (SetStepToPixel} Procedure GetStepToPixel(var Hor,Ver: Integer); {Возвращает чувствительность мыши} begin if IsMouse then with Reg do begin Hor := HorRat; Ver := VerRat end end; IGetStepToPixel} /—————————————_--^ Procedure SetDoubleSpeed(Speed: Word); {Устанавливает порог удвоения скорости перемещения указателя} begin if IsMouse then with Reg do begin ax :° $13; dx := Speed; Speed.2 := Speed; Intr($33,Reg) ; end end; ISetDoubleSpped.} _————————————.——; Function GetDoubleSpeed: Word; (Возвращает порог удвоения скорости} begin GetDoubleSpeed := Speed2 end; {GetDoubleSpped} ^_————————————————————__———_____+ I Координаты I +__——_———_————.———_————___——___—+; Function MouseTextCooX(X: Integer): Byte; {Возвращает текстовую координату по заданной виртуальной} begin MouseTextCooX := X div TextRatioX+1 end; {MouseTextCooX} /———————————————; Function MouseTextCooY(У: Integer): Byte; {Возвращает текстовую координату по заданной виртуальной} begin MouseTextCooY :° У div TextRatioY+1 end; {MouseTextCooY} ^_——————————————; Function MouseGraphCooX(X: Byte): Integer; {Возвращает виртуальную координату по заданной текстовой} begin MouseGraphCooX :° (X-1)*TextRatioX end; {MouseGraphCooX} ^___— _—————————_—_ Function MouseGraphCooY(Y: Byte): Integer; {Возвращает виртуальную координату по заданной текстовой} begin MouseGraphCooY := (У-1)*TextRatioY end; {MouseGraphCooY} ^———————————————_ Procedure MouseWhereXY(var X,Y: Integer); /'Возвращает виртуальные координаты мыши) begin if IsMouse then with Reg do begin ax := $3; Intr($33,Reg); X := ex; Y :° dx end else begin X := -1; Y := -1 end end; (MouseWhereXV) ;.- —————————— ————; Procedure MouseGotoXY(X,Y: Integer); {Переводит указатель иыши в новое положение: X,Y - виртуальные координаты} begin if IsMouse then with Reg do begin ax := $4; ex :» X; dx := Y; Intr($33,Reg) end end; {MouseGotoXY} ^———————————————^ Function MouseWhereX: Byte; {Возвращает горизонтальную текстовую координату} begin if IsMouse then with Reg do begin ax := $3; Intr($33,Reg) ; MouseWhereX := MouseTextCooX(ex) end else MouseWhereX := 0 end; {MouseWhereX) /___—————————————_ Function MouseWhereY: Byte; {Возвращает текстовую координату по вертикали} begin if IsMouse then with Reg do begin ax :- $3; Intr($33,Reg) ; MouseWhereY :=- MouseTextCooY(dx) end else MouseWhereY := 0 end; {MoueseWhereY} ^———————————————; Function MouseIn(XI,Y1,X2,Y2: Integer): Boolean; {Возвращает TRUE, если указатель находится в заданном прямоугольнике} begin if IsMouse then with Reg do begin ax :- $3; Intr($33,Reg) ; MouseIn := (cx>=Xl) and (cx<=X2) and (dx>-Yl) and (dx end else Mousein := False end; (Mousein} ^———————————————————.——.——-——...+ ¦ Состояние кнопок ¦ +-——————————————————.————_—_——+; Function NumButton: Byte; /'Возвращает количество кнопок ыыаш) begin NumButton := NButton end; {NumButton} _•——————————————; Procedure GetMouseState(var Butt,X,Y: Integer); {Возвращает текущее состояние мыши: BUTT - флаг состояния кнопок; Х,У - текущие виртуальные координаты/ begin if IsMouse then with Reg do begin ax := $3; Intr($33,Reg) ; Butt := bx; X :=» ex; Y :- dx end else begin Butt := 0; X := 0; Y := 0 end end; {GetMouseState} ^_——————————————/ Function MousePressed: Boolean; {Возвращает TRUE, если нажата любая кнопка} begin if IsMouse then with Reg do begin ax := $3; Intr($33,Reg) ; MousePressed := bxOO end else MousePressed := False end; {MousePressed.) __————.——————————/ Procedure MouseButtPressed(Butt: Integer; var Stat,Count,X,Y: Integer); {Возвращает информацию о нажатой клавише: BUTT - флаг выбора клавиши; STAT - состояние клавиш; COUNT - количество нажатий, X,Y - координаты} begin if IsMouse then with Reg do begin ax := $5; bx :» Butt; Intr($33,Reg) ; Count := bx; X := ex; Y :° dx; Stat := bx end else end; {MouseButtPressed} /———————————————; Procedure MouseButtReleasedfButt: Integer; var Stat,Count»X,Ys Integer); (Возвращает информацию об отпущенной клавише: BUTT - флаг выбора клавиши; STAT - состояние клавиш; COUNT - количество отпусканий; X,Y - координаты} begin if IsMouse then with Reg do begin ax := $6; bx := Butt; Intr($33,Reg) ; Count :«=• bx; X := ex; Y := dx; Stat := bx end else end; (MouseButtReleased.) ^+—————————————————————————————+ I Окна I +———.——.-—————————————————————.^ Procedure MouseWindow(XI,Y1,X2,Y2: Integer); {Задает координаты области перемещения указателя. XI...Y2 - виртуальные координаты} begin if IsMouse then begin xlm := XI; ylm := Yl; x2m •.ss X2; y2m := Y2; with Reg do begin ax » $7 ex = XI dx = X2 Intr($33 Reg) ; ax - $8 ex = Yl dx = Y2 Intr($33,Reg) end end end; {MouseWinciow} ^-.—————————————; Procedure MouseScreen; (Устанавливает окно во весь экран} var х2,у2: Integer; begin if IsMouse then with Reg do begin ah := ?F; Intr($lO,Reg); case al of 1,4,5,13: begin x2 :» 319; y2 := 199 end; 15,16: begin x2 := 639; y2 :» 349 end; 17,18: begin x2 :- 639; y2 := 479 end; else x2 := 639; y2 := 199 end end; MouseWindow(0,0,x2,y2) end; {MouseScreen} ^—————————————————————————————+ I Форма указателя I +—————.———————————————————————+; Procedure ShowMouse; (Показать указатель мыши/ begin if isMouse and not MouseVisible then with Reg do begin ax :- $1; Intr($33,Reg); MouseVisible :» True and end; {ShowMouse} ^—..————————————.^ Procedure HideMouse; {Убрать указатель мыши/ begin if IsMouse and MouseVisible then with Reg do begin ax := $2; Intr($33,Reg); MouseVisible :- False end end; (HideMouse) ^———————————————; Procedure MouseTextCursor(ScrMask,CurMask: Word); (Устанавливает новый вид текстового указателя} begin if IsMouse then with Reg do begin ax := $A; bx :=• 0; ex :» ScrMask; dx := CurMask; Intr($33,Reg) end end; {MouseTextCursor} ^———————————_———_ Procedure MouseBlink(YUp,YDn: Byte); (Задает аппаратный курсор нужного размера} begin if IsMouse then with Reg do begin ax := $A; bx := 1; ex := YOp; dx :- YDn; Intr($33.Reg) end end; {MouseBlink} ^——————————————/ Procedure MouseGraphCursor(var ScrCurMask;X,Y: Byte); (Задает вид графического указателя} begin if IsMouse then with Reg do begin ax := $9; bx :- X; ex :- Y; es :° seg(ScrCurMask); dx := ofs(ScrCurMask); Intr($33,Reg) end end; (MouseGraphCursor} ^-----------——————---------——-——-———+ I Сохранение/восстановление состояния I +-----------—•--——-----———-——------—--—+; Function MouseBuffSize: Word; (Возвращает длину буфера для сохранения параметров) begin if IsMouse then with Reg do begin ax :- $15; bx :•» 0; Intr($33,Reg); MouseBuffSize :- bx end else MouseBuffSize :« 0 end; {MouseBuffSize} ———————————.——-..——; Procedure SaveMouse(vac Buff); (Сохраняет в буфере текущее состояние шдши} begin if IsMouse then with Reg do begin ax :° $X6; es :« seg(Buff); dx :- of s (Buff) ; Intr($33,Reg> end end; (SaveMouse} {., —————————— ————; Procedure RestoreMouse(vac Buff); {Восстанавливает сохраненное состояние мыши} begin if IsMouse then with Reg do begin ax = $17; es = seg(Buff) ; dx •= ofs(Buff) ; Intr($33,Reg) end end; {RestoreMouse} _•+—————————————————————————————+ I Эмуляция клавиатуры I +————————_——.——————.——-_—.————_+; _ const DoubleChars: Boolean = False; var SecChar: Char; Procedure SetMouseItem(NItem: Byte; var Items); {Устанавливает элементы для выбора мышью: NItetti - количество элементов; Items - array [I..NItem] of MouseItemType; Старые установки сбрасываются} begin if IsMouse then begin ClearMouseItems; GetMem(ItemsList,NItem*SizeOf(MouseItemType)); Move (Items, ItemsList^NIten^SizeOftMouseItemType)); NMouseItertt := NItem end end; {SatMouseItem} /——_-——————_————; Procedure AddMouseItemdtem: MouseItemType) ; {Добавляет еще один элемент для выбора мышыэ. Старые установки сохраняются} var р: PMouseIt; k: Byte; begin if IsMouse then begin k := NMouseItem; GetMem(P,(k+1)*SizeOf(MouseItemType)) ; Move(ItemsList",P",k*3ize0f(MouseItemType)); Move(Item,Pл[k+1],SizeOf(MouseItemType)) ; ClearMouseItems; NMouseItem := k+1; ItemsList :° P end end; {AddMouseItem} /——————————— ———} Procedure ClearMouseItems; (Сбрасывает ранее установленные элементы} begin if IsMouse and (NMouseItem <>0) then begin FreeMem(ItemsList,NMouseItem*SizeOf(MouseItemType)); NMouseItem := 0 end end; {ClearMouseItemf ^———————————————; Procedure GetMouseItem(var NItem: Byte; var Items); (Возвращает установленные элементы} begin if IsMouse and (NMouseItemOO) then begin NItem := NMouseItem; Move(ItemsList",Items,NMouseItem*SizeOf(MouseItemType)) end end; {GetMouseItem} ^——————————————_/ Function KeyOrMousePressed: Boolean; {Возвращает TRUE, если нажата клавиша клавиатуры или кнопка ыыши} vac b,k: Integer; MouseActive: Boolean; begin (Сначала проверяем клавиатуру} if KeyPressed then KeyOrMousePressed := True {Если не нажата никакая клавиша/ проверяем нажатие кнопок юани} else with Reg do begin ax :- $3; Intr($33,Reg); if (bx<>0) and (NMouseItemOO) then {Да, кнопка нажата. Организуем цикл проверки по всем элементам} begin MouseActive :» False; for k := 1 to NMouseItem do if not MouseActive then with ItemsList^k] do begin case Butt of LeftButton : b :=bx and LeftButton; RightButton : b :=bx and RightButton; CenterButton: b :-=bx and CenterButton; AnyButton : b :- bx else b :« 0; end; {caaef MouseActive := (b<>0) and MouseIn(MouseGraphCooX<Xl),MouseGraphCooY(YD, MouseGraphCooX(X2),MouseGraphCooY(Y2)) end; /for, if} KeyOrMousePressed := MouseActive end {if (bx<>0) and...} {Если не активна клавиатура яди не выбран элемент, возвращаем False} else {Ьх=0 или NMouseItemOO} KeyOrMousePressed := False end {with Reg} end; {KeyOrMousePressed} ^————.—————————; Function ReadKeyOrMouse: Char; (Возвращает символ нажатой клавиши или выбранного элемента} var k: Byte; b,bb: Word; MouseActive: Boolean; label loop; begin {Сначала проверяем нажатие клавиши} loop: if not IsMouse or KeyPressed then ReadKeyOrMouse :=• ReadKey {Теперь проверим эмуляцию служебной клавиши} else if DoubleChars then begin DoubleChars •." False; ReadKeyOrMouse := SecChar end {Проверяем необходимость контроля элементов экрана для эмуляции клавиатуры! else if NMouseItemoO then with Reg do begin {Да, нужна проверка} MouseActive := False; lКонтролируем выбор мышью одного из элементов} ах := $3; Intr($33,Reg); {Получаем статус кнопок} bb := Ьх; {Запоминаем его в ЪЪ} if bboO then {Если нажата любая кнопка, то организуем проверку всех элементов до нужного (ActiveMouse станет True)} for k := 1 to NMouseItem do if not MouseActive then with ItemsList^Ik] do begin case Butt of LeftButton : b :=№ and LeftButton; RightButton : b :"bb and RightButton; CenterButton: b :=bb and CenterButton; AnyButton : b := bb; else b := 0; end; if (b<>0) and Mouseinf MouseGraphCooX(Xl),MouseGraphCooY(Yl) , MouseGraphCooX(X2),MouseGraphCooY(Y2)) then begin {Найден отмеченный элемент} MouseActive := True; ReadKeyOrMouse := Char(Lo(Key)) ; if Lo(Key)=0 then begin (Эмуляция служебной клавиши} DoubleChars :=• True; SecChar :•» chr(HitKey)) end end end; {for ... if not MouseActive} {Если мышь не отметила элемент, повторяем с начала} if not MouseActive then goto loop end {if NMouseItemoO} {Если не установлен ни один элемент для мыши, ждем нажатия любой клавг1ши} else ReadKeyOrMouse :•' ReadKey end; {ReadKeyOrMouse) _•+—————————————————————————————+ I Обработка событий от мыши I +—_——————————————————————————— +{ coast OldUserProc: Pointer = MIIi; vac UserProc: MouseHandlerType absolute OldCJserProc; OldAX: Word; Procedure MouseHandler; Par; Assembler; {Ассемблерный интерфейс для вызова обработчика} ASM (Сохраняем в стеке регистры} push Ьр push ds push es push ax mov ax,SEG 6 DATA mov ds, ax pop ax mov OldAX,ax {Проверяем условия вызова} mov ax,Word ptr [OldUserProc] fax - сегментадреса/ or ax,Word ptr [OldUserProc+2] (Адрес = NIL?} jz @ {Да - не вызывать} (Готовим вызов процедуры пользователя} mov ах,OldAX push ax {Mask :- ах} push Ьх /Buttons ;« Ьх) push сх (X := сх} push dx {У :- dx} push di {DX :- dl} push si 'DY :» si} {Вызываем процедуру пользователя} call [OserProc] {Выход из процедуры: восстанавливаем регистры} @: pop es pop ds pop bp ret far end; {MouseHandler} /-——_-——————————; Procedure SetMouseHandler(Mask: Word; Proc: MouseHandlerType); {Устанавливает адрес я условия вызова обработчика) begin if IsMouse then with Reg do begin UserProc :~ Proc; ax :- $OC; ex := Mask; es := seg(MouseHandler); dx :- ofs(MouseHandler) ; Intr($33,Reg) end end; {SetMouseHandlet} ^———————————————; Procedure ChangeMouseHandler(Mask: Word; Proc: MouseHandlerType; var OldMask: Word; var OldProc: Pointer); /Заменяет старый обработчик новым} begin if IsMouse then with Reg do begin OldProc := OldUserProc; ax := $14; ex := Masit; ea :» seg(MouseHandler); dx := ofs(MouseHandler); Intr($33,Reg); OldMask := ex end end; {ChangeMouseHandler! ^————————.———————; Procedure ClearMouseHandler; (Удаляет обработчик событий} begin if IsMouse then with Reg do begin ax := $OC; ex := 0; es :=• 0; dx := 0; Intr($33,Reg) end; end; {ClearMouseHandler} ^==»-====»»==; end. {F_Mouse} {—»—==——=-===} |
(с)Все права защищены По всем интересующим вопросам прошу писать на электронный адрес |