

Units zum II. oder: Programmierung in Abschnitten


In dem letzten Teil haben wir uns ja mit den grundlegenden
Dingen in Sachen Unit-Programmierung beschftigt. Diesesmal
wollen wir mit Hilfe einiger Wiederholungen die Benutzung von
Units vertiefen und einiges mehr hinzulernen.

ALLE: "Jawohl, Herr Lehrer!"

Also, wie schon gesagt: Units werden mit Hilfe der USES-Anwei-
sung eingebunden, nachdem sie ins TPU-Format mit Hilfe der Taste
'F9' compiliert wurden. Man kann also die im INTERFACE-Teil de-
klarierten Prozeduren und Funktionen im Hauptteil des Programms
nutzen.

*****************************************************************

PROGRAM Test;
BEGIN
 WriteLn('Hallo');
END.

*****************************************************************

Hier sehen wir ein kleines Programm, das eine Prozedur enthlt:
"WriteLn". Doch woher nehmen wir diese? Nun, beim Starten von
Turbo oder Borland Pascal wird automatisch eine Unit immer mitge-
laden: SYSTEM. Hier sind alle Prozeduren und Funktionen enthal-
ten, die zur Standardprogramierung dazugehren. Die Standard-
bibliothek TURBO.TPL enthlt die folgenden Units, die bei jedem
Starten mitgeladen werden: SYSTEM, OVERLAY, GRAPH, DOS und CRT.
Mit Hilfe des Programmes TPUMOVER.EXE knnen eigene Units dieser
TPL (Turbo-Pascal-Library) hinzugefgt werden. Doch hierzu steht
noch was in der Rubrik "Tips und Tricks". Also: Beim Zugriff auf
WriteLn wird auf die Unit SYSTEM zugegriffen, die als einzige
nicht mit der USES-Anweisung deklariert werden mu.

Zum Aufbau eigener Units, den man ja wohl eher wissen mu.

ALLE: "Jawohl, Herr Lehrer!"

Hier einmal der schematische Aufbau einer Unit:

*****************************************************************

UNIT <Unitname>;
INTERFACE
 USES <Units>; {Angabe der allgemein und "ffentlich" genutzten}
               {Units}
 ...           {Hier kommen die _Kpfe_ der ffentlichen Prozedu-
               ren und Funktionen hin. Diese knnen dann vom
               Hauptprogramm aus aufgerufen werden.}
IMPLEMENTATION
 USES <Units>; {Angabe der "privat" genutzten Units}
 VAR <Variablen>;
               {Angabe der fr die Quelltexte bentigten Vars}
 ...           {Hier kommen die _kompletten_ Quelltexte der}
               {oben angebenen Proz. und Funkt. hin.}
               {Zustzlich knnen auch Hilfsroutinen, die nicht}
               {ffentlich zugnglich sind, definiert werden.}
BEGIN          {BEGIN steht nur, wenn anstelle der folgenden 3}
               {Punkte Aufrufe von Prozeduren oder Funktionen}
               {stehen, also eine Initalisierung stattfindet}
               {Wenn dies nicht der Fall ist, wird nur "END."}
               {verwendent. Bei Overlays _darf_keine_ Initia-}
               {lisierung stattfinden!!!}
 ...
END.

*****************************************************************

Eigentlich steht die komplette Erklrung der einzelnen Teile
oben als Kommentare. Etwas verwirrend scheint mir dennoch die
Sache mit der Initialisierung zu sein: Wenn in dem Initialisie-
rungsteil BEGIN...END. irgendetwas steht, so findet eine Initia-
lisierung statt. Wenn keine Initialisierung stattfinden soll,
mu man einfach das "BEGIN" weglassen. Bei als Overlays dekla-
rierten Units DARF KEINE Initialisierung stattfinden. Wenn ein
Initialisierungsabschnitt vorhanden ist, wird dieser sofort beim
Aufruf der Unit durchgefhrt. Diese Abschnitte erfolgen der Reihe
nach, d.h. in welcher Reihenfolge die Units in der USES-Anweisung
aufgerufen werden. Wenn sich Units gegenseitig aufrufen, wird
diese Regel natrlich auer Kraft gesetzt. Wichtig wre auch noch
zu sagen, da im INTERFACE-Teil NUR die KOMPLETTEN Prozedur- und
FunktionsKPFE der ffentlich zugnglichen Proz. und Funktionen
stehen (drfen/mssen).

  Weiterhin sollte die Unit so heien, wie sie spter abgespei-
chert werden soll und mit welchem Namen sie spter auch mit USES
eingebunden werden soll. Eine Unit, die unter dem Namen "HOPPEL"
abgespeichert werden soll, sollte mit "UNIT Hoppel;" beginnen und
vom Hauptprogramm aus mit "USES Hoppel" eingebunden werden.

  Manche tun sich auch mit dem Compilieren ins TPU-Format ein
wenig schwer. Eine im Editor befindliche Unit wird mit Hilfe von
"F9" compiliert und in dem in Option/Verzeichnisse/EXE & TPU
Verzeichnis (BP7) bzw. Option/Directories/EXE & TPU Directory
angegebenen Verzeichnis gespeichert. Wenn die Unit nachher auch
wieder gefunden werden soll, dann sollte dieses Verzeichnis sich
unter anderem auch den in O/V/Unit-Verzeichnisse (BP7) bzw.
O/D/Unit-Directories mglicherweise schon vorhandenen Pfadangaben
anschlieen.

Soviel dazu. Um noch ein letztes Mal die praktische Programmie-
rung von Units zu verdeutlichen, werde ich hier eine Unit mit
mehreren kleinen und ntzliche Prozeduren und Funktionen basteln,
die man dann in ein eigenes Programm einbinden kann. Der Quell-
text ist ja auch vorhanden, so da man auch diese Unit hier noch
erweitern kann.

*****************************************************************

UNIT Tools;

INTERFACE

USES Crt;

 PROCEDURE Wri(x,y : BYTE; VG,HG : BYTE; Text : STRING);
 PROCEDURE Rahmen(x1, y1, x2, y2 : BYTE; VG,HG : BYTE);
 PROCEDURE HideCursor;
 PROCEDURE ShowCursor;
 PROCEDURE KeyBufClr;
 PROCEDURE Colors(VG,HG : BYTE);
 PROCEDURE WaitForKeyPressed(Key : CHAR);

IMPLEMENTATION

{Schreibt "Text" an Position x,y im Textmodus mit Farbe VG auf}
{Farbe HG}
PROCEDURE Wri(x,y : BYTE; VG,HG : BYTE; Text : STRING);
VAR OldTextAttr : BYTE;
BEGIN
 OldTextAttr := TextAttr;
 GotoXY(x,y);
 Colors(VG,HG);
 Write(Text);
 TextAttr := OldTextAttr;
END;

{Zeichnet einen Rahmen im Textmodus von Stelle x1,y1 bis zur}
{Stelle x2,y2 mit Farbe VG auf Farbe HG}
PROCEDURE Rahmen(x1, y1, x2, y2 : BYTE; VG,HG : BYTE);
VAR i, j, OldTextAttr : BYTE;
BEGIN
 OldTextAttr := TextAttr;
 Colors(VG,HG);
 Wri(x1,y1,VG,HG,#201);
 Wri(x1,y2,VG,HG,#200);
 Wri(x2,y1,VG,HG,#187);
 Wri(x2,y2,VG,HG,#188);
 FOR i := x1+1 TO x2-1 DO Wri(i,y1,VG,HG,#205);
 FOR i := x1+1 TO x2-1 DO Wri(i,y2,VG,HG,#205);
 FOR i := y1+1 TO y2-1 DO Wri(x1,i,VG,HG,#186);
 FOR i := y1+1 TO y2-1 DO Wri(x2,i,VG,HG,#186);
 FOR i := x1+1 TO x2-1 DO
  FOR j := y1+1 TO y2-1 DO
   Wri(i,j,VG,HG,' ');
 TextAttr := OldTextAttr;
END;

{Lt den ewig blinkenden Cursor verschwinden}
PROCEDURE HideCursor; Assembler;
ASM
 MOV AH,$01;
 MOV CH,$20;
 MOV CL,$20;
 INT $10;
END;

{Lt den verschwundenen Cursor wieder erscheinen}
PROCEDURE ShowCursor; Assembler;
ASM
 MOV ah,$01;
 MOV cx,$0607;
 INT $10;
END;

{Setzt Vordergrundfarbe VG und Hintergrundfarbe HG}
{VG und HG mssen als Zahlen bergeben werden}
PROCEDURE Colors(VG,HG : BYTE);
BEGIN
 TextColor(VG);
 TextBackGround(HG);
END;

{Lscht den Tastaturspeicher}
PROCEDURE KeyBufClr;
VAR Dummy : CHAR;
BEGIN
 REPEAT
  IF KeyPressed THEN Dummy := ReadKey;
 UNTIL KeyPressed = FALSE;
END;

{Wartet auf den mit "Key" bergebenen Buchstaben, bis dieser}
{gedrckt wird. "Key" mu entweder als Buchstabe in Hochkommas}
{oder als #<Zahl> nach der ASCII-Tabelle bergeben werden.}
PROCEDURE WaitForKeyPressed(Key : CHAR);
VAR Ok : BOOLEAN;
BEGIN
 KeyBufClr;
 Ok := FALSE;
 REPEAT
  IF KeyPressed THEN IF ReadKey = Key THEN Ok := TRUE;
 UNTIL Ok = TRUE;
END;

{Kein Initialisierungsteil => nur END.}
END.

*****************************************************************

Da hier sher viel mit Farben gearbeitet wird, die als BYTEs de-
klariert sind, man also fr eine Farbe eine Zahl bergeben mu,
will ich hier mal die Farben mit den zugehrigen Zahlen angeben.

   0   Schwarz
   1   Blau
   2   Grn
   3   Cyan
   4   Rot
   5   Lila
   6   Braun
   7   Hellgrau
   8   Dunkelgrau
   9   Hellblau
   10  Hellgrn
   11  Hellcyan
   12  Hellrot
   13  Hellila
   14  Gelb
   15  Wei

Dabei ist mir aufgefallen, da man die Farben 9-15 nicht als
Hintergrundfarbe benutzen kann. Es erscheint dann immer eine
um 8 verringerte Farbe. Hellcyan wird also im Hintergrund zum
einfachen Cyan. Ich hab' keine Ahnung, woran das liegt.

Fr diese Ausgabe der Unit-Reihe liegen ein paar Programme dem
Sources-Pfad bei:
 TOOLS.PAS      ist der QuellCode fr die Unit TOOLS.
 TOOLS.TPU      ist die compilierte Form der Unit TOOLS.
 DEMOUNIT.PAS   ist der QuellCode zum Beispiel-Prog, das die
                Unit TOOLS nutzt.
 DEMOUNIT.EXE   ist die compilierte Form des Beispiel-Progs.

Alle Compilierungen wurden mit Borland Pascal 7 durchgefhrt.
Als Abschlu noch der Quelltext des Beispiel-Progs DEMOUNIT.PAS:
(Da wo ein "+" steht, mute ich die Zeile aufgrund des Listers
abschneiden. Im Original ist das aber nicht so.)

*****************************************************************

PROGRAM DemoUnit;

USES Crt,Tools;

BEGIN
 Colors(7,0);
 ClrScr;
 HideCursor;
 Rahmen(5,10,70,15,12,1);
 Wri(17,12,14,1,'Dies ist das Demo-Prog zur Unit TOOLS.');
 Wri(17,13,14,1,'Bitte jetzt ''W'' drcken...');
 WaitForKeyPressed('W'); {Hier wird ein _groes_ 'W' gefordert!}
                         {Eine einfache Bettigung der Taste 'w'}
                         {reicht nicht. Es mu zustzlich die}
                         {SHIFT-Taste gedrckt werden.}
 Colors(2,2);
 ClrScr;
 Rahmen(5,7,70,12,14,12);
 Wri(12,8,14,12,'Dies ist das zweite Fenster. Hier kann man' +
                'auch den');
 Wri(12,9,14,12,'Effekt erkennen, da das Fenster schwarz' +
                'unterlegt ist.');
 Wri(17,10,14,12,'Bitte jetzt ''p'' drcken...');
 WaitForKeyPressed('p'); {Hier kann man jetzt einfach nur}
                         die Taste 'p' drcken, da ein _kleines_}
                         'p' gefordert wird.}
 ShowCursor;
 Colors(7,0);
 ClrScr;
END.

*****************************************************************

Bei Fragen wendet euch an uns.

                          ERIC DER SCHRECKLICHE
                          Ŀ
                          
                          
                          ٳ
                            
                            

ALLE: "Jawohl, Herr Lehrer!"


