Pascal-Toolbox Nr. 4
Sicherung des Bildschirminhaltes (im DOS-Textmodus)
Diesmal beschäftigen wir uns mit der Bildschirmsicherung. Jeder
kennt das Problem - der aktuelle Bildschirm soll erhalten bleiben, aber gleichzeitig muß eine
Meldungsbox oder etwas ähnliches für kurze Zeit dargestellt werden. Den Bildschirm
hinterher wieder neu zu zeichnen, ist oft nicht möglich. Hier biete ich also eine
Möglichkeit, diesem Problem Abhilfe zu verschaffen. Der Bildschirminhalt wird mittels einer
Funktion gesichert und hinterher wieder zurückgeschrieben. Alle Angaben beziehen sich auf den
Standard-Textmodus (80x25 Zeichen, 16 Farben).
Wir beginnen wie immer mit dem Unit-Kopf. Zuerst legen wir eine
neue, öffentliche Typdefinition namens TScreen an, welche später die
Cursorposition vor dem Sichern enthält sowie alle Bildpunkte. Beachtet werden muß
hierbei die Tatsache, daß in der X-Achse jeweils 160 (und nicht 80!) Byte benötigt
werden, da pro Bildpunkt zwei Informationen (Zeichen & Zeichenattribut) gespeichert werden. Als
nächstes erfolgt dann die Deklaration der beiden öffentlichen Prozeduren,
SaveScreen und WriteScreen.
UNIT Screen;
INTERFACE
TYPE TScreen=RECORD
Punkte:ARRAY[1..25,1..160] OF Byte;
Pos_X,Pos_Y:integer;
END;
PROCEDURE WriteScreen(VAR S:TScreen);
PROCEDURE SaveScreen(VAR S:TScreen);
IMPLEMENTATION
USES CRT;
Weil wir zum Auslesen des Bildschirms später direkt auf den
Bildschirmspeicher zugreifen, benötigen wir einige Angaben vom System. Die folgende Funktion
ermittelt mit Hilfe des Interruptes $10, Funktion $F, den aktuell gesetzten Video-Modus (siehe dazu
auch Tabelle 3: Video-Modi).
FUNCTION DetectMode:Integer;
VAR D:Byte;
BEGIN
ASM
Mov AH,$0F;
INT $10;
MOV D,AL;
END;
DetectMode:=D;
END;
Um die so gewonnenen Daten entsprechend zu verwerten, benötigen
wir noch eine weitere Funktion, GetSchirm. Diese Funktion wertet den Video-Modus dahingehend
aus, daß die Anfangsadresse des Bildschirminhalts im Speicher zurückgeliefert wird. Je
nach Video-Modus ist diese $b000 oder $b800. Diese Funktion beschränkt sich nur auf die Modi
eins bis zehn (im Prinzip verwenden wir eh nur Textmodi mit einer Auflösung von 80x25 Zeichen,
diese Funktion dient nur als "Alibi").
FUNCTION GetSchirm:Word;
VAR Treiber:Integer;
BEGIN
Treiber:=DetectMode;
CASE Treiber OF
1..6,8..9 : GetSchirm:=$b800;
-2,7,10 : GetSchirm:=$b000;
END;
END;
So, beginnen wir mit der Sicherungsprozedur. Zuerst wird die
Anfangsadresse des Bildschirminhaltes im Speicher bestimmt, dann wird mittels des Pascal-Befehls
Mem der Bildschirminhalt zeilenweise aus dem Speicher gelesen. Vorher wird außerdem
noch die Cursorposition gesichert.
PROCEDURE SaveScreen(VAR S:TScreen);
VAR X,Y:Integer;
Schirmanfang:Word;
BEGIN
Schirmanfang:=GetSchirm;
S.Pos_X:=WhereX;
S.Pos_Y:=WhereY;
FOR Y:=1 TO 25 DO
FOR X:=1 TO 160 DO
S.Punkte[Y,X]:=Mem[Schirmanfang:0+((Y-1)*160+X)-1];
END;
Und nun die Schreibeprozedur. Zuerst wird wieder die Anfangsadresse
des Bildschirminhaltes im Speicher bestimmt, dann werden einfach mittels Mem die Daten
wieder an die Stellen zurückgeschrieben, wo sie herstammen. Zum Schluß wird der Cursor
wieder an die alte Position zurückgesetzt.
PROCEDURE WriteScreen(VAR S:TScreen);
VAR Y,X:Integer;
Schirmanfang:Word;
BEGIN
Schirmanfang:=GetSchirm;
FOR Y:=1 TO 25 DO
FOR X:=1 TO 160 DO
Mem[Schirmanfang:0+((Y-1)*160+X)-1]:=S.Punkte[Y,X];
GotoXY (S.Pos_X,S.Pos_Y);
END;
END.
So, das war's schon.
Angewandt wird das Ganze wie folgt:
PROGRAM Test;
USES CRT,Screen;
VAR S1:TScreen; {Die Variable, die den Bildschirminhalt aufnimmt!}
{...}
BEGIN
{...Bildschirmaufbau etc....}
SaveScreen(S1); {Sicherung des Screens}
{...Temporäre Bildschirmveränderungen...}
WriteScreen(S1); {Wiederherstellung des Screens}
{...}
END.
Die fertige Unit (ca. 1,5 KB) könnt Ihr hier downloaden.
Alle Angaben ohne Gewähr. |