20.4. Работа с образом экрана на диске

Запись текстового экрана на диск часто имеет смысл, если многие программы используют один и тот же сложно заполненный или раскрашенный экран. Записать экран, зная его стартовый адрес и размер, несложно, ибо он занимает сплошной промежуток памяти. Программа на рис. 20.8 показывает, как это сделать.

| USES CRT; { ДЕМОНСТРАЦИЯ ЗАПИСИ /ЧТЕНИЯ ЭКРАНА С ДИСКА }

| {$I get_ptr.inc} {функция GetScreenPtr (см. рис. 20.1) }

| {I get_par.inc) (функция GetScreenSize (см. рис. 20.2) }

| { Процедура сохранения текущего текст-экрана на диске }

| PROCEDURE SaveCurrentScreenOnDisk(FileName : String );

| VAR

| f : File; { бестиповый файл }

| Res : Word; { контрольное число }

| BEGIN

| Assign(f, FileName ); { файл открывается }

| Rewrite(f, GetScreenSize ); { буфер равен экрану }

| { Запись всего экрана как блока по адресу видеопамяти: }

| BlockWrite(f, GetScreenPtr^, 1, Res );

| if Res<> 1 { контроль записи }

| then Writeln(^G 'Сбой при записи'^G);

| Close(f) { закрытие файла }

| END.

Рис. 20.8

- 485 -

| { Процедура считывания текст-экрана с диска на экран. }

| { !!! Процедура не проверяет совпадение режимов }

| { записанного в файле экрана и текущего !!! }

| PROCEDURE LoadScreenFromDisk( FileName : String );

| VAR

| f : File; { бестиповый файл }

| FSize.Res : Word; { размер и контроль }

| BEGIN

| Assign( f, FileName ); { открытие файла }

| Reset( f, 40);

| {Размер буфера чтения 40 - это наименьший общий делитель для размеров видеопамяти в различных текстовых режимах. }

| FSize := FileSize( f ); { число буферов в файле }

| { Чтение всего экрана в ОЗУ по адресу видеопамяти: }

| BlockRead( f, GetScreenPtr^, Fsize, Res);

| if Res<>Fsize { контроль чтения файла }

| then WriteLn( ^G 'Сбой при чтении' ^G };

| Close( f ) { закрытие файла f }

| END;

| VAR { — ОСНОВНАЯ ЧАСТЬ (ПРИМЕР) — }

| j : Byte; с : Char;

| BEGIN

| ClrScr; GotoXY( 1, 5 );

| for c:='A' to 'Я' do { Заполнение экрана: }

| for j:=1 to 40 do begin

| TextAttr := j ; Write( с )

| end; {for for}

| TextAttr := White + 18 * Black;

| SaveCurrentScreenOnDisk('SCREEN.SCN'); {запись на диск }

| Delay(2000); { пауза 2 с }

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

| Delay(1000); { пауза 1 с }

| LoadScreenFromDisk( 'SCREEN.SCN' ); { чтение с диска }

| ReadLn { пауза до нажатия клавиши ввода }

| END.

Рис. 20.8 (окончание)

Рассмотренный пример вполне работоспособен, но имеет один достаток: «готовый» экран находится вне рабочего файла. При создании ЕХЕ-файла это может стать неудобным. Существует возможность включать текстовые изображения непосредственно в ЕХЕ-файл. Для этого надо использовать утилиту BINOBJ.EXE из пакета Турбо Паскаль для преобразования файла с изображением в OBJ-файл:

- 486 -

C:TP> BINOBJ SCREEN.SCN SCREEN.OBJ EXTSCREEN

Первый параметр — исходный файл, второй — имя OBJ-файла, а третий — имя, по которому будет происходить обращение к экрану в программе.

После этого программа должна быть изменена, как на рис. 20.9.

| { ДЕМОНСТРАЦИЯ ВСТАВКИ ГОТОВОГО ЭКРАНА В ПРОГРАММУ }

| USES CRT;

| {$1 get_ptr.inc} { функция GetScreenPtr (см. рис. 20.1)}

| {$1 get_par.inc} { функция GetScreenSize (см. рис. 20.2)}

| {$L screen.obj} { включение OBJ -файла }

| PROCEDURE ExtScreen; EXTERNAL; { в оболочку процедуры }

| { -- ОСНОВНАЯ ЧАСТЬ — }

| BEGIN

| Move( @ExtScreen^, GetScreenPtr^, GetScreenSize );

| { Содержимое процедуры-экрана копируется в видеопамять.}

| { Размер экрана равен текущему. Проверка размера файла-}

| { экрана на соответствие текущему не производится. }

| ReadLn { пауза до нажатия ввода }

| END.

Рис. 20.9

Используя подобные приемы, следует быть уверенными, что они, оправданы. Включение готового экрана в ЕХЕ-файл может занять в нем больше места, чем код рисующей процедуры.