Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2836
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

8, Управление техническими средствами и взаимодействие с MS DOS

SetColor(O); {стираем кадр}

Squarel(round(xn), round(yn), round(dx), round(dy)); dx:=dxl; {заменяем параметры квадрата}

dy: =dyl xn:=xnJ yn:=ynl

end;

CloseGraph;

end.

Прямая запись в видеобуфер. При программировании на экране дви­ жения объектов критичным является время перезаписи изображения: имен­ но из-за большого времени перезаписи движение получается прерывистым. Для уменьшения этого времени при программировании в MS DOS часто ис­ пользуют прямую запись информации в видеобуфер.

Как указывалось в параграфе 8.4, формат информации в видеобуфере за­ висит от используемого графического режима. При использовании младших режимов VGA, на которые рассчитан Borland Pascal, видеобуфер содержит 4 бита на каждую точку, причем биты расположены в параллельных битовых плоскостях и доступ к ним напрямую существенно затруднен (программиро­ вание таких операций обычно выполняется на ассемблере). Однако сущест­ вует режим VGA (режим 19: 200*320 точек 256 цветов из палитры 262 144 цвета), при котором каждой точке соответствует байт (8 бит) в видеобуфере. Именно этот режим и используется, если возникает необходимость програм­ мировать сложное движение с использованием прямой записи в видеобуфер.

Пример 8.8. Разработать программу, обеспечивающую вывод «бегу­ щей» строки. Направление движения строки по экрану - вверх-вниз.

Для создания изображения используем возможности модуля Graph, за­ тем перепишем изображение из видеопамяти в буфер, расположенный в ди­ намической памяти, и перейдя в режим 200*320, организуем циклический вывод изображения напрямую в видеобуфер. Стирание старого изображения будем выполнять чистой кромкой образа (образ «не прозрачный»).

Переход в другой, не поддерживаемый Borland Pascal графический ре­ жим, будем осуществлять, используя ресурсы модуля Dos, описанные далее.

Program ex;

Uses Graph, CrUDos; Type

ScreenType=array [0,.199,0..319J of byte; {массив для хранения образа экрана - формат видеобуфера}

ImageType=array[0..999]ofbyte; {развертка изображения}

ScrTypePtr=^ScreenType; {указатель на массив образа экрана} ImageTypePtr=^^ImageType; {указатель на развертку изображения}

291

Часть L Основы алгоритмизации и процедурное программирование

{процедура установки режима с номером mode}

Procedure SetBIOSMode(mode:byte); Var r:registers;

Begin

r.AL:=mode; {запись номера режима в регистр AL} кАН:=0; {запись номера функции в регистр АН} intr($10,r); {вызов 0-й функции 10-го прерывания}

End;

{основная программа}

Var

Driver,Mode.'Integer; s:string;

ij, n, m, l,y, dy:integer;

Active_Ptr:ScrTypePtr; {указатель на тип "образ экрана"} Image:ImageTypePtr; {указатель на развертку изображения}

Begin

{формирование изображения и сохранение его в памяти}

Driver: =Detect; InitGraph(Driver,Mode, "); s:='ABCDEF\-

SetColor(4); SetTextStylefGothicFont, HorizDir, 3); OutTextXY(2,2,s);

n:=TextHeight(s)+3;

m:^TextWidth(s)+3;

GetMem(Image,(n+l)*(m+])); {получение памяти для записи изображения}

1:=0;

for i:=0 to ndo for J: =0 to mdo

begin

image^[l]:=Lo(GetPixel(j,i)); {запись изображения в буфер} 1:4+1;

end;

CloseGraph;

{запись изображения «напрямую» в видеобуфер} SetBIOSMode($13); {установка 19-го графического режима}

Active_Ptr:=Ptr($AOOO,0); {стандартный адрес видеобуфера}

у:-0; dy~l;

{покадровый вывод изображения} repeat

{побайтная запись изображения в видеобуфер}

1:=0;

for i:=0 to п do

292

8. Управление техническими средствами и взаимодействие с MS DOS

forj:=Oto т do begin

Active_Ptr''[y+i+]0j+20J:=image^flJ; 1:4+1;

end;

for i:=J to 1000 do Delay(3000); {задержка}

Inc(y,dy); {смещение изображения}

if(y>120) or (y<0) then dy:='dy; {организация колебательного

движения}

until KeyPressed;

SetBIOSMode(3); {возврат к стандартному текстовому режиму}

End.

8.8. Взаимодействие с драйвером мыши

Мышь - манипулятор, движение которого по столу или другой поверх­ ности преобразуется в перемещение специального курсора мыши на экране. С ее помощью мы можем «указать» на какую-либо область экрана и, нажи­ мая клавиши мыши, заказать некоторую обработку.

Для управления мышью программы, написанные на Borland Pascal, ис­ пользуют драйвер мыши, предоставляемый BIOS. Вызов этого драйвера осу­ ществляется через инициацию прерывания с номером ЗЗ15 = 51 ю (int 33h ~ на ассемблере).

Драйвер мыши реализует выполнение основных операций с мышью:

инициализирует мышь (с проверкой наличия);

устанавливает курсор мыши в заданное место экрана;

определяет местоположение курсора мыши и состояния ее клавиш (нажаты или нет);

управляет видимостью курсора мыши.

К сожалению, библиотеки Borland Pascal не включают функций обраще­ ния к драйверу мыши, и его вызов приходится осуществлять через процеду­ ру активизации обработчиков прерываний, определенную в модуле Dos.

Процедура Intr(numlnt:byte; Var Regs:Register) - активизирует обработ­ чик прерывания с номером numlnt. Через параметр Regs типа Registers орга­ низуется доступ к содержимому регистров (внутренней памяти) процессора:

Туре Registers = record case Integer of

 

0: (AX,BXCXDXBP^DI,DS,ES,

Flags: word);

J: (AL,AH,BL,BH,CL,CH,DL,DH:byte);

end;...

Обмен данными между программой и драйвером мыши выполняется че­ рез регистры, указанные в описании драйвера. Так, номер вызываемой функ-

293

Часть I. Основы алгоритмизации и процедурное программирование

ции помещается в регистр АХ, а для передачи или получения дополнитель­ ной информации используются регистры СХ, DX.

Ниже приводится текст модуля, содержащего ресурсы, которые обеспе­ чивают доступ к драйверу мыши.

Unit Mouse; Interface

Uses Dos;

Function ResetMouse:Boolean; {проверить наличие} Procedure ShowMouseCursor; {показать курсор мыши} Procedure HideMouseCursor; {спрятать курсор мыши}

{прочитать состояние мыши}

Procedure ReadMouseStatefVar х, у:integer;{координаты мыши}

Var LeftButton,

{нажата левая клавиша}

MiddleButton,

{нажата средняя клавиша}

RightButton:boolean);

{нажата правая клавиша}

Procedure MoveMouseCursor(x,y:integer);

{установить курсор мыши

в точку с заданными координатами}

Implementation

{проверить наличие}

Function ReSetMouse.Boolean; Var г:Registers;

Begin r.AX:^0; intr($33,r);

ReSetMouse: =r.AX=$FFFF; End;

{показать курсор мыши}

Procedure ShowMouseCursor; Var r:Registers;

Begin

KAX:=I;

intr($33,r); End;

{спрятать курсор мыши}

Procedure HideMouseCursor; Var r:Registers;

Begin

KAX:^2;

intr($33,r); End;

294

8. Управление техническими средствами и взаимодействие с MS DOS

{прочитать состояние мыши}

Procedure ReadMouseStatefVar х,у:integer;{координаты мыши}

Var LeftButton,

{нажата левая клавиша}

MiddleButton,

{нажата средняя клавиша}

RightButton:boolean);

{нажата правая клавиша}

Var г:Registers;

 

Begin

 

r.AX:=3;

 

intr($33,r);

 

х:=кСХ;

 

y:==r.DX;

 

LeftButton-fr.BXAND 1)<>0; RightButton:=(r.BXAND 2)<>0; MiddleButton:^(KBXAND 4)<>0;

End;

{установить курсор мыши}

Procedure MoveMouseCursor(x,y:integer); Var r:Registers;

Begin

KAX:=4;

r.CX:=x;

KDX:=y; intr($33,r);

End; End

Разработка программ, использующих мышь, имеет свои особенности. В отличие от клавиатуры, ввод информации с которой осуществляется пользо­ вателем по запросу программы, состояние мыши (перемещение и положение клавиш) может изменяться пользователем в любой момент времени, незави­ симо от программы. Следовательно, программы, работающие с мышью, должны циклически опрашивать состояние мыши и при его изменении осуществлять требуемые операции.

На рис. 8.12 показано, как программа определяет моменты нажатия и от­ пускания клавиш (при выполнении опроса, если клавиша нажата, перемен­ ной Left присваивается значение true, а если - не нажата, то false).

Учитывать приходится также режим экрана, который использует про­ грамма, так как координаты курсора мыши на экране и в текстовом и в гра­ фическом режимах определяются в пикселях.

Взаимодействие с мышью в текстовом режиме. Координаты мыши при работе с ней в текстовом режиме необходимо пересчитывать, причем не­ зависимо от реального размера знакоместа считается, что оно имеет размер 8x8 пикселей.

295

Часть L Основы алгоритмизации и процедурное программирование

Состояние

Клавиша

Клавиша нажата

 

Клавиша

не нажата Г

 

1

не нажата

клавиши

Опросы

 

 

 

 

 

 

 

Действия

 

 

 

 

программы

[

 

I

 

 

^

Left = tme

 

 

 

 

Состояние

Left = false

 

 

Left = false

переменной

 

 

 

 

 

 

Рис. 8.12. Циклический опрос состояния мыши для фиксащ{и моментов нажатия и отпускания клавиши мыши

Пример 8.9. Разработать программу, демонстрирующую особенности использования мыши в текстовом режиме. При нажатии левой клавиши мы­ ши программа должна высвечивать координаты точки. Выход осуществить при нажатии левой клавиши мыши, когда ее курсор находится в окне «Ко­ нец» (рис. 8.13).

Управление разрабатываемой программой будет реализовано только по­ средством мыши. Вначале проверим наличие мыши, нарисуем окно Конец («кнопка»), установим i^pcop в левый верхний угол экрана. Затем будем от­ слеживать перемещение курсора, мыши и нажатие ее левой клавиши. Если клавиша нажата, то определяем местоположение курсора, проверяем, не на­ ходится ли он над окном Конец, и если нет, то выводим его координаты. По­ сле этого ожидаем отпускания клавиши, чтобы повторно не выводить коор­ динаты курсора.

::||Щ||?|^||

iiiii^iiasSs Конец

|||||||||Щ,

-?ciif:f|§ii

Рис. 8.13. Вид экрана в процессе работы программы

296

8. Управление техническими средствами и взаимодействие с MS DOS

Program ex;

 

 

 

 

 

Uses

CrtMouse;

 

 

 

 

 

Var x,y,xt,yt:integer;

l,m,r:boolean;

 

exit_m:boolean;

 

 

 

 

Begin

Clrscr;

 

 

 

 

 

 

if not ReSetMouse then

{проверка наличия мыши}

 

begin

 

 

 

 

 

 

WriteLn('Mbitub не загруэюена');

 

Halt(l);

 

 

 

 

end

 

 

 

 

 

 

else WriteLn('Mbiiub подключена, *);

 

ShowMouseCursor;

{покажем курсор: курсор устанавливается

 

MoveMouseCursor(0,0);

 

в центр экрана}

 

{поместим курсор в левый

 

Window(70,1,80,3);

 

 

верхний угол экрана}

 

{нарисуем окно-кнопку «Конец»}

 

Textattr:=^]6*J+14;

Clrscr;

 

Gotoxy(2,2);

WriteCKoнeц');

 

Windowd

1M25);

Gotoxy(],3);

 

Textattr:=5*]6-^9;

 

 

 

 

repeat

{цикл обработки нажатий клавиши}

 

ReadMouseState(x,y, /, т,г);

 

 

if I then

{если нажата левая кнопка }

 

begin

 

 

 

 

 

{пересчет координат курсора для текстового режима}

 

xt:=x div 8+1;

 

 

 

yt:=y div 8+1;

 

 

 

exitjn:=(xt>=70)

and (xt< =80) and (yt> =1) and (yt< =3);

 

if not exitjn

then

 

 

 

 

begin

 

 

 

 

 

Gotoxy(xt,yt);

 

 

 

 

HideMouseCursor;

{если не убирать курсор,

 

 

 

 

 

то курсор мыши будет затерт строкой}

 

 

Write('x= \ xt:4, ' у= \ yt:4);

 

 

ShowMouseCursor;

{теперь символ под курсором

 

 

 

 

 

 

«просвечивает» другим цветом}

end;

repeat ReadMouseState(x,y,l,m,r) until not I; {ждем отпускания левой кнопки}

end;

until exitjn; {до «нажатия кнопки» Конец}

Textattr:=7; Clrscr;

End

297

Часть 1. Основы алгоритмизации и процедурное программирование

Drawing with mouse:

? MJ.

Курсор мыши

Рис. 8.14. Вид экрана при выполнении программы

Взаимодействие с мышью в графическом режиме* При использова­ нии мыши в графическом режиме также приходится выполнять циклический опрос состояния мыши для определения момента нажатия клавиши.

Пример 8.10. Разработать программу рисования мышью при нажатой левой клавише: точка рисуется при каждом опросе состояния мыши, если клавиша остается нажатой. Реализовать двойное управление (с клавиатуры и мышью): выход ~ при нажатии мышью кнопки Exit на экране или клавиши Esc на клавиатуре (рис. 8.14).

Program ex;

Uses Mouse,Crt,Graph; Var

x,y:mteger;

l,m,r:boolean;

exitjn:boolean;

driver,mode:integer;

ch:char;

{процедура рисования кнопки}

Procedure Button(xI,yI,x2,y2:integer;s:string); Begin

SetColor(O);

 

SetFillStyle(l8);

{рисуем контур кнопки}

Bar(xl,yl,x2,y2);

SetFillStyleOJ);

Ваг(х1-^2,у1+2,х2'3,у2гЗ); {рисуем тени кнопки} SetFillStyle(ll5);

Bar(x],ylxl+ly2);

298

8. Управление техническими средствами и взаимодействие с MS DOS

Bar(xl+2,у]+Ixl+2,y2-J); Bar(x],yJ,x2,yI+J); Bar(xl+lyl+1x2'lyl +2); SetColor(4); SetTextStyle(lA3); OutTextXY(xl^20,yl+3,s);

End;

{основная программа}

Begin Clrscr;

if not ReSetMouse then {проверим наличие мыши} begin

WriteLnCMouse notfound, *); halt(l);

end; driver: ^'detect;

InitGraph(driver,mode,' '); SetColor(4);

OuttextXY(10,]0, 'Drawing with mouse:'); ShowMouseCursor; {покажем курсор мыши}

SetBkColor(3);

Button (500J0,600,50, 'Exit');

repeat {цикл опроса состояния клавиатуры и мыши}

if keypressed then ch:-readkey {если нажата клавиша на клавиатуре, то введем код}

else {если клавиша не нажата, то} begin

ReadMouseState(x,y,l,m,r); {опросим состояние мыши} Exitjn: ==(х> =500)and(x< =600)and(y>=10)and(y< =50); if not Exitjn and I then {если не «нажата» кнопка «Exit»

на экране}

begin {изобразим точку на экране}

HideMouseCursor;

PutPixel(x,y4);

ShowMouseCursor;

end;

end

until (exitjn and I) or (ch=#27);

repeat ReadMouseState(x,y,l,m,r) until not I; {ожидаем отпускания клавиши}

CloseGraph; End

299

Часть I. Основы алгоритмизации и процедурное программирование

Задание для самопроверки

Модернизировать профамму из задания 1 к параграфу 8.4 так, чтобы реализо­ вать двойное управление меню: с использованием клавиатуры и мыши.

8.9.Управление задачами. Вызов дочерних процессов

Сточки зрения MS DOS каждая программа (задача) представляет собой процесс. При запуске процессу выделяется память и передаются окружение

ипараметры командной строки MS DOS.

Окружение - это специальная область памяти, в которой размещены в виде символьных строк некоторые параметры, установленные в DOS. На­ пример:

COMSPEC=C:\COMMAND.COM

{адрес интерпретатора команд

PATH=C:\QEMM;C:\DOS;C:\NC

MS DOS}

{каталоги автоматического по­

PROMPT=$p$q

 

иска}

{вид запроса в командной строке MS DOS}

Пользователь может включить в окружение другие строки, используя команду SET.

Для работы с окружением модуль DOS содержит следующие ресурсы. 1. Функция EnvCount: integer - возвращает количество переменных ок­

ружения, содержащихся в среде MS DOS.

2. Функция EnvStr(Index:integer):strmg - возвращает переменную окру­ жения MS DOS с указанным индексом.

3. Функция GetEnv(EnvVar:string):string - возвращает переменную ок­ ружения MS DOS с указанным именем.

Используя эти функции, можно, например, определить в системе место­ положение каталога временных файлов, обычно заданного в MS DOS пара­ метром work:

flag:--false;

while (i<EnvCount) and not flag do begin

ifpos('work^\EnvStrli])^l then begin

path: =copy(EnvStr[i], 6, length(EnvStr[i])-5); flag:'=true;

end else inc(i);

300