Приложение Л. Использование модулей CRT, DOS и PRINTER для организации интерфейса программ

 

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

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

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

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

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

· math – модуль содержит много дополнительных математических, тригонометрических и статистических функций;

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

· wincrt – модуль для поддержки терминал подобного текстового окна в экране. При этом не нужно писать специальный код для поддержки окон.

 

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

 

Модуль CRT

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

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

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

VAR TextAttr : BYTE,

в которой содержится текущий цвет фона и цвет символов, используемые при выводе на экран процедурами WRITE и WRITELN. Изменив эту переменную, вы задаете новый цветовой атрибут. Цветовой атрибут строится следующим образом : в четырех младших битах хранится цвет символов (от 0 до 15), в следующих трех битах - цвет фона (от 0 до 7), и старший бит отвечает за мерцание. Пусть, например, значение переменной TextAttr равно 237, в двоичной записи - это 1110 1101 (если записывать биты от старшего к младшему). Четыре младших бита (1101) дают цвет символов 13, или LightMagenta - светло малиновый; следующие 3 бита (110) дают цвет фона 6, или Brown - коричневый, старший бит - единичный. Таким образом, будут выводиться мерцающие светло-малиновые символы на коричневом фоне.

Цветовые константы Black ... White определены в CRT точно так же, как и в модуле Graph. Кроме того, определена константа мерцания Blink = 128.

Теперь построим другой цветовой атрибут: мы хоти вывести желтые мерцающие символы на светло-сером фоне. Переменной TextAttr необходимо присвоить значение 14 (желтые символы) +7 (серый фон) * 16 + 128 (мерцание), итого: 14+112+128=254. Столь сложных вычислений легко избежать, если пользоваться 16-ричными числами; наш атрибут в 16-ричном виде записывается как $7E+Blink. Можно обращаться к цвету как по цифровому коду, так и по англоязычному имени.

Структура байта-атрибута показана на рис. Л.1.

 

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

 

Рассмотрим некоторые функции и процедуры модуля CRT:

1. FUNCTION KeyPressed : Boolean - возвращает TRUE, если буфер клавиатуры не пуст (все нажатия клавиш во время работы программы накапливаются в специальном участке памяти - буфере клавиатуры, откуда затем поступают в программу). Функция не очищает буфер клавиатуры!

2. FUNCTION ReadKey : Char - считывает символ из буфера клавиатуры, если буфер пуст, то ожидает нажатия клавиши. Эту функцию удобно использовать для организации пауз в программе.

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

3. PROCEDURE Delay(MS: Word) - приостанавливает выполнение программы на MS миллисекунд.

4. PROCEDURE Sound(Hz: Word) - генерирует звуковой сигнал с частотой Hz герц.

5. PROCEDURE NoSound - выключает звуковой сигнал.

6. PROCEDURE Window(X1,Y1,X2,Y2:Byte) - определяет на экране текстовое окно, заданное координатами верхнего левого и нижнего правого углов. Модуль CRT позволяет работать не только со всем экраном, но и с выделенным на нем прямоугольным текстовым, куда направляется весь вывод. Процедура не выполняет никаких видимых действий!

Координата верхнего левого угла экрана равна (1, 1). Минимальный размер текстового окна - один столбец на одну строку. Если какая-либо координата недопустима, то обращение к процедуре Window игнорируется. Заданное по умолчанию окно (1, 1, 80, 25) в режиме 25-и строк и (1, 1, 80, 43) в режиме 43-х строк, что соответствует всему экрану.

7. PROCEDURE TextBackground(Color: Byte) - задает цвет фона для всего последующего вывода.

8. PROCEDURE TextColor(Color: Byte) - задает цвет символов для всего последующего вывода. Процедуры TextBackground и TextColor вместе обеспечивают те же возможности, что и переменная TextAttr.

9. PROCEDURE ClrScr - очищает текущее окно, используя текущий фоновый цвет.

10. PROCEDURE GotoXY(X,Y:Byte) - перемещает курсор в позицию X строки Y текущего окна. Координаты отсчитываются от левого верхнего угла окна.

Все экранные координаты, кроме координат самого окна, являются зависимыми относительно текущего окна. Например, GotoXY(1, 1) всегда будет устанавливать курсор в верхний левый угол текущего окна.

11. FUNCTION WhereX : Byte и

12. FUNCTION WhereY : Byte  - возвращают текущие относительные координаты курсора (позицию и строку).

13. PROCEDURE DelLine - удаляет строку окна, в которой находится курсор, все нижние строки автоматически смещаются вверх.

14. PROCEDURE InsLine - вставляет пустую строку перед строкой, в которой находится курсор, все нижние строки автоматически смещаются вниз, и последняя строка окна теряется.

Многие процедуры и функции Crt являются относительными к текущему окну, включая ClrEol, ClrScr, DelLine, GotoXY, InsLine, WhereX, WhereY, Read, Readln, Write и Writeln. В переменных WindMin и WindMax хранятся текущие размеры окна. При обращении к процедуре Window, курсор всегда перемещается в позицию (1,1).

При запуске программы из оболочки Паскаля монитор уже находится в текстовом режиме и устанавливать его не нужно. Тем не менее, существует стандартная процедура TextMode (Mode:integer), устанавливающая текстовый режим с номером Mode. Стандартный цветной текстовый режим 25*80 позиций имеет номер 3, цветной текстовый режим 25*40 позиций - номер 1.

 

Программа, очищающая экран и печатающая слово ПРИВЕТ! в заданном месте экрана.

Program Primer_crt1;

Uses Crt;

  Begin

   clrscr;

   GotoXY(20, 10);

   WriteLn('Привет!');

End.

 

Пример программы, которая рисует улитку Паскаля в текстовом режиме при помощи символа *.

Program primer_crt2;
Uses Crt;
Const X=40;Y=14;
Var I:Integer;
Begin
   ClrScr;
   For I:=0 To 200 Do
      Begin
      GotoXY(X+Round(Sin(I/9)*I/9),Y+Round(Cos(I/9)*I/15));
      Write('*');
      Delay(1000);
     End;
   ReadLn;
End.

 

Пример программы с процедурой Window. В программе создаются произвольного размера окна, которые закрашиваются произвольным цветом. Обратите внимание, что после объявления нового активного окна, процедура ClrScr работает уже для этого окна, а не для всего экрана.

Program Primer_crt3;

  Uses Crt;

  Var X, Y : byte;

  Begin

   TextBackground(Black);   // цвет фона черный

   ClrScr;

   Repeat

      X:=succ(Random(80)); // начальная координата окна меньше пределов

      Y:=succ(Random(25));

      Window(X, Y, X + Random(15)+1, Y + Random(10)+1);

      TextBackground(Random(16));   // цвет фона окна

      Delay(200);

      ClrScr;

    Until KeyPressed;

End.

 

Использование звуковых сигналов.

Program Primer_crt4;

Uses Crt;

Var I:Integer;

Begin

  For I:=0 To 80 Do

    Begin

     Sound(200+100*i); {Звук с нарастающей частотой от 200 Гц}

     Delay(1000);  {задержка}

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

   End;

End.

 

Покажем также несколько примеров программ с более серьезным интерфейсом.

Первая программа распознает коды нажатых клавиш, включая коды расширенных клавиш, таких как F1, F2, стрелки направления, Home, End и т.п.

Program Primer_crt5;

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}

end.

 

Вторая программа загадает число, а пользователь должен его отгадать.

Program Game;

USES Crt;

VAR X,F : Byte;

          S : STRING;

          Code : Integer;

          Yes  : Boolean;

BEGIN

   Window(1,1,60,20); // создаем новое окно

   TextBackground(7); // серого цвета

   ClrScr; {очистим экран}

   RANDOMIZE; F:=RANDOM(10); {загадаем число}

   Window(26,11,54,13);  // создаем еще одно новое окно

   TextAttr:=$20;      // зеленого цвета

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

        REPEAT

           GotoXY(3,2);

           WRITE('Введите число от 0 до 9 ');

           READLN(S); VAL(S,X,Code);

               IF (Code=0)AND(X=F) THEN

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

                         ClrScr;

                         GotoXY(8,2);

                         WRITE('Вы угадали !!!');

                         REPEAT UNTIL KeyPressed;

                         HALT;

                        END;

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

                TextAttr:=$4F+Blink;

                ClrScr;  Sound(500); GotoXY(11,2);

                WRITE('ошибка !'); Delay(500); NoSound;

               {запрос на повторение}

               TextAttr:=$20; ClrScr; GotoXY(6,2);

               WRITE('Сдаетесь ? [Y/N]');

               IF ReadKey IN ['Y','y'] THEN Halt;

        UNTIL FALSE;

END.

 

При построении интерфейса необходимо руководствоваться простыми правилами:

·        на экране не должно быть "мусора" – используйте процедуру ClrScr;

·        пользователь в любой момент работы должен понимать, что от него требуется - выводите подсказки к вопросам;

·        неверный ввод данных не должен приводить к аварийному завершению программы – проверяйте и зацикливайте чтение с клавиатуры;

·        результаты работы должны выводиться в понятном и аккуратном виде.

 

Модуль DOS

Процедура GetTime(var Hour, Minute, Second, Sec100 : Word) - возвращает текущее системное время, установленное в операционной системе.

Процедура GetDate(var Year, Month, Day, DayofWeek : Word) - возвращает текущую системную дату, установленную в операционной системе. Значения DayofWeek: 1 – понедельник, 2 – вторник, 3 - и т.д.

 

Пример:

GetTime(HH, MM, SS, S100);

 

Полученное с помощью процедуры GetTime значение времени можно вывести в заданные координаты экрана в виде "Текущее время: HH-часов, MM-минут, SS-секунд".

 

Program Prim_Dos;

uses crt, dos;

var Hour,minute,second,sec100: word;

begin

   clrscr;

   textcolor(lightblue);

   repeat

     gotoxy (1,1);

     GetTime (Hour, minute, second, sec100);

     writeln ('Текущее время: ',Hour:2, ':', minute:2, ':', second:2);

     write ('Текущее время: ',Hour:2, ' часов ', minute:2, ' минут ', second:2, ' секунд');

     Delay (1000);

   Until keypressed;

end.

 

Модуль PRINTER

Иногда требуется, чтобы программа вывела результаты своей работы на принтер. Для этого в разделе описаний программы следует указать оператор

uses printer;

подключающий стандартную библиотеку для работы с принтером.

При использовании оператора write или writeln необходимо указать символическое имя принтера lst, описанное в библиотеке printer. А точнее, модуль Printer объявляет файловую переменную текстового типа, связанную с портом LPT.

Например, так:

 

write ('Hello');             // строка 'Hello' выведена на экран

write (lst,'Hello');           // строка ‘Hello’ выведена на принтер

 

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

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