{ С.В.Мизрохи TURBO PASCAL и об'ектно-ориентированное программирование. } { Глава 20, стр. 123-135. } {$R-,S-} Unit Mouse; Interface Uses Dos; Const {----- Маски кнопок -----} Left_b = $0001; Right_b = $0002; Center_b = $0004; {----- Маски для задания параметра call_mask -----} Pos_changed = $0001; Left_Press = $0002; Left_Release = $0004; Right_Press = $0008; Right_Release = $0010; Center_Press = $0020; Center_Release = $0040; Function Ms_Init(Var nButtons : Integer) : Boolean; Function Ms_In : Boolean; Procedure Ms_Show; Procedure Ms_Hide; Procedure Ms_Read(Var x, y, b_mask : Word); Procedure Ms_Read_Motion(Var hCount, vCount : Word); Procedure Ms_Set_Pos(x, y : Word); Procedure Ms_lightpen_On; Procedure Ms_lightpen_Off; Function Ms_Get_b( b_Mask : Word; Var count : Word; Var last_x, last_y : Word) : Word; Function Ms_Get_b_Release( b_Mask : Word; Var count : Word; Var last_x, last_y : Word) : Word; Procedure Ms_Set_hMinMax(Min, Max : Word); Procedure Ms_Set_vMinMax(Min, Max : Word); Procedure Ms_Set_GraphPointer(hotx, hoty : Word; Var image); Procedure Ms_Set_TextPointer(select : Word; char_attr_StLine : Word; char_attr_EndLine : Word); Procedure Ms_Set_MPP(hMPP, vMPP : Word); Procedure Ms_Cond_Off(Top, Left, Bottom, Right : Word); Procedure Ms_Set_2speed(MPS : Word); Procedure Ms_Set_Routine(call_mask : Word; sub : Pointer); Procedure Ms_Swap_Routine( call_mask : Word; sub : Pointer; Var last_call_mask : Word; Var last_sub : Pointer); Function Ms_Get_State_bfsz : Word; Procedure Ms_Get_State(Var Ms_State); Procedure Ms_Set_State(Var Ms_State); Procedure Ms_Set_V_Page(Ms_V_page : Word); Function Ms_Get_V_page : Word; Implementation Const Ms_Call = $33; {----- Номер прерывания -----} Var Reg : Registers; { Ms_Init True - если драйвер установлен False - если драйвер не установлен nButtons содержит число кнопок на "мыши" Параметры драйвера после инициализации позиция : центр экрана индикатор видимости : -1 (курсор не виден) графический курсор : стрелка текстовый курсор : инвертированный цвет маска прерывания : 0, программа пользователя не используется эмуляция светового пера : включено масштаб по горизонтали : 8:8 масштаб по вертикали : 16:8 диапазон координат : зависит от видеорежима} Function Ms_Init(Var nButtons : Integer) : Boolean; Begin Reg.AX := 0; Intr(Ms_Call, Reg); IF Reg.AX = 0 Then Begin nButtons := 0; Ms_Init := False; End Else Begin nButtons := Reg.BX; Ms_Init := True; End; End; {----- Ms_Init -----} Function Ms_In : Boolean; Begin Reg.AX := 0; Intr(Ms_Call, Reg); IF Reg.AX = 0 Then Ms_In := False Else Ms_In := True; End; {----- Ms_Init -----} { Ms_Show Сделать курсор видимым. Если курсор уже был видимым, то ничего не происходит. Примечание. В теории на каждый Ms_Show должен быть выдан свой Ms_Hide (Ms_Show увеличивает внутренний счетчик на 1. Пока значение счетчика положительно, курсор виден на экране. Значение счетчика уменьшается при вызове Ms_Hide. Но, например, для драйвера Microsoft Mouse 6.10Z это не выполняется. Для него любой Ms_Hide выключает курсор.)} Procedure Ms_Show; Begin Reg.AX := 1; Intr(Ms_Call, Reg); End; {----- Ms_Show -----} { Ms_Hide Сделать курсор невидимым. См. примечание для предыдущей функции. } Procedure Ms_Hide; Begin Reg.AX := 2; Intr(Ms_Call, Reg); End; {----- Ms_Hide -----} { Ms_Read Возващает текущие координаты "мыши" и состояние кнопок. Если нажаты кнопки, то в b_mask биты показывают bit 0 = Левая кнопка bit 1 = Правая кнопка bit 2 = Центральная кнопка (если их 3)} Procedure Ms_Read(Var x, y, b_mask : Word); Begin Reg.AX := 3; Intr(Ms_Call, Reg); x := Reg.CX; y := Reg.DX; b_mask := Reg.BX; End; {----- Ms_Read -----} { Ms_Set_Pos Устанавливает позицию "мыши". x, y усекаются до допустимых значений. Допустимые значения зависят от видеорежима. } Procedure Ms_Set_Pos(x, y : Word); Begin Reg.AX := 4; Reg.CX := x; Reg.DX := y; Intr(Ms_Call, Reg); End; {----- Ms_Set_Pos -----} { Ms_Get_b Возвращает текущее состояние кнопок на "мыши". Count - содержит количество нажатий интересующей кнопки (задается битом в b_mask) после предыдущего обращения к этой функции. После этого обращения счетчик нажатий обнуляется. last_x, last_y - координаты "мыши" в момент последнего нажатия требуемой кнопки. } Function Ms_Get_b( b_mask : Word; Var count, last_x, last_y : Word) : Word; Begin Reg.AX := 5; Reg.BX := b_mask; Intr(Ms_Call, Reg); count := Reg.BX; last_x := Reg.CX; last_y := Reg.DX; Ms_Get_b := Reg.AX; End; {----- Ms_Get_b -----} { Ms_Get_b_Release Возвращает текущее состояние кнопок на "мыши". Count - содержит количество отпусканий интересующей кнопки (задается битом в b_mask) после предыдущего обращения к этой функции. После этого обращения счетчик отпусканий обнуляется. last_x, last_y - координаты "мыши" в момент последнего отпускания требуемой кнопки. } Function Ms_Get_b_Release( b_mask : Word; Var count : Word; Var last_x, last_y : Word) : Word; Begin Reg.AX := 6; Reg.BX := b_mask; Intr(Ms_Call, Reg); count := Reg.BX; last_x := Reg.CX; last_y := Reg.DX; Ms_Get_b_Release := Reg.AX; End; {----- Ms_Get_b_Release -----} { Ms_Set_hMinMax Задает горизонтальный диапазон движения "мыши". Если Min>Max, то они меняются местами. Если в момет обращения курсор был вне диапазона, то он прыгает внутрь его. } Procedure Ms_Set_hMinMax(Min, Max : Word); Begin Reg.AX := 7; Reg.CX := Min; Reg.DX := Max; Intr(Ms_Call, Reg); End; {----- Ms_Set_hMinMax -----} { Ms_Set_vMinMax Задает вертикальный диапазон движения "мыши". Если Min>Max, то они меняются местами. Если в момет обращения курсор был вне диапазона, то он прыгает внутрь его. } Procedure Ms_Set_vMinMax(Min, Max : Word); Begin Reg.AX := 8; Reg.CX := Min; Reg.DX := Max; Intr(Ms_Call, Reg); End; {----- Ms_Set_vMinMax -----} { Ms_Set_GraphPointer Установить графический образ курсора. hotx, hoty - координаты "горячей точки" (т.е. координаты этой точки из образа курсора будут возвращаться в функциях Ms_Get_b, Ms_Get_b_Release) относительно образа курсора. Левый верхний угол имеет координаты (0,0). image - маска курсора. Первые 16 слов - это маска экрана. Вторые 16 слов - маска курсора. Новый курсор строится так: видеопамять AND маска экрана результат XOR маска курсора } Procedure Ms_Set_GraphPointer(hotx, hoty : Word;Var image); Begin Reg.AX := 9; Reg.BX := hotx; Reg.CX := hoty; Reg.DX := Ofs(image); Reg.ES := Seg(image); Intr(Ms_Call, Reg); End; {----- Ms_Set_GraphPointer -----} { Ms_Set_TextPointer Задает вид курсора в текстовом режиме. select - тип построения курсора (0 - программный, 1 - аппаратный). Если select=0, то char_attr_StLine - символ и атрибут; char_attr_EndLine - символ и атрибут. Результирующий символ под курсором будет ( (char_attr_StLine AND символ_в_видеопамяти) XOR char_attr_EndLine) Если select=1, то char_attr_StLine - начальная строка мигающего курсора; char_attr_EndLine - конечная строка мигающего курсора.} Procedure Ms_Set_TextPointer(select : Word; char_attr_StLine : Word; char_attr_EndLine : Word); Begin Reg.AX := 10; Reg.BX := select; Reg.CX := char_attr_StLine; Reg.DX := char_attr_EndLine; Intr(Ms_Call, Reg); End; {----- Ms_Set_TextPointer -----} { Ms_Read_motion : Возвращает: hCount - количество сотых долей дюйма, на которое переместилась "мышь" по горизонтали после предыдущего вызова этой функции. vCount - количество сотых долей дюйма, на которое переместилась "мышь" по вертикали после предыдущего вызова этой функции. Положительные числа означают движение вправо и вниз. } Procedure Ms_Read_Motion(Var hCount, vCount : Word); Begin Reg.AX := 11; Intr(Ms_Call, Reg); hCount := Reg.CX; vCount := Reg.DX; End; {----- Ms_Read_Motion -----} { Ms_Set_Routine : Задает процедуру пользователя для обработки прерываний от "мыши" и ее маски. call_mask бит 0 - вызов при перемещении "мыши"; бит 1 - вызов при нажатии левой кнопки; бит 2 - вызов при отпускании левой кнопки; бит 3 - вызов при нажатии правой кнопки; бит 4 - вызов при отпускании правой кнопки; бит 5 - вызов при нажатии средней кнопки; бит 6 - вызов при отпускании средней кнопки. Если все эти биты равны нулю, то программа управления не получает. Если в единицу установлено несколько бит, то программа получает управление при возникновении любого из заданных событий. Sub - адрес программы пользователя. При входе в эту процедуру (PROC FAR): Ax - равно call_mask; Bx - состояние кнопок; Cx - горизонтальная позиция; Dx - вертикальная позиция; Di - счетчик горизонтальных перемещений; Si - счетчик вертикальных перемещений.} Procedure Ms_Set_Routine(call_mask : Word; sub : Pointer); Begin Reg.AX := 12; Reg.CX := call_mask; Reg.DX := Ofs(sub^); Reg.ES := Seg(sub^); Intr(ms_call, Reg); End; {----- Ms_Set_Routine -----} { Ms_lightpen_On Включить эмуляцию светового пера ( тогда можно из BASICа обрабатывать нажатие кнопок "мыши" через оператор PEN).} Procedure Ms_lightpen_On; Begin Reg.AX := 13; Intr(Ms_call,Reg); End; {----- Ms_lightpen_On -----} { Ms_lightpen_Off Выключить эмуляцию светового пера. } Procedure Ms_lightpen_Off; Begin Reg.AX := 14; Intr(Ms_call,Reg); End; {----- Ms_lightpen_On -----} { Ms_Set_MPP Установить масштабный коэффициент пересчета перемещений "мыши" из сотых долей дюйма в точки растра. hMPP - число сотых долей дюйма в 8 точках по горизонтали (по умолчанию = 8). vMPP - число сотых долей дюйма в 8 точках по вертикали (по умолчанию = 8). (1 <= MPP <= 32767) } Procedure Ms_Set_MPP(hMPP, vMPP : Word); Begin IF (hMPP >= 1) And (hMPP <= 32767) And (vMPP >= 1 ) And (vMPP <= 32767) Then Begin Reg.AX := 15; Reg.CX := hMPP; Reg.DX := vMPP; Intr(Ms_call, Reg); End; End; {----- Ms_Set_MPP -----} { Ms_Cond_Off : Задает область экрана, которая будет обновляться. Координаты левого верхнего и правого нижнего углов задаются в пикселах. Если при вызове этой функции курсор находится внутри данной области, то он отключается. Для включения курсора необходимо обратиться к Ms_Show. } Procedure Ms_Cond_Off(Top, Left, Bottom, Right : Word); Begin Reg.AX := 16; Reg.CX := Left; Reg.DX := Top; Reg.SI := Right; Reg.DI := Bottom; Intr(Ms_Call, Reg); End; {----- Ms_Cond_Off -----} { Ms_Set_2speed : Задает порог скорости длоя движения курсора. Когда курсор движется очень быстро, масштабный коэффициет (Ms_Set_MPP) увеличивается вдвое. По умолчанию MPS (сотые дюйма в секунду) равно 128. } Procedure Ms_Set_2speed(MPS : Word); Begin Reg.AX := 19; Reg.DX := MPS; Intr(Ms_Call, Reg); End; {----- Ms_Set_2speed -----} { Ms_swap_Routine : Установить новую процедуру обработки прерываний от Mouse. call_mask - маска прерывания (см. Ms_Set_Routine) Sub - адрес новой процедуры. Значение регистров при входе описано в Ms_Set_Routine. last_call_mask - маска старой программы. last_sub - маска старой прогграммы. } Procedure Ms_swap_Routine( call_mask : Word; sub : Pointer; Var last_call_mask : Word; Var last_sub : Pointer); Begin Reg.AX := 20; Reg.CX := call_mask; Reg.DX := Ofs(sub^); Reg.ES := Seg(sub^); Intr(Ms_Call, Reg); last_call_mask := Reg.CX; last_sub := Ptr(Reg.ES, Reg.DX); End; {----- Ms_Swap_Routine -----} { Ms_Get_State_bfsz Возвращает объем памяти, необходимый для сохранения состояния драйвера. } Function Ms_Get_State_bfsz: Word; Begin Reg.AX := 21; Intr(Ms_Call, Reg); Ms_Get_State_bfsz := Reg.BX; End; {----- Ms_Get_State_bfsz -----} { Ms_Get_State Запомнить состояние драйвера в буфере. } Procedure Ms_Get_State(Var Ms_State); Begin Reg.AX := 22; Reg.DX := Ofs(Ms_State); Reg.ES := Seg(Ms_State); Intr(Ms_Call, Reg); End; {----- Ms_Get_State -----} { Ms_Set_State Восстановить из буфера состояние драйвера. } Procedure Ms_Set_State(Var Ms_State); Begin Reg.AX := 23; Reg.DX := Ofs(Ms_State); Reg.ES := Seg(Ms_State); Intr(Ms_Call, Reg); End; {----- Ms_Set_State -----} { Ms_Get_V_page Возвращает номер текущей видеостраницы, используемой драйвером. } Function Ms_Get_V_Page: Word; Begin Reg.AX := 30; Intr(Ms_Call, Reg); Ms_Get_V_Page := Reg.BX; End; {----- Ms_Get_V_Page -----} { Ms_Set_V_Page Задать номер видимой страницы. } Procedure Ms_Set_V_Page(Ms_V_Page : Word); Begin Reg.AX := 29; Reg.BX := Ms_V_Page; Intr(Ms_Call, Reg); End; {----- Ms_Set_V_Page -----} End.