Pascal-Toolbox Nr. 3
(Meldungs-) Fenster ohne Turbo Vision (DOS)
Diesmal wollen wir eine Unit erstellen, die uns die bekannten
Meldungsfenster mit Schatten erstellt.
Ich habe hierbei auf Mausunterstützung, Cursorabschaltung
(demnächst in einer Toolbox zu finden...) und Buttons verzichtet, da dies (a) zu umfangreich
werden würde und (b) bei Bedarf relativ schnell realisiert werden kann.
Zuerst erstellen wir den Unit-Kopf mit der Angabe der
öffentlichen Prozeduren. Diese sind PopUp und MessageBox. Erstere erzeugt ein Fenster mit
Schatten und Titel, letztere erzeugt unter Verwendung von PopUp ein Meldungsfenster mit Titel sowie
Text- und Tastenzeile.
UNIT Fenster;
INTERFACE
PROCEDURE PopUp (XX, YY, Breit, Hoch:Integer; Title:String; BkColor, Color:Word);
PROCEDURE MessageBox(Title, InfoText, Tasten:String; BkColor, Color:Byte);
IMPLEMENTATION
USES DOS,CRT;
Zuerst definieren wir die Hilfsfunktionen:
Für den Schatten benötigen wir eine Prozedur, die den
Bildschirminhalt an bestimmten Stellen auslesen kann. ReadChar übernimmt diese Aufgabe.
Über Interrupt $10 (Funktion $8) läßt sich das
Zeichen an der aktuellen Cursorposition auslesen. Es ist nur vorher die aktuelle Bildschirmseite in
das Register BH einzutragen, welche wir aus dem BIOS-Datenbereich entnehmen. Als Ergebnis liefert der Aufruf das
Char (in AL) und dessen Attribut (in AH) an der aktuellen Cursorposition.
PROCEDURE ReadChar(VAR Wort, Color:Byte);
VAR D,C,Seite:Byte;
BEGIN
Seite:=Mem[$0040:$62];
ASM
Mov AH,$08;
Mov BH,Seite;
Int $10;
Mov C,AL;
Mov D,AH;
END;
Wort:=C;
Color:=D;
END;
Diese grundlegende Prozedur verwenden wir nun in der folgenden
Prozedur, welche den Text an der aktuellen Cursorposition schattenartig verdunkelt.
Das Zeichen an der Position wird ausgelesen, die entsprechenden Textattribute für Schatten
gesetzt und das Zeichen mit den neuen Attributen geschrieben.
PROCEDURE MakeShadow;
VAR A,B:Byte;
BEGIN
ReadChar(A,B);
TextColor (Darkgray);
TextBackground (Black);
Write (Chr(A));
END;
Für die Zentrierung von Text benötigen wir später die
folgende Funktion. Sie tut nichts weiter, als den übergebenen String zentriert in der
aktuellen Zeile auf dem Bildschirm auszugeben.
PROCEDURE Center(Wort:String);
BEGIN
GotoXY (40-(Length(Wort) DIV 2),WhereY);
Write (Wort);
END;
Jetzt geht's los.
In der folgenden Funktion wird das Fenster erstellt und mit Titel und Schatten versehen.
PROCEDURE PopUp (XX, YY, Breit, Hoch:Integer; Title:String; BkColor, Color:Word);
VAR X,I:Integer;
Middle:ShortInt;
OldColor:Byte;
(XX:YY) gibt den Ursprung des Fensters an, Breit die
Breite, Hoch die Höhe (jeweils in Zeichen), Title den Titel, der über dem
Fenster stehen soll, BkColor die Hintergrund- und Color die Vordergrundfarbe.
X und I sind Hilfsvariablen, Middle dient zur Zentrierung des Titels,
OldColor speichert die ursprünglichen Textattribute zwischen (sonst muß
später nach Aufruf der Prozedur immer TextColor aufgerufen werden, und das ist ja nicht im
Sinne des Erfinders :-))
BEGIN
OldColor:=TextAttr;
TextColor (Color);
TextBackground (BkColor);
GotoXY (XX,YY);
Write (#201);
FOR I:=1 TO Breit DO Write (#205);
Writeln (#187);
FOR X:=1 TO Hoch DO BEGIN
GotoXY (XX,YY+X);
Write (#186);
FOR I:=1 TO Breit DO Write (' ');
Writeln (#186);
END;
GotoXY (XX,YY+Hoch+1);
Write (#200);
FOR I:=1 TO Breit DO Write (#205);
Write (#188);
IF Title<>'' THEN BEGIN
Middle:=Length(Title) DIV 2;
GotoXY (XX+(Breit DIV 2)-Middle,YY);
Write (' ',Title,' ');
END;
Zuerst werden die aktuellen Textattribute aus der Konstante TextAttr
gesichert. Dann werden die neuen Farben gesetzt und das Fenster gezeichnet (mit einer
Übersicht über die einzelnen Zeichenwerte kann ich leider nicht dienen, schaut einfach
mal in einer ASCII-Tabelle nach). Zum Schluß wird noch, wenn vorhanden, der Titel zentriert
auf das Fenster gesetzt.
FOR I:=1 TO Hoch+2 DO BEGIN
GotoXY (XX+Breit+2,YY+I);
MakeShadow;
GotoXY (XX+Breit+3,YY+I);
MakeShadow;
END;
FOR I:=1 TO Breit+1 DO BEGIN
GotoXY (XX+I+1,YY+Hoch+2);
MakeShadow;
END;
TextColor (OldColor MOD 16);
TextBackground (OldColor DIV 16);
END;
Jetzt wird der Schatten erzeugt. Aufgrund des Dos-Zeichenformats
(8x16) brauchen wir in der Breite doppelt so viele verdunkelte Zeichen wie in der Höhe, damit
ein einheitliches Bild entsteht. Am Ende werden dann nur noch die Textattribute wieder
zurückgesetzt.
Jetzt kommen wir zu der Meldungsbox-Prozedur:
PROCEDURE MessageBox(Title, InfoText, Tasten:String; BkColor, Color:Byte);
VAR X,XX,Posi:ShortInt;
OldColor:Byte;
Title gibt wieder den Titel an, InfoText den Text, der
angezeigt werden soll, Tasten kann entweder noch zusätzlichen Text enthalten oder die
Tasten anzeigen, die gedrückt werden sollen (z.B. "Beliebige Taste drücken zum
Fortfahren!"), BkColor und Color geben wieder die Farben des Fensters an.
Position und Größe des Fensters brauchen nicht angegeben werden, da die Prozedur das
Fenster automatisch anpaßt und zentriert.
OldColor sichert wieder die TextAttribute, X, XX, Posi sind Hilfsvariablen.
BEGIN
OldColor:=TextAttr;
X:=0;
Posi:=1;
IF Length(InfoText)>=Length(Title) THEN X:=Length(InfoText)
ELSE X:=Length(Title);
IF (X<Length(Tasten)) THEN X:=Length(Tasten);
X:=X+6;
IF Odd(X) THEN Dec(X);
XX:=40-(X DIV 2);
IF Odd(XX) THEN Dec(XX);
PopUp (XX,10,X,5,Title,BkColor,Color);
TextColor (Color); TextBackground (BkColor);
GotoXY (1,12);
Center (InfoText);
GotoXY (1,14);
Center (Tasten);
TextColor (OldColor MOD 16);
TextBackground (OldColor DIV 16);
END;
END.
Zuerst werden wieder die Textattribute gesichert. Als nächstes
wird bestimmt, welcher der drei übergebenen Strings der längste ist und dessen Länge
in X gesichert. Dieser Wert wird dann um 6 Einheiten erhöht und in eine gerade Zahl
umgewandelt (wenn nötig; Funktion Odd bzw. Dec), damit der Text nicht bündig mit dem Rand
des Fensters ist, sondern mehr im Fenster ist. Dann wird X halbiert, auf eine gerade
Zahl gebracht und in XX gesichert. Nun wird ein Fenster (mittels PopUp) erzeugt, und zwar
mit X als Breite und XX als X-Koordinate. Die Y-Koordinate sowie die Höhe sind
standardisiert und brauchen nicht verändert werden.
Nach Aufruf der Prozedur PopUp werden erneut die Farben für das Fenster gesetzt (PopUp hat ja
schön brav alles wiederhergestellt), um noch die Inhalte von InfoText und Tasten
mittels der Prozedur Center in das Fenster zu plazieren. Danach werden dann wieder die alten
Textattribute wiederhergestellt.
Die Prozeduren sind damit komplett.
Ein Testprogramm könnte dann zum Beispiel so aussehen:
USES Crt,Fenster;
VAR X,Y:Integer;
BEGIN
TextBackGround (Lightgray);
TextColor (White);
ClrScr;
FOR X:=1 TO 79 DO
FOR Y:=1 TO 24 DO BEGIN GotoXY(X,Y); Write (Chr(Random (26)+65)); END;
MessageBox ('Wichtige Meldung','Dies ist ein Test','Beliebige Taste fährt fort...',Blue,Yellow);
ReadKey;
TextBackGround (Black);
TextColor (Lightgray);
ClrScr;
END.
Anmerkung: die ersten Zeilen (bis Write (Chr(Random...) sind
nur dazu da, den Schatteneffekt zu verdeutlichen.
Einschränkungen der Prozeduren: Es erfolgt keine
Prüfung, ob (a) die Texte länger als 80 Zeichen sind (unschöne Bildschirmausgabe)
oder (b) ob das Fenster komplett auf den Bildschirm paßt.
Diese Prüfungen muß das aufrufende Programm durchführen (oder sie müssen in
diese Prozeduren nachträglich noch eingebaut werden).
Die fertige Unit (ca. 2 KB) könnt Ihr hier downloaden.
Alle Angaben ohne Gewähr. |