http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

Паскаль для новичков (часть 22)

 

Спрашивали? Отвечаю…

Дружба с Микки Маусом (часть 2)

(продолжение)

 
Автор: Владислав Демьянишин
 
Паскаль для новичков
Продолжаем тему работы на Паскале с манипулятором “мышь”.
Осталось рассмотреть две немаловажные процедуры, которые помогут настраивать область перемещения курсора мыши в зависимости от экранного разрешения. Все дело в драйвере мыши, который предполагает, что по умолчанию установлено экранное разрешение 640x400, то есть если на самом деле режим экрана будет с разрешением 640x480, то вертикальные координаты курсора мыши будут варьироваться в пределах 0..399, а нижние 80 строк будут для него недоступны. Или если ширина экрана 800 точек, то будут доступны лишь столбцы 0..639, а правые столбцы 640..799 нет. Надо добавить, что в текстовом режиме, например, 80x25 реальное пиксельное разрешение считается 640x400 (размер символа 8x16). А так, как текстовые режимы VESA имеют большее разрешение, то и соответственно понадобится корректировать область перемещения курсора мыши.
 
Чтобы откорректировать область перемещения курсора, нужно просто установить минимальные и максимальные значения по горизонтали и вертикали в соответствии с экранным разрешением, будь то текстовый или графический режим. Это можно сделать при помощи процедур Ms_SetMinMaxX и Ms_SetMinMaxY. Первая устанавливает диапазон перемещения курсора по горизонтали, то есть ограничивает его движение экранными столбцами Min..Max включительно. Для этого регистр CX загружается параметром Min, а регистр DX – Max и вызывается функция 7 драйвера.
 
procedure Ms_SetMinMaxX(Min,Max:word); assembler;
asm
mov ax,07h; mov cx,Min; mov dx,Max; int 33h
end;
 
Аналогично действует процедура Ms_SetMinMaxY, но применительно к вертикальной области перемещения курсора, и вызывает функцию 8 драйвера.
 
procedure Ms_SetMinMaxY(Min,Max:word); assembler;
asm
mov ax,08h; mov cx,Min; mov dx,Max; int 33h
end;
 
Хотя драйвер мыши предоставляет гораздо больший функциональный набор, я могу сказать, что рассмотренных функций вполне достаточно, чтобы осуществить удобный интерфейс разрабатываемой программы. Следует учесть, что данный модуль MSMOUSE является универсальным. Т.е. содержит все основные возможности общения с мышью. Для обеспечения работы с мышью в конкретных текстовых или графических режимах, следует создать модуль-надстройку, переопределив некоторые подпрограммы в соответствии с условиями работы. Сейчас мы этим и займемся.
 

Поддержка мыши в текстовых режимах VESA

 
Ввиду того, что драйвер мыши не знает, как корректно перемещать и отображать курсор в текстовых режимах VESA, возникает необходимость отключения курсора мыши и вместо него эмулировать курсор, инвертируя атрибут символа в позиции курсора. Помимо этого, драйвер мыши всегда принимает и возвращает положение курсора в экранных пикселях (точках), что применительно к тестовому режиму не очень удобно. Поэтому создадим небольшой модуль-надстройку TXTMOUSE.PAS, который будет обеспечивать нормальную работу с интерфейсом мыши в текстовых режимах, рассмотренного ранее модуля VESACRT. Начнем как обычно с заголовка Unit. В объявлении Uses сошлемся на модули VesaCrt и MsMouse, которые рассматривались в предыдущих статьях.
 
Unit TxtMouse;
 
interface
 
Uses VesaCrt, MsMouse;
 
function Ms_SetTextMode( num : word ) : boolean;
procedure Ms_Show( x, y : word );
procedure Ms_Hide;
function Ms_GetX : word;
function Ms_GetY : word;
procedure Ms_CurMove( x, y : word );
 
Объявим переменные Ms_Old_X и Ms_Old_Y для хранения устаревших координат курсора мыши и переменную Ms_Visible, отражающую видимость курсора мыши.
 
var Ms_Old_X, Ms_Old_Y : word;
      Ms_Visible : boolean;
 
implementation
 
Работу программы, как и прежде, следует начинать с вызова функции Ms_Init модуля MSMOUSE, поэтому переопределять эту функцию нет необходимости. Но функцию установки текстового режима следует переопределить так, чтобы она устанавливала не только нужный текстовый режим по индексу, но и соответствующую область перемещения курсора мыши. Значит, функции Ms_SetTextMode быть!
 
function Ms_SetTextMode( num : word ) : boolean;
begin
Ms_SetTextMode := SetTextMode(num);
Ms_SetMinMaxX(0, Screen.MaxX*Screen.CharWidth);
Ms_SetMinMaxY(0, Screen.MaxY*Screen.CharHeight);
end;
 
Ее можно вызывать вместо функции SetTextMode модуля VESACRT, где индексами шести текстовых режимов могут быть константы VesaDefault..Vesa132x60, объявленные в модуле VESACRT, который уже рассматривался ранее.
Далее опишем внутреннюю процедуру инвертирования атрибута символа в позиции экрана (X, Y), при этом бит мерцания затронут не будет, чтобы не нервировать пользователя. Процедура InvertSimbol нужна для рисования текстового курсора мыши в заданной позиции, а при перемещении курсора, следует выполнить эту же процедуру для устаревших координат курсора мыши.
 
procedure InvertSimbol( x, y : word );
var TextScreen : PScrLine;
begin
if (x>Screen.MaxX) or (y>Screen.MaxY) then exit;
TextScreen := ptr( ScrAddr, y*Screen.Width*2 );
with TextScreen^[x] do
        Attr := (Attr and $80) or ((not Attr) and $7f);
end;
 
После инициализации мыши не следует вызывать процедуру Ms_CurShow, так как это будет мешать правильному отображению курсора мыши. Вместо нее объявим процедуру Ms_Show, которая правильно отобразит курсор в заданной позиции (X, Y). Координаты следует задавать в символах, а не в точках.
 
procedure Ms_Show( x, y : word );
begin
if Ms_Visible then
if (x=Ms_Old_X) and (y=Ms_Old_Y) then exit;
Ms_Visible := true;
Ms_SetPosition( x*Screen.CharWidth,
y*Screen.CharHeight );
Ms_Old_X := x;
Ms_Old_Y := y;
InvertSimbol( x, y );
end;
 
Если нужно выключить курсор мыши, то ни в коем случае нельзя вызывать процедуру Ms_CurHide. На замену ей, объявим процедуру Ms_Hide, которая восстановит атрибут символа в устаревшей позиции курсора мыши.
 
procedure Ms_Hide;
begin
if not Ms_Visible then exit;
Ms_Visible := false;
InvertSimbol( Ms_Old_X, Ms_Old_Y );
end;
 
Для определения положения курсора мыши в символьных позициях достаточно воспользоваться функциями Ms_GetX и Ms_GetY.
 
function Ms_GetX : word;
begin
Ms_GetX := Ms_X div Screen.CharWidth;
end;
 
function Ms_GetY : word;
begin
Ms_GetY := Ms_Y div Screen.CharHeight;
end;
 
Если текст на экране долгое время остается неизменным, а курсор нужно перемещать в соответствии с его новыми координатами, то в некотором цикле следует вызывать процедуру Ms_CurMove, которая восстановит атрибут символа в устаревшей позиции курсора, и отобразит курсор уже в новой позиции. Новые координаты (X,Y) следует задавать в символах.
 
procedure Ms_CurMove( x, y : word );
begin
if Ms_Visible then begin
   Ms_Hide;
   Ms_Show(x,y);
   end
   else begin
          Ms_SetPosition( x*Screen.CharWidth, y*Screen.CharHeight);
          Ms_Old_X := x;
          Ms_Old_Y := y;
          end;
end;
 
И завершить модуль следует инициализацией переменных:
 
begin
Ms_Old_X := 0;
Ms_Old_Y := 0;
Ms_Visible := false;
end.
 
Хочу заметить, что если на экране постоянно перерисовываются некоторые строки, то при использовании процедуры Ms_CurMove будет наблюдаться шлейф в виде еще одного инвертированного символа в устаревшей позиции курсора мыши. Это следствие того, что процедура Ms_CurMove не подозревает, что текст в устаревшей позиции был обновлен, и что его восстанавливать не нужно. Поэтому, если изображение на экране постоянно обновляется (весь экран), то лучше использовать процедуру Ms_Show, которая будет просто отображать курсор на экране. Вот код небольшой программы, которая иллюстрирует совместную работу модулей TXTMOUSE и VESACRT:
 
Uses TxtMouse, MsMouse, VesaCrt;
 
var mode : word;
 
{ возвращает число в виде строки }
function IntToStr( i : longint) : string;
var s : string;
begin
Str( i, s );
IntToStr := s;
end;
 
{ устанавливает очередной текстовый режим,
возможная ошибка игнорируется }
procedure IncMode;
begin
Inc( Mode );
if Mode>5 then Mode := 0;
if Ms_SetTextMode( Mode ) then;
TextOut( 0, Screen.MaxY, 'Last string' );
TextOut( 0, 6, 'CharHeight: ' +
IntToStr( Screen.CharHeight ) + ' ' );
TextOut( 0, 7, 'Screen: ' +
IntToStr( Screen.mode ) + ' ' );
end;
 
begin
Mode := 1;
if not Ms_Init then begin
   { выдаем сообщение об ошибке }
   writeln('Error: Mouse driver not found.');
   halt;
   end;
if not Ms_SetTextMode( Mode ) then begin
   { выдаем сообщение об ошибке }
   writeln('Error: Bad screen mode');
   halt;
   end;
IncMode;
{ отключаем текстовый курсор }
CursorHide;
{ включаем курсор мыши и позиционируем его в центр
экрана }
Ms_Show(Screen.Width div 2,Screen.Height div 2);
repeat
if (Ms_GetX<>Ms_Old_X) or (Ms_GetY<>Ms_Old_Y) then begin
   { Если курсор мыши переместился, то обновляем информацию о его координатах и смещаем курсор в новую позицию. Именно на этих строках и  будет наблюдаться шлейф курсора мыши }
   TextOut(0,0,'X: '+IntToStr(Ms_GetX)+' ');
   TextOut(0,1,'Y: '+IntToStr(Ms_GetY)+' ');
   TextOut(0,4,'OldX: '+IntToStr(Ms_Old_X)+' ');
   TextOut(0,5,'OldY: '+IntToStr(Ms_Old_Y)+' ');
   Ms_CurMove( Ms_GetX, Ms_GetY );
   end;
if Ms_Click( mbLeft ) then begin
   { по клику левой клавиши мыши переходим к следующему текстовому режиму экрана и позиционируем курсор в его центре }
   IncMode;
   Ms_Show(Screen.MaxX div 2,Screen.MaxY div 2);
   end;
{ по клику правой клавиши мыши прекращаем цикл }
until Ms_Click( mbRight );
{ восстанавливаем текстовый режим по умолчанию и завершаем работу программы }
if SetTextMode( 0 ) then;
end.
 
В данной программе текстовый курсор скрыт, но если в нем будет необходимость, то его можно включить командой CursorShow, реализованной в модуле VESACRT. Так же вместе с модулями VESACRT и TXTMOUSE можно использовать модуль KEYBOARD, который был рассмотрен ранее.
 
Как Вы могли заметить, в последнем примере, после инициализации драйвера мыши для установки необходимого текстового режима используется функция Ms_SetTextMode модуля TXTMOUSE, а перед завершением программы выполняется функция SetTextMode модуля VESACRT. Это допустимо, так как не имеет значения, как будет установлен стандартный для MS-DOS текстовый режим 80x25, потому что при установке этого режима драйвер мыши сам сможет корректно определить область перемещения курсора мыши. И все будет тип-топ ;o)
 
Еще, хочу обратить внимание на применение процедуры TextOut модуля VESACRT, которая в отличие от стандартной команды Writeln не способна преобразовывать числовое значение в текстовое представление, поэтому предварительно параметры Ms_GetX, Ms_GetY, Ms_Old_X, Ms_Old_Y и другие обрабатываются функцией
 
IntToStr. Функция IntToStr использует стандартную процедуру Str для преобразования численного значения в эквивалентное текстовое представление, после чего полученное строковое значение пригодно для вывода на экран процедурой TextOut.
 
Как видите, при помощи рассмотренных модулей легко можно заставить программу повиноваться пользователю как по мановению волшебной палочки, роль которой в данном случае исполняет манипулятор мышь.
 
Исходный код модулей и примеров к ним можно с легкостью найти на выше указанном сайте. Там же можно скачать резидентную справочную систему Norton Guide, которая поможет узнать много интересного об устройстве ОС MS-DOS и драйверов к ней как на английском языке, так и на русском.
Мавр сделал свое дело. Мавр может уходить…
 

Литература

1. Диалоговая справочная система Norton Guide.
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 22): Спрашивали? Отвечаю... Дружба с Микки Маусом (часть 2) (продолжение)
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы