Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник по Паскалю.doc
Скачиваний:
36
Добавлен:
16.12.2018
Размер:
2.17 Mб
Скачать

23.2. Стандартные модули Паскаля

В состав Паскаля входит ряд стандартных модулей, перечислим некоторые из них:

  • dos -- в модуле dos находятся подпрограммы взаимодействия с операционной системой и обработки файлов;

  • strings -- модуль обеспечивает поддержку символьных строк, завершающихся нулевым байтом;

  • graph -- в модуле находится библиотека, состоящая из более, чем 50 графических подпрограмм для рисования различных геометрических фигур;

  • crt -- подпрограммы модуля обеспечивают контроль над текстовыми режимами экрана, расширенными кодами клавиатуры, цветами, окнами и звуком;

  • printer -- знакомый нам ранее модуль, служащий для программного вывода на принтер.

Чтобы использовать любой из этих модулей, его достаточно подключить оператором uses.

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

24. Модуль crt и создание консольных интерфейсов

Модуль crt содержит процедуры и функции, предназначенные для работы с экраном консоли в текстовом режиме. Как и ряд других стандартных модулей, crt встроен в компилятор и содержится в файле turbo.tpl.

Экран в текстовом режиме разбивается на отдельные строки, а каждая строка -- на позиции, причем в каждую позицию может быть помещен только 1 символ из набора ASCII.

Для полного описания экранной позиции кроме символа следует задать еще и атрибут, содержащий информацию о цвете символа и фона на экране. Символ и атрибут занимают в памяти по 1 байту. Структура байта-атрибута показана на рис. 24.1.

Рис. 24.1. Структура байта-атрибута консоли

Старший бит 7 управляет мерцанием символа (символ на экране мерцает, если он установлен в 1), биты 4-6 содержат цвет фона (кодируется двоичными числами от 0 до 7 включительно), а биты 0-3 -- цвет символа (от 0 до 15). Разумеется, программисту обычно не приходится заполнять байт атрибута по битам, для этого есть стандартные коды цветов. Основные цвета кодируются цифрами от 0 до 15, причем цвет текста может быть любым, а цвет фона -- только из первых 8 цветов. Все цвета описаны в табл. 24.1.

Табл. 24.1. Коды и наименования стандартных цветов

Код

Наименование

Цвет

0

BLACK

черный

1

BLUE

синий

2

GREEN

зеленый

3

CYAN

циановый

4

RED

красный

5

MAGENTA

фиолетовый

6

BROWN

коричневый

7

LIGHTGRAY

светло-серый

8

DARKGRAY

темно-серый

9

LIGHTBLUE

голубой

10

LIGHTGREEN

светло-зеленый

11

LIGHTCYAN

светло-циановый

12

LIGHTRED

светло-красный

13

LIGHTMAGENTA

светло-фиолетовый

14

YELLOW

желтый

15

WHITE

белый

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

Широко используемые текстовые режимы имеют в окне консоли 25 строк по 80 столбцов (позиций) в строке. Нумерация строк и позиций начинается с 1 и считается слева направо и сверху вниз. Весь экран в текстовом режиме может быть описан парой координат (1, 1), (80, 25). Обратите внимание на порядок записи -- столбец, затем строка.

Ниже рассмотрены основные процедуры и функции модуля. Везде для краткости введены следующие обозначения:

x,x1,x2 -- координаты столбцов экрана;

y,y1,y2 -- координаты строк экрана;

c -- значение цвета.

Особенность модуля crt состоит в том, что он позволяет работать не только со всем экраном, но и с выделенным на нем прямоугольным окном. При этом весь ввод, вывод и прокрутка текста происходят в пределах окна. По умолчанию размеры окна совпадают с размерами экрана, но можно явно установить их обращением к стандартной процедуре Window (x1,y1,x2,y2);, где (x1, y1) и (x2, y2) -- соответственно, левый верхний и правый нижний угол окна.

Цвет фона окна c задает процедура textbackground ( c );, а цвет символов -- textcolor ( c );.

Процедура без параметров clrscr; очищает текущее окно цветом фона.

Для установки текстового курсора в позицию окна с координатами (x, y) определена процедура gotoxy (x,y);.

Программно определить текущее положение курсора позволяют 2 стандартные функции Wherex:char; и Wherey:char;, возвращающие, соответственно, текущие x- и y-координату курсора.

Процедура ClrEol; удаляет все символы от позиции курсора до конца строки включительно, заполняя этот участок цветом фона.

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

Процедура Sound (F:word); включает встроенный динамик с частотой F герц, обеспечивая выдачу звукового сигнала.

Процедура Delay (T:word); задает задержку выполнения программы, равную T миллисекунд (1000 мс = 1 сек.). Эта процедура используется для организации задержек выполнения программы, а также всегда вызывается после sound, чтобы определить время звучания динамика.

Процедура без параметров NoSound; выключает динамик. Обязательно используется после пары Sound и Delay.

Наконец, в модуле crt определены 2 стандартных функции для работы с кодами нажатых клавиш. Функция readkey:char; возвращает код символа, прочитанный из буфера клавиатуры. Функция keyPressed:boolean; возвращает значение true, если была нажата клавиша на клавиатуре (за исключением вспомогательных клавиш Alt, Shift, Ctrl и т. д.). Использование последней функции позволяет организовать циклы, выполняющиеся до нажатия какой-либо клавиши.

При запуске программы из оболочки Паскаля монитор находится обычно в текстовом режиме и устанавливать его не нужно. Тем не менее, существует стандартная процедура textMode (Mode:integer), устанавливающая текстовый режим с номером Mode.

Стандартный цветной текстовый режим 25*80 позиций имеет номер 3, цветной текстовый режим 25*40 позиций -- номер 1.

Модуль crt содержит также системные переменные, которые можно изменять в соответствии с указанным для них типом.

Переменная CheckBreak:boolean; управляет реакций программы на прерывание по сочетанию клавиш Ctrl+Break. По умолчанию переменная имеет значение true (реакция включена).

Если переменная DirectVideo:boolean; имеет значение true, процедуры вывода на экран пишут данные непосредственно в видеопамять, не используя операционную систему. Это ускоряет вывод, но может использоваться только на полностью IBM-совместимых ЭВМ.

Переменная textAttr:integer; содержит текущий атрибут текста, сформированный по описанным выше правилам.

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

uses crt;

var ch : char; {Символ, который вводим}

begin

clrscr; {Очистили экран}

writeln ('Программа выводит коды клавиш;',

' Esc - выход.');

repeat

writeln('Нажмите клавишу:');

ch := readkey; {Ждем ввода символа}

if ch = #0 then {Если нажата спец.

клавиша, то функция вернула 0,}

begin

ch := readkey; {и нужно прочитать код

символа дополнительно}

writeln('Нажата специальная клавиша ',

'с кодом ', ord(ch));

end

else {Иначе если нажата обычная клавиша –

сразу видим ее код}

writeln('Нажата клавиша с ASCII-кодом',

' ',ord(ch));

until ch=#27; {Значение 27 –

это код клавиши Escape}

writeln ('До свидания.');

end.

Как правило, в реальных программах широко используются небуквенные клавиши, такие как Enter, F1, Esc и т. д. Узнать их коды можно из таблиц ASCII-символов. Например, код клавиши Escape равен #27. Для записи клавиатурного кода на Паскале перед его значением ставится символ #, как сделано в этом примере. Более подробно об обработке нажатий клавиш рассказано в Приложении 5. Листинги 5-8 из Приложения 4 также иллюстрирует основные аспекты обработки нажатий клавиш.

В качестве развернутого примера использования функций модуля crt напишем программу, которая заполняет экран случайными цветными окнами, а также является примером проигрывания несложной "музыки" через встроенный динамик компьютера. Для рисования рамок в этой программе используются символы псевдографики, которые есть только в кодировке DOS (см. Приложение 1).

Program crt_example;

uses crt;

const minLen=10; {минимальная длина окна}

pause=500; {задержка при выводе звука}

blink=128; {установка бита мерцания}

var x1,y1,x2,y2 :integer;

{координаты окна}

background, {цвет фона окна}

color, {цвет текста}

freq, {частота звука}

setblink :integer; {есть/нет мерцание}

procedure doubleFrame (x1,y1,x2,y2:integer;

Header: string);

{Процедура рисует двойной рамкой окно

с заголовком и подготавливает его

внутреннюю часть для ввода текста}

{ x1,y1,x2,y2 - координаты окна}

{ header - заголовок окна}

var i,j: integer;

begin

Window (1,1,80,25);

{Рисуем верхнюю строку рамки }

gotoxy (x1,y1); write ('╔');

for i:=x1+1 to x2-1 do write('═');

write ('╗');

{Перебираем строки внутри окна}

for i:=y1+1 to y2-1 do begin

gotoxy (x1,i); write('║');

for j:=x1+1 to x2-1 do write (' ');

{Внутренность окна - пробелы}

write('║'); {Правая граница}

end;

{Аналогично рисуем нижнюю строку}

gotoxy (x1,y2); write('╚');

for i:=x1+1 to x2-1 do write('═');

write('╝');

gotoxy (x1+(x2-x1+1-Length(Header))

div 2,y1);

{Ставим курсор в середину верхней строки}

write (Header); {Выводим заголовок}

Window (x1+1,y1+1,x2-1,y2-1);

{Устанавливаем текущее окно внутри рамки}

gotoxy (1,1);{Ставим курсор в левый

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

end;

begin

textbackground (BLACK);

Window (1,1,80,25);

{окно вывода - весь экран}

clrscr;

{Инициализируем генератор случайных чисел}

randomize;

DirectVideo:=true;

while not keyPressed do begin

{Пока не нажата клавиша,

выполняется цикл}

x1:= 1 + random(80-minLen);

x2:=x1 + minLen + random (80-x1-minLen);

y1:= 1 + random(25);

y2:= 1 + y1 + random (25-y1);

{Выбрали случайные координаты окна }

background:=random(8);

color:=random(16);

{Выбрали цвет фона и текста}

setblink:=random(2);

{Выбрали установку мерцания ДА или НЕТ}

textbackground (background);

textcolor(color+blink*setblink);

{Цвет текста с учетом мерцания}

doubleFrame (x1,y1,x2,y2,' Hello! ');

{Рисуем окно с помощью процедуры}

background := (textAttr and 112) shr 4;

{ Из байта цвета, содержащегося в

переменной textAttr, выделяем цвет

фона. Операция shr xx сдвигает

байт вправо на xx бит, а 112 в

двоичной системе это 01110000

(включены биты, отвечающие за фон) }

case background of

{ В зависимости от цвета фона выбираем

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

0: freq:=262; {Частота ноты До}

1: freq:=294; { -"- Ре}

2: freq:=330; { -"- Ми}

3: freq:=349; { -"- Фа}

4: freq:=392; { -"- Соль}

5: freq:=440; { -"- Ля}

6: freq:=494; { -"- Си}

7: freq:=524; { -"- До}

end;

sound (freq); {Включаем динамик}

Delay (pause);

{Ждем, пока не истечет задержка}

Nosound; {Выключаем динамик!}

end; {Конец основного цикла}

{Восстанавливаем атрибуты текста и окно}

textbackground (BLACK);

textcolor (LIGHTGRAY);

Window (1,1,80,25);

clrscr;

end.

Использование этой программы на современном быстром процессоре может и не дать вам насладиться "космической музыкой" -- проблема в реализации функции Delay, учитывающей не реально прошедшее время в миллисекундах, а "условное" время, связанное с тактовой частотой процессора. Для исправления ситуации следует написать и применять собственную реализацию Delay, привязанную к функции GetTime модуля dos, позволяющей получить "абсолютное" системное время в часах, минутах, секундах и сотых долях секунды. Ниже приводится одна из возможных версий такой функции с комментариями основных действий и тестом:

uses crt,dos;

function getlongintTime:longint;

{Вернет системное время как longint}

var Hour,minute,second,sec100: word;

var k,r:longint;

begin

GetTime (Hour, minute, second, sec100);

{Прямое вычисление по формуле

Hour*360000+minute*6000+second*100+sec100

не сработает из-за неявного

преобразования word в longint:}

k:=Hour; r:=k*360000;

k:=minute; Inc (r,k*6000);

k:=second; Inc(r,k*100);

Inc(r,sec100); getlongintTime:=r;

end;

procedure MyDelay (ms:word);

{Корректно работает с задержками

до 65 сек.!}

var endTime,curTime : longint;

cor:boolean; {признак коррекции времени

с учетом перехода через сутки}

begin

cor:=false;

endTime:=getlongintTime + ms div 10;

if endTime>8639994 then cor:=true;

{Учитываем возможный переход через сутки;

23*360000+59*6000+59*100+99=8639999 и

отняли 5 мс с учетом частоты срабатывания

системного таймера BIOS}

repeat

curTime:=getlongintTime;

if cor=true then begin

if curTime<360000 then

Inc (curTime,8639994);

end;

until curTime>endTime;

end;

var Hour,minute,second,sec100: word;

begin

clrscr;

{setTime (23,59,58,99);}

{если раскомментарить – может изменить

системное время!}

repeat

gotoxy (1,1);

GetTime (Hour, minute, second, sec100);

write (Hour:2, ':', minute:2, ':',

second:2, ':',sec100:2, ' ');

MyDelay (500);

until keypressed;

end.

В Приложении 4 приведены также листинги программ для вывода кодов часто используемых клавиш, движения по экрану "прицела" с помощью клавиш со стрелками, а также программа создания несложного двухуровневого меню пользователя (листинги 5-7).