Модуль 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. Коды и наименования стандартных цветов
Можно обращаться к цвету как по цифровому коду, так и по англоязычному имени.
Широко используемые текстовые режимы имеют в окне консоли 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).
Читайте также: A) за создание условий неэффективного использования ресурсов Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|