Ресурсы модуля crt для управления экраном.

Управление экраном с помощью ресурсов модуля crt базируется на понятии «окно».

Окно - часть экрана прямоугольной формы. В момент получения программой управления весь экран считается окном 25x80 знакомест. Программист может определять на экране новые окна и управлять как цветом символов и фона окна, так и размещением информации в окне. Вывод информации в текстовом режиме осуществляется стандартными процедурами Write и WriteLn текущими цветом символа и цветом фона.

При выводе четыре символа интерпретируются особым образом:

#7 - звуковой сигнал;

#8 - перемещение курсора влево на один символ;

#10 - перемещение курсора на строку вниз (если курсор находился в последней строке, то содержимое экран «прокручивается» на строку вверх);

#13 - перемещение курсора в начало текущей строки.

Ресурсы модуля crt для управления экраном. - student2.ru

Рис. 8.2. Текущее окно на экране и относительная адресация символа в окне

Процедуры начинают вывод с того места, где стоит курсор. Координаты курсора определяются относительно верхнего левого угла текущего окна (рис. 8.2). Для управления окнами и размещения в них информации модуль crt содержит следующие процедуры и функции.

1. Процедура Window(xl, у1, х2, y2:word) - определяет на экране окно. Местоположение и размеры окна определяются координатами верхнего левого (х1, у1) и нижнего правого (х2, у2) углов прямоугольника. Координаты текущего окна модуль crt хранит в специальных переменных:

WindMin, WindMax:word.

Откуда координаты текущего окна можно определить, применив функции 1о и hi, которые выделяют из слова младший и старший байты соответственно:

xl=Lo(WindMin) - координата х верхнего левого угла;

у1=Hi(WindMin) - координата у верхнего левого угла;

x2=Lo(WindMax) - координата х нижнего правого угла;

y2=Hi(WindMax) - координата у нижнего правого угла.

После объявления окна курсор устанавливается в верхний левый угол окна.

2. Процедура TextColor(color:byte) - устанавливает текущий цвет вывода символов в окне.

3. Процедура TextBackGround(color:byte) - устанавливает текущий цвет фона окна. Цвета для процедур TextColor и TextBackGround можно задавать, используя специальные константы модуля crt:

Black=0; {черный} DarkGrey=8; {темно-серый}

Blue=1; {синий} LightBlue=9; {светло-синий}

Green=2; {зеленый} LightGreen=10; {светло-зеленый}

Cyan=3; {голубой} LightCyan=11; {светло-голубой}

Red=4; {красный} LightRed=12; {розовый}

Magenta=5; {фиолетовый} LightMagenta=13; {сиреневый}

Brown=6; {коричневый} Yellow=14; {желтый}

LightGrey=7; {светло-серый} White=15; {белый}

Blink=128; {мерцание}

Текущие цвета символа и фона в виде байта атрибута хранятся в переменной TextAttr:word. Текущий цвет фона из этой переменной определяется как

(TextAttr div 16) mod 8,

a текущий цвет символа как

TextAttr mod 16.

4. Процедура ClrScr - очищает окно, выводя в него пробелы с текущим атрибутом. После этого курсор устанавливается в верхний левый угол окна. Если окно не установлено, то очищается весь экран. Эту процедуру обычно используют после определения окна и атрибута его символов, чтобы обозначить окно на экране.

5. Функция WhereX:word - возвращает координату х текущего положения курсора в окне.

6. Функция WhereY:word - возвращает координату у текущего положения курсора в окне.

7. Процедура GotoXY(x,y:word) - перемещает курсор на знакоместо с координатами x и у.

Модуль crt содержит также процедуры, работающие с текущей строкой (строкой, в которой стоит курсор).

8. Процедура DelLine - удаляет текущую строку.

9. Процедура InsLine - вставляет строку, сдвигая остальные строки вниз.

10. Процедура ClrEol – стирает часть строки справа от курсора.

Пример 8.1.

Разработать программу вычисления среднего арифметического заданного количества чисел n, где n<10. Реализовать оконный интерфейс, представленный на рис. 8.3. Верхнее окно интерфейса не зависит от исходных данных. Его нужно определить, задать цвета символов и фона, очистить и вывести в него текст. Ввод ответа пользователя будет выполняться с того места, где окажется курсор. Количество окон для ввода чисел зависит от введенного значения. Их положение на экране необходимо рассчитать.

Ресурсы модуля crt для управления экраном. - student2.ru

Рис. 8.3. Интерфейс программы вычисления среднего арифметического

Нижнее окно также не зависит от исходных данных. Его нужно определить и внести в него результат. Ниже представлена соответствующая программа с комментариями.

Program ex;

Uses Crt;

Var a:array[1 10] of integer;

x,dx,n,i:integer; s:real;

Begin

ClrScr; {очищаем экран}

Window(20,3,50,5); {выделяем окно ввода количества чисел}

TextAttr:=16+7; {определяемсветло-серые символы на синем фоне}

ClrScr; { выделяем окно ввода}

GotoXY(2,2); {устанавливаем курсор для вывода запроса}

Write(‘введите количество чисел:’); {выводим запрос}

ReadLn(n); {вводим ответ пользователя}

dx:=(80-(n+1)*3)div n;

х:=0;

s:=0;

TextAttr:=2*I6+14; {желтые символы на зеленом фоне}

for i:=1 to n do

begin х:=х+3;

Window(x,7,x+dx,9); {устанавливаем окно ввода данных}

ClrScr; {выделяем это окно}

GotoXY(2,2);{устанавливаем курсор для ввода данных}

ReadLn(a[i]); {вводим число}

s:=s+a[i];

x:=x+dx;

end;

TextAttr:=4*16+14; {желтые символы на красном фоне}

Window(18,11,53,13); {устанавливаем окно результата}

ClrScr;{выделяем окно результата}

GotoXY(3,2);{устанавливаем курсор для вывода результата}

Write('Cpeднee арифметическое =’, s/n:5:2);

ReadLn; {ожидаем нажатия клавиши Enter}

Window(1,1,80,25); {восстанавливаем окно на весь экран}

TextAttr:=7; {восстанавливаем стандартные цвета}

ClrScr; {очищаем экран}

End.

Управление клавиатурой

Клавиатура - достаточно сложное устройство, в состав которого входит микропроцессор и память - буфер клавиатуры. При нажатии и отпускании любой клавиши в буфер клавиатуры записываются так называемые коды нажатия/отпускания, при этом микропроцессор клавиатуры отсекает дребезг клавиш - сигналы, полученные при неполном контакте в процессе нажатия и отпускания клавиши.

Клавиши клавиатуры делят на буквенно-цифровые, специальные и клавиши смещения.

К буквенно-цифровым относят клавиши букв, цифр, специальных знаков и пробела. Их используют для ввода информации.

Специальные клавиши - это клавиши управления курсором (←, ↑, →, ↓, Home, End, Tab, Page up. Page down), удаления (Del, Backspace), клавиши переключения режимов (Ins, Caps lock, Num lock, Scrool lock), функциональные клавиши (Esc, Break, Fl, F2, F3, ..., FI2) и т.д. Эти клавиши используют для выполнения вспомогательных операций во время работы с компьютером.

Клавиши смещения - это клавиши Shift, Ctrl и Alt. Их используют совместно с другими клавишами для изменения вводимых кодов. Так, если при нажатии клавиши «а» формируется код строчной буквы а латинского алфавита, то нажатие Shift-a приведет к вводу кода заглавной буквы А латинского алфавита.

Всего выделяют около 400 различных комбинаций, которые могут обрабатываться программой. Эти комбинации формируются на основании кодов нажатия/отпускания специальной программой BIOS (базовая система обработки ввода-вывода) и записываются в буфер BIOS клавиатуры.

Изначально считалось, что количество различных комбинаций не превысит 256, и, соответственно, для представления этой информации будет достаточно 1 байта (см. приложение 2), но со временем количество комбинаций возросло, и потребовалось использование второго байта.

В настоящее время для представления комбинаций, не вошедших в таблицу ASCII, используют расширенные коды, состоящие из двух байт: первый байт равен 0, а второй - содержит расширенный scan-код (см. приложение 3).

Ввод буквенно-цифровых данных с клавиатуры осуществляется процедурами Read и ReadLn,при этом реально происходит чтение кодов ASCII из буфера BIOS клавиатуры. Считанные символьные коды преобразуются во внутренний формат в соответствии с типом переменной.

Процедуры Read и ReadLn обрабатывают только комбинации, соответствующие буквам и цифрам, а также некоторые специальные комбинации, например, маркер конца строки (комбинация символов #13, #10).

Модуль crt содержит специальные функции управления клавиатурой, которые позволяют работать с расширенными кодами.

1. Функция KeyPressed: boolean - возвращает true, если нажата любая клавиша, false - если буфер BIOS клавиатуры пуст; функция не извлекает символы из буфера, не ожидает ввода;

2. Функция ReadKey:char - извлекает очередной код из буфера BIOS клавиатуры и возвращает его как результат операции, ожидает ввода, но не высвечивает вводимого символа.

Для чтения расширенного кода функцию ReadKey необходимо вызывать дважды: первый раз она вернет 0, а второй - расширенный scan-код:

chl:=ReadKey; {читаем код}

if chl=#0 then ch2:=ReadKey; {если код=0, то читаем второй байт}

Пример 8.2.Разработать программу определения кодов клавиш и их комбинаций. Выход из цикла осуществлять по нажатию клавиши Esc.

Program ex;

Uses crt;

Var c1,c2:char;

Begin

repeat c1:=ReadKey; {вводим код}

if c1=#0 then {если расширенный код}

begin

c2:=ReadKey; {то читаем расширенный scan-код}

WriteLn(ord(c1):5, ord(c2):5) {выводим расширенный код}

end

else WriteLn(ord(c1):5) {выводим код ASCII}

until c1 =#27;{до нажатия Esc}

End.

Таблица 8.2

Ресурсы модуля crt для управления экраном. - student2.ru

Примечание. Функция ReadKey обрабатывает коды из буфера BIOS клавиатуры, поэтому с ее помощью нельзя получить коды нажатия/отпускания отдельных клавиш, не преобразуемых в расширенные scan-коды, например, клавиш смещения, клавиш переключения режимов.

Состояния клавиш смещения и клавиш переключения режимов BIOS фиксирует в байте состояния клавиатуры (табл. 8.2), который расположен в

оперативной памяти по адресу $0:$417.

Для прямого обращения к этому байту можно использовать стандартно объявленный массив Mem:array of byte, например: Mem[$0:$417], или наложить некоторую переменную на интересующий нас байт оперативной памяти:

Var KeyState:byte absolute $0:$417; … .

Управление динамиком

Модуль crt также содержит процедуры, обеспечивающие управление динамиком.

1. Процедура Sound (f:word) - генерирует звук указанной частоты в Гц.

Для справки, основной гамме соответствуют следующие частоты: нота «до» основной октавы - 330 Гц, далее - 349 Гц, 370 Гц, 392 Гц, 415 Гц, 440 Гц, 466 Гц, 494 Гц, 523 Гц, 554 Гц, 588 Гц, 622 Гц и, наконец, нота «до» следующей октавы - 660 Гц. Частоты нот других октав кратны частотам основной.

2. Процедура NoSound - выключает динамик.

3. Процедура Delaу (t:word) - обеспечивает задержку на заданный интервал времени, мс.

Поскольку к настоящему моменту времени быстродействие компьютеров существенно возросло и изменились некоторые принципы их построения, процедура Delay не всегда обеспечивает корректную задержку, как видно из последующей программы. В этих случаях для организации задержки целесообразно использовать процедуру, которая читает реальное время.

4. Процедура GetTime (VarHour, Minute, Second, Sec100:word) – возвращает текущее время суток. Определена в модуле Dos.

Пример 8.3.Разработать программу проигрывания основной октавы.

Проигрывание гаммы осуществляется включением и выключением динамика с разными частотами.

Program ex;

Uses Crt;

Const f: array[1..13] of word = (330, 349, 370, 392, 415, 440,

466, 494, 523, 554, 588, 622, 660);

Var i:byte;

Begin for i:=1 to 13 do

begin

Sound(f[i]);

for j:=1 to 5000 do Delay(1000);{задержка ?!}

NoSound;

end;

End.

Чтобы не подбирать время задержки для конкретного компьютера, построим свою процедуру обеспечения требуемой задержки, использующую процедуру GetTime:

Program ex;

Uses Crt, Dos;

Procedure NewDelay(dTime:word);

Var key:boolean;

Hour, Min, Sec, Sec100, MyHour, MyMin, MySec, MySec100: Word;

Begin

GetTime(Hour, Min, Sec, Sec100); {узнаем текущее время}

{определяем время завершения задержки}

MySec100:=Sec100+dTime; MySec:=Sec+MySecl00 div 100;

MySec100:=MySec100 mod 100;

MyMin:=Min+MySec div 60; MySec:=MySec mod 60;

MyHour:=Hour+MyMin div 60; MyMin:=MyMin mod 60;

key:=false;

while not key do {цикл задержки}

Begin

GetTime(Hour, Min, Sec, Sec100); {узнаем текущее время}

{проверяем, наступил ли заданный момент}

if (Ноиr>МуНоиr) or ((Ноиr=МуНоиr) and ((Min>MyMin) or

((Min=MyMin) and ((Sec>MySec) or

((Sec=MySec) and ((Sec100>=MySec100)))))))

then key:=true;

End

End;

Const farray[1..13] of word = (330, 349, 370, 392, 415, 440,

466, 494, 523, 554, 588, 622, 660);

Var i:byte; j:integer;

{описываем массив окон пунктов меню}

Const menu:array[1..4] of win=

((x1:5;y1:4;x2:15;y2:4;text: 'new '),

(x1:5;y1:5;x2:15;y2:5;text: 'open'),

(x1:5;y1:6;x2:15;y2:6;text: save'),

(x1:5;y1: 7;x2:15;y2:7;text: 'exit'));

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

Procedure DrawWin(w:win;attr:byte);

Begin

with w do

begin

TextAttr:=attr; {устанавливаем атрибут окна пункта}

Window(xl,у1,х2,у2); {устанавливаем окно пункта}

Clrscr; {высвечиваем окно пункта}

GotoXY(2,1); {устанавливаем курсор}

Write(text); {выводим название пункта}

end;

End;

{процедура рисования меню с выделенным пунктом npos}

Procedure DrawMenu(npos: integer);

Begin

Clrscr;

for i:=1 to 4 do

if i=npos then DrawWin(menu[i],94) {выводим выделенный пункт}

else DrawWin (menu[i], 30); {выводим невыделенный пункт}

End;

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

Begin

npos:=1; {выделенный пункт меню}

DrawMenu(npos); {выводим меню}

repeat

ch1:=ReadKey; if ch1=#0 then ch2:=ReadKey;

case ch1 of

#0: case ch2 of

#72: begin {стрелка вверх}

if npos>1 then {если не верхний пункт}

begin

DrawWin(menu[npos],30); {убираем выделение текущего пункта меню}

npos:=npos-1; {переходим к предыдущему пункту}

DrawWin(menu[npos],94); {выделяем новый пункт}

end;

end;

Begin for i:=l to 13 do

begin

Sound(f[i]):

NewDelay(50);

NoSound;

end;

End.

Наши рекомендации