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