Sie sind auf Seite 1von 47

1

PhTe 9 CRASH Kurs DELPHI Nach dem Start prsentiert sich Delphi (Version 3.0) in etwa so:

Die gesamte Entwicklungsoberflche wird unterteilt in - das (obere) HAUPTFENSTER - den (linken) OBJEKTINSPEKTOR - das (rechte) FORMULAR (Ausgabefenster) - der (rechte) QUELLTEXTEDITOR Hauptfenster: Die Menueleiste: die Bedienung erfolgt wie in anderen Windows-Programmen. Erwhnenswert ist, das manche Eintrge der Einzelmenues ber sog HOTKEYS schneller anwhlbar sind, z.B. erreicht man durch Drcken der Funktionstaste F9, dass das aktuelle

Programm in einem Rutsch bersetzt (compiliert) und dann gestartet wird. (Dasselbe erreicht man auch mit dem Dreiecksymbol in der Symbolleiste.) Die Symbolleiste: 1 2 3 4 5 6 7 8 9 10 11 12 13 14

1 2 3 4 5 6 7

Projekt ffnen ffnet ein bereits vorhandenes Delphi-Projekt Alles speichern speichert alle Dateien eines Projektes Datei zum Projekt hinzufgen Unit aus einer Liste auswhlen Formular aus einer Liste auswhlen Start Programm wird compiliert und gestartet Pause Programm wird angehalten; diesen Knopf nach Mglichkeit NICHT bettigen 8 Datei ffnen ffnet eine Datei zustzlich (kein Projekt!!) 9 Datei speichern speichert die aktuelle Datei 10 Datei aus Projekt entfernen 11 Umschalten zwischen Formular und Quelltexteditor 12 Neues Formular 13 Einzelne Anweisung Hilfsmittel zur Fehlersuche 14 Gesamte Routine - Hilfsmittel zur Fehlersuche Die Komponentenpalette:

Hier finden sich zusammengefasst in sog. Registerpaletten

(Registerordnern) (z.B. Standard, Zustzlich,...) die einzelnen vorgefertigten Bausteine einer jeden Delphianwendung. Vorlufig arbeiten wir mir mit den beiden Paletten Standard bzw Zustzlich. Bewegt man die Maus auf eine der Komponenten erscheint nach ca 1 s (fr Vergessliche) ein sog. Kurzhinweis (Tooltip) mit dem Namen der jeweiligen Komponente. Objektinspektor: Hier knnen ohne jeden groen Programmieraufwand die Eigenschaften der zum Formular gehrigen Komponenten, die sowieso mit Standardwerten belegt sind, den individuellen Wnschen angepasst werden (Gre, Name, Lage, Schriftart, ...) Formular: Es ist das sptere Anzeigefenster des Programms, aber auch die Arbeitsplatte auf der die Programmoberflche `zusammengebastelt` wird. Auf ihm werden whrend der Entwicklungszeit die Komponenten mit der Maus platziert und durch Ziehen mit der Maus an einem der 8 hervorgehobenen Zieh-Punkte an die gewnschte Gre angepasst. Whrend der Laufzeit werden z.B. durch Maus-Click auf die betreffende Komponente die damit verbundenen Methoden ausgelst. Quelltexteditor Das ist die Stelle der Entwicklungsumgebung, an der wir spter unser eigenes Delphiprogramm eintippen werden. Dieser Editor enthlt immer schon von Delphi selbst erzeugte vorgefertigte Quelltextzeilen, die auf keinen Fall gendert oder gelscht werden drfen. Zwischen Formular und Quelltexteditor kann man hin und her schalten (z.B. Menuepunkt Ansicht / Umschalten Formular / Unit bzw. Symbolleiste Symbol Nr 11 bzw. als Hotkey F12 Speichern unserer Delphi-Projekte: Ein Delphi-Programm kann im Lauf seiner Entwicklung aus mehreren Dateien ( durchaus 10 oder sogar mehr) bestehen. Einige dieser Dateien knnen wir selbst speichern, andere werden beim Compilieren bzw. beim Speichern automatisch erzeugt. Damit diese Dateien nicht unkontrolliert auf dem Rechner erzeugt und gespeichert werden und sich einzelne Delphi-Projekte nicht gegenseitig in den Weg kommen sollen, ist es erforderlich, alle Dateien eines Delphi-Programms in ein und demselben Extraordner zu speichern.

Vorgehensweise: 1) Menuepunkt Datei / Alles speichern (bzw. entsprechender Knopf der Symbolleiste) 2) Wahl des Zielverzeichnisses 3) Erstellen des Unterordners, der das Delphi-Projekt aufnehmen soll: - Drcken des Knopfes Neuer Ordner erstellen (Knopf in der Speichern in Zeile) - Den Ordnernamen neuer Ordner im erscheinenden Bild durch den Wunsch-Ordnernamen (z.B. ProjektNr1) ersetzen. - Durch einen Doppelklick auf das Ordnersymbol vor dem Namen ProjektNr1 den neuen Unterordner erzeugen - Im nunmehr erscheinenden Bild den Knopf Speichern drcken. Es wird die Datei mit dem Namen Unit1.pas gespeichert. Diese Datei muss als erste unbedingt gespeichert werden. - Im nunmehr erscheinenden Bild nochmals den Knopf Speichern drcken. Jetzt wird die unbedingt erforderliche Speicherung der zweiten Datei Projekt1.dpr vorgenommen. Notwendige Dateien eines Delphi Projektes: - *.DPR Dateien. DPR steht als Abkrzung fr Delpi-Projekt. Hier werden alle im Projekt eingebundenen Formulare verwaltet. - *.PAS Dateien. Diese enthalten den Object-PascalQuelltext. - *.DFM Dateien. DFM steht als Abkrzung fr DelphiFormular. Hier sind in komprimierter Form z.B. alle Einstellungen, die wir im Objektinspektor vorgenommen haben, gespeichert. - *.RES Dateien. RES steht als Abkrzung fr RessourcenDatei. Hier ist z.B. das Icon gespeichert, das man auf dem Desktop erhlt, wenn man ein Delphi-Programm oder eine Verknpfung zu einem solchen auf dem Desktop ablegt.

Dateien, die nach der Compilation entstehen : - *. EXE Dateien. EXE steht als Abkrzung fr executable (= ausfhrbar). Es handelt sich um ein eigenstndig lauffhiges Programm, das denselben Namen wie die DPR-Datei trgt. (Aus Projekt.dpr wird projekt1.exe. Wer ein fertiges Programm anderen zum Gebrauch geben mchte, braucht nur diese EXE-Datei weiterzugeben. - *.DCU Dateien. DCU steht als Abkrzung fr Delphi Compiled Unit. Sie enthlt den in Maschinensprache bersetzten Quelltext der entsprechenden Unit. Weitere mgliche Dateien: - *.DOF Dateien. Sie enthalten ber den Menuepunkt Projekt / Optionen eingestellte Compiler-Einstellungen. - *.DSK Dateien. DSK steht als Abkrzung fr Desktop, dessen aktuelle Einstellungen beim Beenden von Delphi hier gespeichert werden. - *.DLL-Dateien. DLL steht als Abkrzung fr Dynamic Link Libraries. Das sind spezielle Windows-Dateien, die Befehle enthalten, auf die man z.B. von Delphi-Programmen aus zugreifen kann. - Daten-Dateien. Ein elektronisches Wrterbuch z.B. kann nur auf der Grundlage einer Vokabeldatei laufen. Transport von Delphi-Projekten nach Hause: Wer sein Projekt auf Stick oder Diskette mit nach Hause nimmt, um z.B. daran weiter zu arbeiten, braucht nicht alle diese Dateien zu kopieren, sondern nur die Dateien mit der Endung DPR, PAS, DFM und RES. Die EXE-Datei braucht er z.B. nicht zu kopieren, weil sie beim ersten Compilieren `zu Hause` wiederum neu angelegt wird. Delphi beenden: - Menue Datei / Beenden auswhlen - Symbol X im Hauptfenster oben rechts in der Ecke anklicken Ein Delphi-Projekt wieder ffnen: - Delphi starten - Menue Datei / ffnen auswhlen - den richtigen Ordner anwhlen - Projekt1.dpr (oder anderer Name des jeweiligen Projektes) anwhlen und ffnen.

Ein lauffhiges geladenes Programm starten: - Menuepunkt Start / Start anwhlen - Hotkey F9 Ein laufendes Programm unterbrechen; Rckkehr in die Bearbeitungsebene - Menuepunkt Start / Programm zurcksetzen - Hotkey ALT F4 Unser erstes Programm Starte Delphi und speichere sofort das (noch leere) Projekt im whrend dieser Arbeit zu erstellenden Order mit dem Namen Nr1 im Ordner EigeneProjekte, der sehr wahrscheinlich auch noch von dir neu erstellt werden muss. Plaziere auf dem Formular - eine Komponente vom Typ PANEL (wird verwendet fr berschriften, hervorgehobene Textausgaben,...) - 2 Komponenten vom Typ BUTTON(auch Schaltflche oder Knopf genannt) (wird verwendet, um durch Anklicken mit der Maus eine Aktion auszulsen) - 1 Komponente vom Typ LABEL (wird zur Ausgabe normaler Texte benutzt.)

- Verndere im Objektinspektor die Eigenschaft CAPTION (Bezeichner) so, dass aus den Standardnamen die gewnschten werden und verndere durch Ziehen mit der Maus oder Eintragungen im Objektinspektor die Gre, die Lage der Komponenten und weiterhin auch die Schriftart und Schriftgre der Eintragungen.

- Wechsle durch Doppelklick auf den Gut-Button in den Quelltexteditor und trage in die angezeigte Prozedur procedure TForm1.Button1Click(Sender: TObject); begin end; in die freie Zeile zwischen begin und end die Zeile Label1.Caption := 'Das freut mich'; ein. Benutze dabei fr das verwendete Hochkomma zum Einschluss des Textes die richtige Taste. - Verfahre analog mit dem Schlecht-Button und trage die Zeile Label1.Caption := 'Das tut mit aber Leid!' ein. - Speichere dein Projekt. - Starte dein Programm. Das zweite Programm: unser erstes richtiges Rechenprogramm Entwerfe auf dem Formblatt exakt die folgende Oberflche:

Panel

Edit

Label

Button

Button

Neu sind die EDIT-Komponenten, die (nach einem Mausklick darauf) zur Eingabe (aber auch Ausgabe) von Zeichen dienen. Fr uns ist nur eine Eingabe in die ersten drei sinnvoll, weil wir aus den eingegebenen (zuerst nur ganzzahligen) Werten fr Lnge, Breite und Hhe die anderen Quaderangaben ausrechnen wollen und die folgenden vier Editkomponenten zur Anzeige dieser Rechenergebnisse fr Kantenlnge, Oberflche, Volumen und Raumdiagonale benutzen wollen. Eine theoretisch auch denkbare Eingabe von Werten in diese letzten vier Editkomponenten macht also keinen Sinn. Bei Verwendung von Label-Komponenten fr die letzten vier knnte man diese denkbare Fehlbedienung innerhalb des laufenden Programms verhindern, allerdings wre dann die denkbare Aufgabenerweiterung aus beliebigen drei gegebenen Angaben die anderen vier zu berechnen auch nicht mehr mglich. Neu an diesen Editkomponenten ist erst einmal, dass die Eigenschaft CAPTION fr sie nicht existiert. Entsprechendes wird hier von der Eigenschaft TEXT bernommen, deren Rolle nicht mit der Rolle der Eigenschaft Name verwechselt werden darf. Die Eigenschaft Name der 7 Editkomponenten setzt man am besten gleich zu Anfang auf die besser merkbaren Bezeichner LaengeEdit (statt Edit1) bis DiagonaleEdit (statt Edit7).

Passe weiterhin das Formular im Objektinspektor in den folgenden Eigenschaften auf die angegebenen Werte an: Width: 400 Height: 500 Caption: Projekt2 Position: poScreenCenter Ergnze nach einem Doppelklick auf den Abbruch-Button im Quelltexteditor die Prozedur procedure TForm1.Button2Click(Sender: TObject); begin close; end; um den fett gedruckten Abbruch-Befehl close;

In diesem Entwicklungsstadium kann unser Programm schon Folgendes: - nach dem Start ist das Formular in seiner Gre angepasst in der Bildschirmmitte positioniert (siehe: Position: poScreenCenter. - alle Edit-Felder sind voll funktionstchtig (eingeben, lschen, ndern,...) - bei einem Mausklick auf den Abbruch-Button wird das Programm beendet. - Der Rechnen-Knopf lsst sich anklicken und geht dabei nach innen, aber die Berechnung und Ausgabe der gesuchten Werte mssen wir ihm noch beibringen . Dazu ist erforderlich: 1) Bereitstellung von Speicherplatz fr die einzugebenden Werte (z.B Lnge,...). 2) Einlesen der einzugebenden Werte (z.B Lnge,...) als Zeichenketten (TYP String) 3) Umwandeln der eingelesenen Zeichenketten in Zahlen vom TYP integer. 4) Berechnung der Werte (z.B. fr Volumen,...) mit diesen Zahlen. 5) Umwandlung der berechneten Zahlen (z.B. fr Volumen, ...) in Zeichenketten (denn nur solche knnen am Bild-schirm ausgegeben werden. 6) Ausgabe dieser Zeichenketten, die die Rechenergebnisse darstellen.

10

All dies soll whrend der Laufzeit des Programms nach einem Klick auf den Rechnen-Button erfolgen. Zur Entwicklungszeit des Programms mssen wir (nach Doppelklick auf den Rechnen-Button) die entsprechenden Anweisungen im Quelltexteditor eingeben. Zu 1) Fr die Quaderlnge fhren wir die Variablennamen laenge ein und erklren, dass diese Variable vom Typ integer ist, also eine ganze Zahl im Bereich -231 bis 231 1 sein kann (Speicherbedarf 4 BYTE). procedure TForm1.Button1Click(Sender: TObject); Var Laenge, ... :integer; begin .... end; ... Zu 2) und 3) Wir wandeln die im Lngenfeld eingegebene Zeichenkette, die die Quaderlnge darstellen soll, in eine ganze Zahl um, also vom Typ string in den Typ integer. procedure TForm1.Button1Click(Sender: TObject); var Laenge,... :integer; begin Laenge := StrToInt(LaengeEdit.Text); ... end;... Zu 4) Die in den drei Variablen Laenge, Breite und Hoehe vom Typ integer erfassten Werte benutzen wir nun, um die Integer-Variable Volumen zu berechnen: procedure TForm1.Button1Click(Sender: TObject); var Laenge,... :integer; begin Laenge := StrToInt(LaengeEdit.Text); ... Volumen := Laenge*Breite*Hoehe; end;... Zu 5) und 6) Hier erfolgt wieder die Umwandlung der Volumen-Integer-Zahl in einen ausgabefhigen String: Procedure TForm1.Button1Click(Sender: TObject);

11

var Laenge,... :integer; begin Laenge := StrToInt(LaengeEdit.Text); ... Volumen := Laenge*Breite*Hoehe;. ... VolumenEdit.text := IntToStr(Volumen); ... end; ... Sptestens bei der Lngenberechnung fr die Raumdiagonale mit Hilfe einer Wurzel (in Delphi Sqrt (fr Squareroot)) stellt sich der Variablentyp integer als unbrauchbar heraus. Der hierfr geeignete Variablentyp lautet z.B. real , der auch fr die Variablen Laenge, Breite und Hoehe geeignet wre, um z.B. nicht nur ganzzahlige Eingaben, sondern auch Dezimalzahlen verarbeiten zu knnen. Die entsprechenden Zusatzzeilen im Programm lauten: procedure TForm1.Button1Click(Sender: TObject); var Laenge,... :integer; Diagonale,... : real; begin Laenge := StrToInt(LaengeEdit.Text); ... Volumen := Laenge*Breite*Hoehe;. Diagonale:= Sqrt(Laenge*Laenge + Breite* Breite + Hoehe*Hoehe); ... VolumenEdit.text := IntToStr(Volumen); ... DiagonaleEdit.text:=FloatToStr(Diagonale); end; ... wobei FloatToStr(Diagonale) die Umwandlung einer (Flie-) Kommazahl in einen String bewirkt. TIP: Weil mit diesem einfachen FloatToStr-Befehl keine Formatierung der Kommazahl verbunden ist, erscheint die Ausgabe i.d.R. auf `unerwnschte` Art und Weise. Besser ist

12

der Befehl mit Formatierungsangabe, der hier wie folgt lautet: FloatToStrF(Diagonale, ffFixed, 10,2);. Die 2 steht dann z. B. fr die Anzahl der Nachkommastellen. Genaueres kannst du ber die Delphi-Hilfestellung erfahren. Auswahl der wichtigsten Variablentypen in Delphi 3.2 1) Variablentypen zur Speicherung ganzer Zahlen (IntegerTypen): Variablentyp Minimalwert Maximalwert Speicherbedarf Byte Word Shortint Integer 0 0 -128 = -27 -2147483648 =-231 255 = 28-1 65535 =216-1 127=27-1 2147483647 =231-1 1 2 1 4 Byte Byte Byte Byte

2) Variablentypen zur Speicherung gebrochener Zahlen (RealTypen) Variablentyp Minimalwert Maximalwert Real Single Double Extended 2,9*10-39 1,5*10-45 5*10-324 3,4*10-4932 1,7*1038 3,4*1038 1,7*10308 1,1*104932 Gltige Stellen 11 12 78 15 16 19 20 Speicher bedarf 6 Byte 4 Byte 8 Byte 10 Byte

Diesen Typ `extended` bentigt man z.B. dann, wenn man eine Dezimalzahl als Zeichenkette (Typ STRING) eingibt und dieser eingelesenen Zeichenkette den entsprechenden Wert der Dezimalzahl zuordnen mchte. Der entsprechende Befehl: z.B. laenge := StrToFloat(laengeEdit.text); setzt voraus, dass `laenge`als Variable vom Typ extended in der var-Zeile deklariert wurde. 3) Variablentyp zur Speicherung einzelner Zeichen (Tastendruck, einzelner Buchstabe,..) Variablentyp char; Speicherbedarf: 1 Byte Eine Char-Variable dient zur Aufnahme eines einzelnen von 256 mglichen Zeichen. Zur bersetzung eines Zeichens in die Zahl, unter der im Computerspeicher das Zeichen abgelegt wird, verwendet man standardisierte bersetzungstabellen (Codierungen). Unter DOS ist das der ASCII-Code ( American Standard Code for Information Interchange).

13

Unter Windows ist das der ANSI-Code (American National Standards Institute als Gegenstck zur deutschen DINNormung). In den ersten 128 Zeichen besteht bereinstimmung, in den hheren Code-Nummern kommt es zu Abweichungen.( Der Buchstabe kleines a hat z. B. die Codenummer 97, groes A entsprechend 65.) 4) Variablentypen zur Speicherung von Wahrheitswerten Variablentyp Boolean Speicherbedarf: 1 Byte Mgliche Werte sind TRUE (Aussage wahr) oder FALSE (Aussage falsch). Bekannt ist dir dieser Datentyp z.B. aus dem Objektinspektor, wo Eigenschaften bestimmter Komponenten aktiviert (true) oder aber deaktiviert (false) werden.

14

Unsere dritte Programmieraufgabe: Zahlenraten gegen den Computer Anforderungen an das Programm: - Der Computer erzeugt bei jedem neuen Spiel selbststndig unter dem Variablennamen Zufallszahl eine neue Integer-Zahl aus dem Bereich von 1 bis z.B. 100, die vom Nutzer mit mglichst wenig Versuchen geraten werden soll. - Nach jedem Rateversuch wird die Eingabe vom Computer mit einer der drei folgenden mglichen Ausgaben bewertet: Die Zahl ist zu gro! oder Die Zahl ist zu klein! oder Die Zahl stimmt! . - Die Anzahl der Rate-Versuche wird jeweils aktualisiert ausgegeben. - Nach dem Erraten der Zahl soll der Nutzer die Mglichkeit haben, mit einer neu erzeugten Zufallszahl ein neues Spiel zu beginnen. Speichere zuerst Dein neues Projekt in einem separaten Unterordner z.B. mit dem Namen Nr3. Gestalte dann Dein Formular mit Hilfe folgender Komponenten:

2 Panel-, 3 Label-, 2 Edit-, 3 BitBtn-Komponenten: Denke daran, (zumindest) der unteren Panel- , und den beiden Editkomponenten im Objektinspektor aussagekrftige Namen

15

zu geben (z.B. ErgebnisPanel, EingabeEdit, AnzahlEdit,..) und auch die BitBtn-Namen passend zu whlen ( NeuButton, RateButton, EndeButton). Diese neuen BitButtonKomponenten stehen in der Komponentenpalette Zustzlich (ganz vorne) zur Verfgung und bieten Buttons mit Bildern an. Um die vorgegebenen Effekte zu erzielen, muss man zuerst im Objektinspektor die Eigenschaft Kind der drei BitBtn-Komponenten einstellen und danach erst die vorgeschlagene Beschriftung ber die Eigenschaft Caption whlen. Diese Eigenschaft Kind wird fr Neubutton auf bkRetry fr RateButton auf bkOK und fr EndeButton auf bkAbort gesetzt. Beginne jetzt mit der Ereignisbehandlungsroutine fr den EndeButton (Close-Befehl). Bei den entsprechenden Routinen fr die beiden vorderen BitBtns kommt es bei der Behandlung der Variablen `Zufallszahl` zu einer neuen Situation bei der Verabredung dieser Variablen, weil beide diese Variable Zufallszahl bearbeiten. Wenn man auf den BitBtn Neue Zahl klickt, wird diese Variable mit einem neuen Wert versehen; wenn man auf den BitBtn Raten klickt, wird der Wert von Zufallszahl u.a. fr Vergleiche mit der eingegebenen Ratezahl bentigt. Diese Variable Zufallszahl kann also nicht wie bisher lokal in der Prozedur erklrt werden, sondern muss global vereinbart werden. Dafr whlen wir die Variante der globalen Variablendeklaration innerhalb des `implementation`-Teils der Unit unmittelbar nach dem Einbinden des Formulars. Konkret: ... implementation

{$R *.DFM} var Zufallszahl, ...: integer; procedure TForm1.EndeButtonClick(Sender: TObject); ...

16

Damit ist die Variable Zufallszahl jetzt an jeder Stelle der Unit gltig und kann in allen Prozeduren verwendet werden. hnliche berlegungen gelten fr die Variable Anzahl (der Rateversuche) , weil sie beim Klicken auf den Neue-ZahlButton auf 0 gesetzt werden muss, aber auch nach einem Klick auf den Rate-Button innerhalb der dann abzuarbeitenden Prozedur bei jeder neuen Eingabe in das EingabeEdit-Feld jeweils um 1 erhht werden muss. Die Anweisung Zufallszahl := Random(10); wrde eine zufllige Integer-Zahl zwischen 0 und 9 erzeugen, die Anweisung Zufallszahl := Random(100)+1; also wie verlangt - eine zwischen 1 und 100. Ein Haken besteht noch darin, dass allein nur mit dieser Anweisung bei jedem Programmstart immer mit derselben Zufallszahl begonnen wrde. Um das zu verhindern, muss vorher mit Hilfe der Anweisung Randomize; der Zufallszahlen-Generator immer auf einen neuen Startwert gesetzt werden, der sich in Delphi bei Verwendung dieser Anweisung aus der aktuellen Uhrzeit und dem aktuellen Datum `errechnet`. Aber wo soll diese Doppelanweisung Randomize; Zufallszahl := Random(100)+1; plaziert werden? Am einfachsten wre es in der Prozedur, die nach einem Doppelklick auf den Neue-Zahl-Button `aufgeht`. Aber : Nach jedem Programmstart msste der Benutzer dann vor seinem ersten Rateversuch erst einmal den Neue-ZahlButton anklicken, was dieser Benutzer vielleicht gar nicht wei. Und schon fangen dann gleich zu Beginn die Probleme an, und das Programm wird sich keiner groen Beliebtheit erfreuen. Besser wre eine Prozedur, die bei Programmstart automatisch ausgefhrt wird. Diese Mglichkeit verbirgt sich hinter dem OnCreate-Ereignis des Formulars, welches du super-einfach durch einen Doppelklick auf eine leere Stelle des Formulars auslst. Als Ergebnis dieses Doppelklicks erzeugt Delphi die folgende Prozedur, in die (jetzt wieder im Quelltext-Editor) die fett-gedruckte Doppelanweisung eingetragen wird: ... procedure TForm1.FormCreate(Sender: TObject); begin Randomize; Zufallszahl := Random(100)+1; end; ....

17

Nicht vergessen: Sollte sich derselbe Spieler per NeuButton nach seiner ersten Runde fr ein weiteres Spiel entscheiden, muss diese Doppelanweisung fr die Erzeugung einer Zufallszahl natrlich auch in dieser Prozedur erneut vorkommen. Weiterhin muss dann der Wert fr Anzahl (der Rateversuche) auf 0 gesetzt werden und eine Beschriftung des zweiten Panels (z.B. mit: Die Zahl ist zu gro! oder Die Zahl stimmt! ) verschwinden. Also (nach einem Doppelklick auf den NeuButton): procedure TForm1.NeuButtonClick(Sender: TObject); begin Randomize; Zufallszahl := Random(100)+1; Anzahl := 0; AnzahlEdit.Text := IntToStr(Anzahl); ErgebnisPanel.Caption := ''; end; ... Am Schluss ist noch die Ereignisbehandlungsroutine fr den Rate-Button zu schreiben. Hier ist der im EingabeEdit-Feld eingegebene Rate-Versuch vom Programm zu bewerten. Nach der Anweisung: ... Eingabe:= StrToInt(EingabeEdit.text);... muss ein Vergleich von Eingabe mit Zufallszahl stattfinden und im unteren Panel ein entsprechender Ergebnistext ausgegeben werden. Mache dir an dieser Stelle klar, dass die Variable Eingabe durchaus lokal - also nur fr diese Rate-Prozedur gltig deklariert werden kann. Der angesprochene Vergleich wird durch die folgende DelphiVergleichs-Anweisung ermglicht: IF Bedingung THEN Anweisung fr den JA-Fall ELSE Anweisung fr den NEIN-Fall. Die einfachste Realisierung lautet also unter Verzicht auf ELSE-Teil der Anweisung: If Eingabe = Zufallszahl then ErgebnisPanel.Caption := Zahl stimmt!'; If Eingabe > Zufallszahl then ErgebnisPanel.Caption := Zahl ist zu gro!'; If Eingabe < Zufallszahl then ErgebnisPanel.Caption := Zahl ist zu klein!'; den 'Die 'Die 'Die

18

Nachteil: Selbst wenn nach der ersten Zeile das Ergebnis bereits feststehen sollte, werden trotzdem unntigerweise die beiden folgenden Zeilen abgearbeitet. Die bessere Lsung lautet also unter Verwendung des ELSE-Teils der Anweisung: If Eingabe = Zufallszahl Then ErgebnisPanel.Caption := 'Die Zahl stimmt!' Else If Eingabe > Zufallszahl Then ErgebnisPanel.Caption := 'Die Zahl ist zu gro!' Else ErgebnisPanel.Caption := 'Die Zahl ist zu klein!'; 1) Beachte, dass zwischen Then und Else KEIN Semikolon stehen darf. 2) Beachte, wie durch das Einrcken der Programmtext bersichtlich strukturiert wird, und damit auch die Einsicht in die Logik des Programms gefrdert wird. Vergiss nicht, in dieser Prozedur das Hochzhlen fr die Anzahl der Rateversuche und weiterhin die Bildschirmausgabe fr diese Anzahl zu programmieren. Damit msste das Programm lauffhig sein. Die folgenden Zusatzforderungen sollen aber noch erfllt werden. 1) Als lstig wird angesehen, dass fr eine Zahleingabe immer erst in das Eingabe-Editierfeld mit der Maus geklickt werden muss. Besser wre es, wenn der Cursor automatisch in diesem Feld stehen wrde, oder anders ausgedrckt: wenn das Eingabe-Editierfeld nach Eingabe einer Zahl sofort wieder den Eingabefokus erhalten wrde. 2) Fehlversuche sollen im unteren Panel durch eine blaue Schrift in Schriftgre 12, ein Treffer soll durch eine entsprechende Textausgabe in rot in Schriftgre 14 ausgegeben werden. Zu 1) Die Methode SetFocus gehrt zu allen Objekten, die den Eingabefocus aufnehmen knnen (Btn, BitBtn, Edit,...) und sie sorgt dafr, dass das jeweilige Steuerelement nicht immer extra mit der Maus bzw. der Tastatur angewhlt werden muss. Weil sie sich auf das EingabeEdit-Feld bezieht, wird einfach an die bisherigen Anweisungen der RateButtonClick-Prozedur eine Zeile mit der Anweisung EingabeEdit.SetFocus; angehngt. Zu 2) Bisher wurden die Einstellungen fr Schriftart (Font) , Schriftgre (Size), Schriftfarbe (Color), ... im

19

Objektinspektor einheitlich fr das Objekt eingestellt. Dabei werden die Eigenschaften Schriftgre (Size) , Schriftfarbe (Color), ... nicht als eigenstndig, sondern als Untereigenschaft der Schriftart (Font) des Objektes gefhrt. Die zur Schriftart gehrige Untereigenschaft Size des Objektes ErgebnisPanel wird dann durch folgende Anweisung auf z.B. den Wert 12 eingestellt: ErgebnisPanel.Font.Size := 12; . Analog ist die Schriftfarbe rot durch eine Anweisung der Form ErgebnisPanel.Font.Color := clRed; einzugeben. Hierbei werden die Namen der in Delphi eingebundenen Windows-Standardfarben benutzt, eine Palette von Mglichkeiten, die man im Objektinspektor bei der Eigenschaft Color z. B. einer Panel-Komponente durchblttern kann. Hier im berblick die 16 Windowsgrundfarben in Delphi: Farbkonstante Farbkonstante clBlack Schwarz clSilver Silber clMaroon Rotbraun clRed Rot clGreen Grn clLime Limonengrn clOlive Olivgrn clYellow Gelb clNavy Marineblau clBlue Blau clPurple Violett clFuchsia Pink clTeal Petrol clAqua Karibikblau clGray Grau clWhite Wei Dadurch wird es nun ntig innerhalb der If ... THEN ... Anweisung mehrere nacheinander auszufhrende Anweisung einzuklammern. Dies geschieht mit Hilfe der Klammerwrter Begin .... End; . Fr den ersten Teil innerhalb der RateButtonClick-Prozedur ergibt sich also folgendes: IF Eingabe = Zufallszahl THEN begin ErgebnisPanel.Font.Color := clRed; ErgebnisPanel.Font.Size := 14; ErgebnisPanel.Caption := 'Die Zahl stimmt!' end ELSE IF Eingabe > Zufallszahl ... THEN ...

20

Auch hier ist wieder durch Einrcken die logische Zusammengehrigkeit optisch zum Ausdruck gebracht worden, ein Schreibstil, den man unbedingt pflegen sollte. Nach Bercksichtigung der letzten Tipps msste das Programm jetzt auch in der verbesserten Version lauffhig sein. Eine unangenehme Fehleranflligkeit weist es allerdings immer noch auf: Wenn man z.B. zu Spielbeginn vor der Eingabe einer Zahl auf den Rate-Button klickt oder z.B. whrend des Spiels (vielleicht irrtmlich) statt einer Zahl ein anderes Zeichen (Buchstabe, Punkt, Komma, Semikolon,...) eintippt, reagiert das Programm brutal mit Abbruch. Abhilfe schafft hier das sog. try&except-Prchen. Der Anweisungsblock hinter dem Schlsselwort try wird nur versuchsweise ausgefhrt. Wenn alles klappt, ist es gut und die Anweisungen im Except-Block werden bersprungen. Wenn ein Fehler registriert wird (z.B. Eingabe eines Buchstabens an einer Stelle, an der eine Integer-Zahl erwartet wird), wird ein zwischen den Schlsselwrtern except und end eingeschlossener zweiter Anweisungsblock ausgefhrt, der dann sinnvollerweise als Fehlerbehandlungsroutine ausgelegt ist. Vorher ist allerdings in der Menueleiste bei TOOLS / Umgebungsoptionen im Register VORGABEN die Einstellung Bei Exceptions anhalten zu deaktivieren (Haken im Kstchen wegklicken). Also: try // hier stehen alle Anweisungen, // die versuchsweise ausgefhrt werden except // hier stehen alle Anweisungen, die im Falle eines Fehlers // auszufhren wren, z.B. auf den Fehler aufmerksam // machen!! end; Dadurch ergibt sich z. B. die folgende Version der RateButtonProzedur: procedure TForm1.RateButtonClick(Sender: TObject); var Eingabe : integer; begin try Anzahl := Anzahl + 1;

21

AnzahlEdit.Text := IntToStr(Anzahl); Eingabe:= StrToInt(EingabeEdit.text); If Eingabe = Zufallszahl then begin ErgebnisPanel.Font.Color := clRed; ErgebnisPanel.Font.Size := 14; ErgebnisPanel.Caption:= 'Die Zahl stimmt!' end else If Eingabe > Zufallszahl then ErgebnisPanel.Caption := 'Die Zahl ist zu gro!' else ErgebnisPanel.Caption := 'Die Zahl ist zu klein!'; except ErgebnisPanel.Caption := 'Vernnfige Eingabe bitte !!'; end; EingabeEdit.SetFocus; end; Aufgabe: Ergnzungen des Projektes Zahlenraten gegen den Computer 1) Die Spieler einer Sitzung sollen durch Anklicken eines weiteren ( vierten) BitBtn (Name: BilanzButton, Caption: Spielebilanz) im ErgebnisPanel eine Information darber erhalten, - wie oft sie bisher erfolgreich die Computer-Zufallszahl erraten haben und -welche durchschnittliche Anzahl von Rateversuchen sie dazu bentigt haben. 2) Weiterhin soll eine bisher mgliche Fehlbedienung ausgeschlossen werden, die noch darin besteht , dass man in der bisher vorliegenden Version trotz eines erfolgreich abgeschlossenen Spiels weiterhin Rateversuche unternehmen kann, ohne vorher ein neues Spiel begonnen zu haben. Erstmalig kommt dabei der Variablentyp `boolean` zur Anwendung, fr den es nur die beiden Werte `true` oder `false ` gibt..

Vorschlge fr die Realisierung:

22

I) Umbenennung der Variablen Anzahl in AnzahlVersuche II) Umbenennung der Komponente AnzahlEdit in AnzahlVersucheEdit (natrlich auch entsprechende Umbenennung der Eigenschaften dieser Komponente, z.B. AnzahlEdit.Text in AnzahlVersucheEdit.Text usw. ...) Benutze dazu den Menuepunkt Suchen - Unterpunkt Ersetzen mit entsprechenden Voreinstellungen wie z.B Suchen und Ersetzen mit Einzelbesttigung vom Textanfang an. III) Deklaration der Variablen AnzahlSpiele , AnzahlVersuche_insgesamt und AnzahlVersuche_im_Schnitt. berlege dir genau den jeweiligen Variablentyp und ob diese Variablen lokal oder global deklariert werden mssen. Wenn irgend mglich, ist eine lokale Deklaration immer vorzuziehen. IV) Sorge dafr, dass an der richtigen Stelle (zum richtigen Zeitpunkt) - der Startwert fr AnzahlSpiele , AnzahlVersuche_insgesamt und AnzahlVersuche_im_Schnitt auf den richtigen Wert gesetzt wird. - AnzahlSpiele, AnzahlVersuche_insgesamt und AnzahlVersuche_im-_Schnitt aktualisiert werden. - die Ausgabe dieser Bilanz-Informationen erfolgt. Auch der unerwnschte Fall, dass jemand eine Bilanz sehen mchte, bevor er das erste Spiel erfolgreich beendet hat, soll mglichst bercksichtigt sein. V) Sorge dafr, dass die Variable Spiel_fertig vom Typ boolean - passend deklariert wird. - bei Spielbeginn ( FormCreate, NeuesSpiel, ) den Wert false hat. - genau an der richtigen Stelle auf den Wert true gesetzt wird. Rateversuche sollen also nur dann mglich sein, wenn die Bedingung `If Spiel_fertig = false ` erfllt ist. Weitere unzulssige Rateversuche mssen also zu einer entsprechen-

23

den Fehlermeldung bzw Aufforderung im Ergebnis-Panel fhren. Unser viertes Projekt: Hoch die `Zahlen` !!!

Der Benutzer dieses Programms soll auf Wunsch mehrfach eine ganze positive Zahl eingeben drfen, von der ausgehend im Programm fnf neue Zahlen berechnet und ausgegeben werden sollen. Und zwar: - das Quadrat der eingegebenen Zahl. - die Kubikzahl zur eingegebenen Zahl. - die Summe der Zahlen von 1 bis zur eingegebenen Zahl. - die Summe der Quadratzahlen von 1 bis zur eingegebenen Zahl. - die Summe der Kubikzahlen von 1 bis zur eingegebenen Zahl.

Das Formular ist wie folgt vorzubereiten:

Verwendung finden : 2 x Panel-, 5 x Label-, 6 x Edit-, 3 x BitButtonkomponenten;

24

Die untere Panel-Komponente dient zur Ausgabe von Fehlermeldungen. Die Labelkomponenten brauchen als `feststehende Texte` NICHT unbedingt umbenannt zu werden. Die Editkomponenten werden sinnvollerweise umbenannt in (der Reihe nach): EingabeEdit, QuadratEdit, KubikEdit, SummeEdit, QuadratsummeEdit, KubiksummeEdit. Die BitButton werden ebenfalls (nach nderung der KINDEigenschaft im Objektinspektor) in Neu-, Rechnen- und EndeButton umbenannt. Bei Anklicken des vorderen NeuButtons sollen alle Editkomponenten ` leergemacht` werden und das EingabeFeld oben rechts den Eingabefokus erhalten. Beim Anklicken des Rechnen-Buttons soll zuerst festgestellt werden, ob berhaupt eine sinnvolle Eingabe erfolgte. Mgliche

25

fehlerhafte Eingaben ( z.B. Buchstabe statt Zahl, negative Zahl, Zahl ber 100, ...) sollen von einer angemessenen ( serisen !!) Meldung im unteren MeldungsPanel begleitet werden. Nur bei einer sinnvollen Eingabe soll die Berechnung der neuen fnf Zahlen erfolgen, wobei die drei Summenberechnungen auf neue Programmiermethoden fhren. Die einfache Zahlensumme soll mit einer FOR TO (DOWNTO) DO Schleife, die Quadratzahlsumme mit einer WHILE DO Schleife und die Kubikzahlsumme mit einer REPEAT UNTIL Schleife programmiert werden. Allen drei Schleifen-Sorten gemeinsam ist, dass eine Anweisungsfolge mehrfach hintereinander ausgefhrt wird. Die Anzahl der Wiederholungen muss bei einer FORSchleife vorher genau als Ganzzahl bekannt sein; bei den beiden anderen Schleifentypen wird die Anzahl der Wiederholungen vom Erflltsein einer bestimmten Bedingung abhngig gemacht. Die FOR TO (bzw DOWNTO) DO Schleife FOR Nr := Start TO Ziel DO ANWEISUNGSBLOCK (notfalls in begin ... end eingepackt) IntegerVariable Endwert Startwert der IntegerVariablen Hier soll der Startwert kleiner als der Endwert sein, so dass hochgezhlt wird und zwar immer in Einerschritten. Anderenfalls wrde mit DOWNTO in Einerschritten heruntergezhlt werden knnen. Fr die Zhlvariable werden als Bezeichner meist einfache Buchstaben i, j, k, ... gewhlt; als reine Zhlvariable bedarf sie keiner aufwndigen Bezeichnung. Nach entsprechenden Variablenvereinbarungen wrde der Kern der entsprechenden Methode lauten:

26

Summe := 0; For i:= 1 to Eingabe do Summe := Summe + i; SummeEdit.Text := IntToStr(Summe); Die WHILE DO Schleife WHILE Bedingung DO Anweisungsblock (dieser notfalls in begin ... end eingepackt) d.h.: solange eine bestimmte Bedingung erfllt ist, soll der Computer einen Anweisungs-block ausfhren. Wenn die Bedingung sofort nicht erfllt ist, wird der Anweisungsblock also gar nicht ausgefhrt. Achtung: Wenn die Anweisungsfolge nicht dazu fhrt, dass die Bedingung irgendwann einmal nicht mehr zutrifft, gert der Pc in eine fatale Endlosschleife!!! Im Gegensatz zur FOR-Schleife wird hier keine Zhlvariable automatisch vom Programm in Einerschritten herauf- oder herabgesetzt. All dies unterliegt der eigenen Programmierkunst. Fr die konkrete Programmieraufgabe wre im Vorfeld eine Variable QuadratSumme zu deklarieren, dann auf den Wert Null zu setzen, um dann anschlieend im Rahmen der While-Schleife die Quadratzahlen von 1, 2, ... bis zur Eingabe-Zahl hinzu zu addieren. Dazu muss aber parallel eine Zhlvariable (z.B. mit dem Namen j) in Einerschritten hochgezhlt werden. Nach entsprechenden Variablendeklarationen knnte der entsprechende Programmteil z.B. wie folgt lauten: QuadratSumme :=0; j : = 0; WHILE j < Eingabe DO begin j:=j+1; QuadratSumme := QuadratSumme + sqr(j); end; QuadratSummeEdit.Text := IntToStr (QuadratSumme); Das Hochzhlen der Variablen j um 1 realisiert man professioneller durch den Befehl inc(j).

27

Durch inc(j,2) wrde man entsprechend die Variable j in Zweierschritten hochzhlen. Das Fachwort heit ` INKREMENTIEREN`. Entsprechendes DEKREMENTIEREN (Herunterzhlen) erfolgt mit dec(j) in Einerschritten, bzw bei z.B dec(j,10) in 10erSchritten.

28

REPEAT

Die REPEAT UNTIL Schleife Der Computer soll also eine Anweisungsblock bestimmte Anweisungsfolge UNTIL Bedingung wiederholen, bis eine bestimmte Bedingung erfllt ist. Der Anweisungsblock wird also garantiert mindestens einmal ausgefhrt. Achtung: Wenn die Anweisungsfolge nicht dazu fhrt, dass die Bedingung irgendwann doch einmal zutrifft, gert der Pc in eine fatale Endlosschleife!!! Fr die konkrete Programmieraufgabe wre im Vorfeld eine Variable KubikSumme zu deklarieren, dann auf den Wert Null zu setzen, um dann anschlieend im Rahmen der Repeat-UntilSchleife die Kubikzahlen von 1, 2, ... bis zur Eingabe-Zahl hinzu zu addieren. Dazu muss aber parallel eine Zhlvariable (z.B. mit dem Namen k) in Einerschritten hochgezhlt werden. Nach entsprechenden Variablendeklarationen knnte der entsprechende Programmteil z.B. wie folgt lauten: KubikSumme := 0; k := 0; repeat inc(k); KubikSumme := KubikSumme + k*k*k; until k = Eingabe; KubikSummeEdit.Text := IntToStr(KubikSumme); Mache dir nochmals genau klar, warum in der WHILE-Schleife eine `Kleiner-Bedingung`, in der Repeat-Schleife eine `Gleichheitsbedingung` verwendet wurde.

29

Unser fnftes Projekt: Verwendung des Locad-Interface unter DELPHI an der parallelen Drucker-Schnittstelle

Das Bild zeigt das Interface (rechts) mit angeschlossener EinAusgabe-Platine (links). In dieser Zusammensetzung verfgt es ber 3 Eingnge (EIN0, EIN1 und EIN2), an denen 0-Signale bzw. 1-Signale dem PC zur Auswertung eingespeist werden knnen. An den 3 Schaltern 0, 1 und 2 knnen die 0- bzw. 1Signale auch ohne EIN-AUSGABE-Platine vorgegeben werden. Ferner verfgt es ber 6 Ausgnge (AUS0 bis AUS5), an denen 0-Signale bzw. 1-Signale - vom PC gesteuert - bei Bedarf zur Verfgung gestellt werden knnen. Die Verbindung PC Interface geschieht ber ein Druckerkabel, welches die parallele Druckerschnittstelle auf der PCRckseite als 25-polige SUB-D-Buchsenleiste herausgefhrt mit der 36-poligen CENTRONICS-Buchse am Interface verbindet. Bei Computern neuerer Bauart wird hufig auf diese parallele Schnittstelle zugunsten eines Anschlusses ber USB verzichtet.

30

Anschlussnummerierung an der SUB-D-Buchsenleiste

18

Druckerkabel 25-polig Sub-D / Centronics

19 Eingangsbuchse am Interface 36 Rckseite eines Druckers (CENTRONICS-Schnittstelle) USB / Centronics

Dieses Interface kann nun direkt mit einer Programmiersprache (z.B. DELPHI) angesprochen werden. Die Programmiersprache muss 'nur (!!!!)' einen Zugang auf die Parallelschnittstelle (LPT) nach dem Centronics-Standard ermglichen, der bei IBMkompatiblen Rechnern den Zugriff auf die drei folgenden 8-BitRegister umfasst: DATEN- Register ( dient i.d.R. bei Anschluss eines Druckers zur Ausgabe von Druckerdaten) STATUS- Register ( dient i.d.R. bei Anschluss eines Druckers zum Lesen des Druckerstatus) (STEUER-(Kontroll- )Register (dient i.d.R. bei Anschluss eines Druckers zum Steuern von Druckerfunktionen); wird von uns aber NICHT genutzt.) Der ersten Druckerschnittstelle (LPT1) ist nach diesem Standard die Basisadresse `hexadezimal 378` (dezimal 888 = 3*16 + 7*16 + 8) zugeordnet. Unter dieser Basisadresse BA (`hexadezimal 378` ) steht somit das Datenregister als zusammenhngender 8-BitAusgabeport zur Verfgung, unter BA +1 das Statusregister, unter BA +2 das Steuerregister. ber diese drei Register kann nun ein Datenaustausch stattfinden. Das Locad - Interface benutzt

31

- als Datenausgang Teile des DATEN-Registers, - als Dateneingang Teile des STATUS-Registers gem folgender Zuordnung: Register/Bits Datenregister Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Statusregister Bit 3 Bit5 Bit 7 / invertiert Pin am SUB-DStecker Pin-Nr am 36poligen CentronicsStecker 2 3 4 5 6 7 32 12 11

2 3 4 5 6 7

(Aus (Aus (Aus (Aus (Aus (Aus

0) 1) 2) 3) 4) 5)

15 (Ein 0) 12 (Ein 1) 11 (Ein 2)

Aus DELPHI heraus sind nach einer entsprechenden Spracherweiterung um eine so genannte Treiber-DLL (DynamicLink-Library) mit dem Namen PORT.DLL (abgelegt in Windows/System) diese drei Register direkt ansprechbar, sofern ihre vom Betriebssystem verwalteten Adressen wie oben angegeben - bekannt sind. ACHTUNG: Wenn auf einem Rechner die parallele Schnittstelle anders als hier vorausgesetzt installiert ist, oder wenn bei zuknftigen Windows-Versionen der Zugriff auf die Schnittstelle anders als hier vorausgesetzt organisiert ist, wird die direkte Ansprache dieser parallelen Schnittstelle und damit der Einsatz dieses Interfaces in dieser geplanten Form NICHT mglich sein. Da die `spteren` Betriebssysteme Windows NT, 2000 und XP und erst recht VISTA keine direkten Zugriffe auf die parallelen Ports des PC erlauben, mssen noch weitere zustzliche Treiber installiert werden (u.a. UserPort.sys im Verzeichnis Win\system32\ drivers). Ferner muss bei Benutzung eines solchen `neueren` Betriebssystems die zur Verfgung gestellte Software UserPort.exe vor dem Delphi3-Beginn gestartet werden. In dieser Anwendung dann auf `Start` klicken und anschlieend auf `Exit`. Dadurch wird der von den Windows-

32

Programmierern eigentlich verbarrikadierte Zugang zu den Parallelports doch wieder ermglicht. Wenn dieser ermglichte Hardwarezugriff am Ende der Sitzung wieder deaktiviert werden soll, muss das Programm UserPort.exe erneut gestartet werden und in dieser Anwendung auf `Stop` geklickt werden. Die zur PORT.DLL gehrige fr uns also verfgbare - Funktion InPort(PortAddr: Word) liefert einen Wert vom Typ BYTE zurck, der alle Informationen ber das 8-Bit-Register mit der angegebenen Adresse beinhaltet; so z. B. alle Informationen ber die Beschaltung der Eingnge EIN 0, 1, 2, wenn man ber die passende Adresse das Statusregister anspricht. Zweckmigerweise beschafft man sich diese Information ber das Statusregister innerhalb eines Delphi-Programms durch die Wertzuweisung daten_ein := InPort(BA +1); an eine vorher deklarierte Variable mit dem Namen daten_ein vom Typ BYTE. Der konkrete jeweilige Wert kann dann z.B. mit StatusEdit.Text := IntToStr(daten_ein) im Fenster einer geeigneten Edit-Komponente (z.B. mit dem Namen StatusEdit) sichtbar gemacht werden. Die ebenfalls zur PORT.DLL gehrige Prozedur OutPort(PortAddr: Word; Data: Byte) belegt bei passender Wahl der Variablen Portaddr das Datenregister so, wie es dem Wert der Variablen Data entspricht. Will man also smtliche 6 Ausgnge der EIN/AUSGABE-Platine einem 1-Wert entsprechend auf 5 V schalten, so mssen die ersten 6 Bits mit den Nummern 0 bis 5 des Datenregisters mit 1 belegt werden. Wegen 1. 2o + 1. 21 + 1. 22 + 1. 23 + 1. 24 +1. 25 = 63 lautet der entsprechende Befehl OutPort(BA, 63)

33

B asis A dresse des SPEICHER (RAM) des Computers


Vorangehende Register
Bit Nr 7 6 5 4 3 2 1 0

Datenregisters, das zusammen mit dem Status- und dem Steuerregister die parallele Schnittstelle (LPT1)verwaltet.

6 vom Computer aus steuerbare Ausgnge, die auf 0V bzw. 5V gesetzt werden knnen
AUS 0 1 2 3 4 5

Daten Register;
Bit Nr 7 6 5

BA= 888 10 = 378 16


4 3 2 1 0

PIN 2 PIN 3 PIN 4 PIN 5 PIN 6 PIN 7

PIN 2 PIN 3 PIN 4 PIN 5 PIN 6 PIN 7

Status Register; BA + 1
Bit Nr 7 6 5 4 3 2 1 0

Ein 0
PIN 15 PIN 1 2 PIN 1 1 PIN 3 2 PIN 1 2 PIN 1 1

I N T E R F A C E

Steuer Register; BA + 2
Bit Nr 7 6 5 4 3 2 1 0

Druckerkabel
nachfolgende Register
Bit Nr 7 6 5 4 3 2 1 0

3 Eingnge, von wo aus dem Computer Eingangssignale (0V bzw. 5V) gemeldet werden knnen

25-poliger SUB-D-Stecker

Computer

36-poliger CENTRONICS-Stecker

Physik-Technik

34

Um einen zuverlssigen Gebrauch der PORT.DLL zu gewhrleisten, sollen folgende Mindestvoraussetzungen gegeben sein: - die Datei PORT.DLL befindet sich im WindowsVerzeichnis ...\windows\system\ oder aber im Verzeichnis des laufenden EXE-Programms (hier DELPHI). - die UNIT PORTINC.PAS (besser noch die bereits compilierte Form PORTINC.DCU) befindet sich jeweils im Verzeichnis des aktuellen Projektes. Sie stellt ein externes Delphi-Modul dar, das alle DLL-Aufrufe vollstndig deklariert enthlt, so dass der Programmierer den Zugriff auf alle DLL-Bestandteile hat, ohne sich noch um die genauen Deklarationskonventionen kmmern zu mssen. - Die UNIT PORTINC muss in der USES-Liste der DELPHIAnwendung aufgelistet sein. - Mit Hilfe der Konstantenvereinbarung: const BA = $378; wird als Basisadresse die des Datenregisters, welches die 6 Ausgnge AUS 0, .., AUS 5 der EIN/AUSGABE-Platine bedient, vereinbart. Damit ist das Statusregister, welches die Auswertung der drei Eingnge EIN0, .., EIN2 dieser EIN/AUSGABE-Platine ermglicht, unter der Adresse BA + 1 ansprechbar. - Ab Betriebssystemversion WINDOWS NT (und hher) ist zustzlich eine Sys-Datei mit dem Namen UserPort.Sys ins Verzeichnis WINNT \ SYSTEM32 \ DRIVERS zu kopieren und jeweils vor Start der Delphi-Anwendung (also vor dem ersten Compilieren) die Datei UserPort.Exe aus dem Verzeichnis INTERFACE-Zusatzprogramme zu starten. Hierdurch wird der eigentlich durch die Windowsentwickler nicht erlaubte Zugriff auf die parallele Schnittstelle doch wieder ermglicht.

Physik-Technik

35

Die Auswertung des STATUS-Registers

Konstruiere das vorgegebene Delphi-Formular. Neu fr dich ist die TIMER-Komponente, die du auf der Seite System der Komponentenpalette findest und wie gewohnt auf dem Formular plazieren kannst. Mit Doppelklick auf diese Komponente wechselst du in den Editor. Im Objektinspektor siehst du, dass dieses Timerobjekt nur ber wenige Eigenschaften verfgt. Zwei davon sind wichtig fr uns: Enabled bestimmt, ob der der Timer ein- (true) oder ausgeschaltet (false) ist. Interval bestimmt das Zeitintervall (in Millisekunden), in dem eine Aktion des Timers ausgelst wird. Innerhalb der Methode procedure TForm1.Timer1Timer(Sender: TObject); begin end; sind nun alle Anweisungen einzufgen, die fr das regelmige Abfragen des aktuellen Inhalts des Statusregisters ( also der aktuellen Belegung der EIN0, .., EIN2 Eingnge) von Bedeutung sind. Und das sind nacheinander die Abfrage und die Ausgabe des Inhaltes dieses Statusregisters. Die beiden folgenden Anweisungen mssen also mit einer entsprechenden

Physik-Technik

36

Variablenvereinbarung in die Methode Timer1Timer bertragen werden: daten_ein := InPort(BA + 1); StatusEdit.Text := IntToStr(daten_ein); Jetzt muss nur noch dafr gesorgt werden, dass dieses Abfragen des aktuellen Wertes des Statusregisters z.B. jede 1/10 Sekunde = 100 Millisekunden erfolgt. Die entsprechende Interval-Eigenschaft des Timer-Objektes wird deshalb gleich beim Programmstart in der FormCreate-Prozedur passend gesetzt. Ebenfalls wird dort der Timer erst einmal ausgeschaltet, weil wir ihn ber den StartStoppButton gezielt ein- bzw ausschalten wollen. Dies fhrt zu: procedure TForm1.FormCreate(Sender: TObject); begin Timer1.Enabled:=false; Timer1.Interval:=100; StartStoppButton.Caption := 'Messung starten'; end; ber den StartStoppButton sorgen wir nun fr ein gezieltes Ein/Ausschalten des Timers und einer stets aktuellen Ausgabe des STATUS-Register-Wertes. procedure TForm1.StartStoppButtonClick(Sender: TObject); begin if timer1.enabled = false then begin Timer1.Enabled:= true; StartStoppButton.Caption := 'Messung STOPPEN'; end else begin Timer1.Enabled:= false; StartStoppButton.Caption := 'Messung STARTEN'; StatusEdit.Text := ''; end; end;

Physik-Technik

37

Bei Fehlermeldungen solltest du nochmals berprfen, ob auch alle Mindestvoraussetzungen, die auf Seite 31 aufgelistet sind, erfllt sind. Aufgabe: Verschaffe dir eine bersicht ber die Werte des Statusregisters in Abhngigkeit von den Belichtungsverhltnissen an den mit LDR bestckten Eingngen EIN0, EIN1 und EIN2. STATUSREGISTER BIT Nr 6 5 4 3 2 1 DEZIMALWERT Belichtung (hell/dunkel) EIN0 EIN1 EIN2

Ergebnis: Bit 3 fhrt den Wert 0 (bzw.1) genau dann, wenn die Lichtschranke an EIN0 hell (bzw. verdunkelt) ist. Bit 5 fhrt den Wert 0 (bzw.1) genau dann, wenn die Lichtschranke an EIN1 hell (bzw. verdunkelt) ist. Bit 7 fhrt den Wert 0 (bzw.1) genau dann wenn die Lichtschranke an EIN0 verdunkelt (bzw hell.) ist (INVERTIERUNG an Bit 7). Weil nur die Bits 3, 5 und 7 `effektiv vorhersehbar` jeweils mit Wert belegt sind (die nicht angeschlossenen Bits 0,1,2,4,6 sind nicht unbedingt alle immer gleich belegt - und schon gar nicht von alleine mit Wert Null - , muss die Abfrage der Belegung der drei Eingnge bitweise unter Verwendung der AND Verknpfungsanweisung erfolgen. Z.B. fr die an EIN0 ( Bit 3; entspricht 8 10)angeschlossene Lichtschranke: If daten_ein AND 8 = 0 then AusgabePanel1.Caption:= Die an EinO angeschlossene Lichtschranke ist belichtet. else AusgabePanel1.Caption:= Die an EinO angeschlossene Lichtschranke ist verdunkelt.

Physik-Technik

38

Die Verwendung des Datenregisters:

Erzeuge das obige Delphi-Formular. Schalte ber die FormCreate Methode den Timer aus. Nach einem Mausklick auf den StartStoppButton soll der Timer eingeschaltet sein und die ButtonAufschrift sich in `STOPP` verndern. Wenn dieser Button mit der Aufschrift `STOPP` dann mit der Maus angeklickt wird, soll der Timer ausgeschaltet werden und sich die Button-Aufschrift in `START` verndern. Innerhalb der Timer1Timer-Methode soll nun dafr gesorgt werden, das im Sekundentakt erst alle Ausgnge einzeln, dann die Ausgnge paarweise (1,2; 3,4; 5,6;), dann in Dreiergruppen (1,2,3; 4,5,6;) und zum Abschluss alle sechs gleichzeitig ein HIGH-Signal fhren. Damit diese unterschiedlichen Belegungen des Datenregisters deutlich voneinander unterschieden werden knnen, soll jede einzelne Belegung durch den Befehl delay(dauer); eine Sekunde lang ( das sind 1000 Millisekunden) Bestand haben. Das setzt voraus, dass die Konstantenvereinbarung erweitert wird auf const BA = $ 378; dauer = 1000; . Die Verwendung der 5 x 8 LED Matrix Die in 8 Zeilen zu jeweils 5 Stck angeordneten Leuchtdioden dienen z. B. zur Schrift-Ausgabe. Dazu mssen in schneller Folge genau die Leuchtdioden aufleuchten, die dann in ihrer Gesamtheit bedingt durch die Trgheit des Auges das Erscheinungsbild eines bestimmten Buchstabens ergeben.

Physik-Technik

39

Elektronische Realisierung der 5X8 LEDMatrix


7 6 5 4 3 2 1 1 0 1
Dual Dezimal Decoder der Zahlen von 0 bis 7

22

21

20

Bit 0 1

3 4 5 6 des Datenregisters

Physik-Technik

40

Die Verdrahtung auf der Platine ist so erfolgt, dass vom Datenregister die ersten 5 Bit (Bit 0, 1,...,4) eine der 5 Leuchtdioden jeder Zeile ansprechbar machen und die restlichen drei Bit (Bit 5, 6, 7) die jeweilige Zeile (Zeilennummer 0, 1 ,..., 7) charakterisieren. Weiterhin ist die Verdrahtung so realisiert, dass zum Aufleuchten einer bestimmten LED das entsprechende Bit des Datenregisters einen 0-Wert fhren muss. Aufgabe: Schreibe ein Delphi-Programm, welches auf der 5x8-LED-Matrix a) den Grobuchstaben A erscheinen lsst b) nacheinander die Grobuchstaben S Leerzeichen O Leerzeichen S Leerzeichen erscheinen lsst. Buchstabe A Datenregister bitweise Bit 0 1 2 3 4 5 6 7 Wert des Datenregisters LED-Auswahl Spalte Zeile

LED-Muster

Zeile 7 6 5 4 3 2 1 0

LED-Muster

Leerzeichen Datenregister bitweise Bit 0 1 2 3 4 5 6 7 Wert des Datenregisters LED-Auswahl Spalte Zeile

Zeile 7 6 5 4 3 2 1 0

Physik-Technik

41

LED-Muster

Buchstabe S Datenregister bitweise Bit 0 1 2 3 4 5 6 7 Wert des Datenregisters LED-Auswahl Spalte Zeile

Zeile 7 6 5 4 3 2 1 0

LED-Muster

Buchstabe O Datenregister bitweise Bit 0 1 2 3 4 5 6 7 Wert des Datenregisters LED-Auswahl Spalte Zeile

Zeile 7 6 5 4 3 2 1 0

Physik-Technik

42

UNTERPROZEDUREN Bei der Programmieraufgabe Schreiben der Buchstabenfolge S Leerzeichen O Leerzeichen S Leerzeichen ist die Befehlsfolge zum Erzeugen des Leuchtmusters fr den Buchstaben S zweimal, das des Leerzeichens sogar dreimal abzurufen. Es ist sicherlich nicht sinnvoll dieselbe Befehlsfolge mehrfach in das Programm (genauer: die Prozedur Timer1Timer(..) ) aufzunehmen und damit den Programmumfang unntig lang und unbersichtlich zu gestalten. Hier bedient man sich der Technik, die mehrfach bentigte Befehlsfolge in eine Unterprozedur zu packen und diese Unterprozedur dann an der passenden Stelle aufzurufen. Da die Befehlsfolgen fr das BuchstabenLeuchtmuster hier nur innerhalb Timer1Timer(..)-Prozedur aufgerufen werden und sonst nirgendwo, ist es auch sinnvoll, die Unterprozeduren LOKAL innerhalb der Timer1Timer(..)-Prozedur zu deklarieren. Konkret ergibt sich folgendes: procedure TForm1.Timer1Timer(Sender: TObject); Procedure Leerzeichen; Var i : integer; begin For i := 1 to dauer2 do begin OutPort(BA,255); delay(dauer1); OutPort(BA,223); delay(dauer1); OutPort(BA,191); delay(dauer1); OutPort(BA,159); delay(dauer1); OutPort(BA,127); delay(dauer1); OutPort(BA,95); delay(dauer1); OutPort(BA,63); delay(dauer1); OutPort(BA,31); delay(dauer1); end; end; Procedure Buchstabe_S; var i : integer; begin for i := 1 to dauer2 do begin OutPort(BA,225); delay(dauer1); OutPort(BA,222); delay(dauer1); OutPort(BA,190); delay(dauer1); OutPort(BA,157); delay(dauer1); OutPort(BA,123); delay(dauer1); OutPort(BA,87); delay(dauer1);

Physik-Technik

43

OutPort(BA,47); delay(dauer1); OutPort(BA,16); delay(dauer1); Outport(BA,31); delay(dauer1); end; end; end; Procedure Buchstabe_O; var i : integer; begin for i := 1 to dauer2 do begin OutPort(BA,241); delay(dauer1); OutPort(BA,206); delay(dauer1); OutPort(BA,174); delay(dauer1); OutPort(BA,142); delay(dauer1); OutPort(BA,110); delay(dauer1); OutPort(BA,78); delay(dauer1); OutPort(BA,46); delay(dauer1); OutPort(BA,17); delay(dauer1); Outport(BA,31); delay(dauer1); end; end; begin Buchstabe_S; delay(dauer2); Leerzeichen; delay(dauer2); Buchstabe_O; delay(dauer2); Leerzeichen; delay(dauer2); Buchstabe_S; delay(dauer2); Leerzeichen; delay(dauer2); end; Durch eine geschickte Wahl der Konstanten dauer1 und dauer2 kann man erreichen, dass das Leuchtmuster des Buchstabens deutlich wahrgenommen werden kann. Mit einer entsprechenden Sammlung von Unterprozeduren sind alle denkbaren Zeichen auf der 5x8-LED-Anzeige erzeugbar. Das gewnschte Zeichen wird dann einfach durch Eintragen des Namens der entsprechenden Unterprozedur aufgerufen.

Physik-Technik

44

Der simultane Gebrauch von Daten- und Statusregister: Im Unterricht wurde unter LOCAD die elektronische Lsung und Realisierung einer automatisierten Stckgutverpackung mit zwei Laufbndern entwickelt. In Abhngigkeit von den Belichtungsverhltnissen an drei Lichtschranken wurden die beiden Frderbandmotoren gesteuert. Als besonders einprgsam in Erinnerung geblieben ist die Tatsache, dass die Elektronikbaugruppen, die - einzeln fr sich alleine betrieben fehlerlos funktionierten, beim Zusammenfgung zu einer komplexen Schaltung aufeinander Streinflsse ausbten, die wiederum nur durch besondere schaltungstechnische Tricks (Diode, Kondensator,..) berlistet werden konnten. Hier kann ein Delphi-Programm Abhilfe schaffen, indem es die komplizierte Elektronik durch ein entsprechendes Programm ersetzt. Je nach den Belichtungsverhltnissen an den drei Lichtschranken (Inport-Befehl) steuert es den Lauf der beiden Frderbandmotoren (Outport-Befehl).
Aufgabenstellung: Automatische Stckgutverpackung durch ein Delphi-Programm Die Frderbandanlage wird durch Maus-Clicks am Bildschirm gesteuert

EIN0 LS0 Zhlerlichtschranke, EIN1 LS1 Auffangkartonlichtschranke Ein2 LS2 Lichtschranke am Ende des unteren Frderbandes Motor1 (oberes Frderband) an AUS1, Motor2 (unteres Frderband) an AUS2

Physik-Technik

45

Die zugehrigen Methoden betreffen: procedure FormCreate(Sender: TObject); procedure Freigabe1ButtonClick(Sender: TObject); procedure Freigabe2ButtonClick(Sender: TObject); procedure NotAusButtonClick(Sender: TObject); procedure ZaehlerstandResetButtonClick(Sender: TObject); procedure Timer1Timer(Sender: TObject);
LSUNG: Die Prozeduren des Frderbandprojektes procedure TForm1.FormCreate(Sender: TObject); begin Outport(BA,8); {Lichtschranken-Energieversorgung an AUS3} Freigabe1 := false; Freigabe2 := false; Zaehlerstand := 0; ZaehlerstandEdit.text := IntToStr(zaehlerstand); LS0_alt := 0; Timer1.enabled := true; timer1.interval := 100; end; procedure TForm1.Freigabe1ButtonClick(Sender: TObject); begin If freigabe1 = false then begin freigabe1 :=true; Freigabe1button.caption := 'StoppMotor1'; end else begin freigabe1 :=false; Freigabe1button.caption := 'FreigabeMotor1'; end;

Physik-Technik end; procedure TForm1.Freigabe2ButtonClick(Sender: TObject); begin If freigabe2 = false then begin freigabe2 :=true; Freigabe2button.caption := 'StoppMotor2'; end else begin freigabe2 :=false; Freigabe2button.caption := 'FreigabeMotor2'; end; end; procedure TForm1.NotAusButtonClick(Sender: TObject); begin Freigabe1 :=false; Freigabe1button.caption := 'FreigabeMotor1'; Freigabe2 :=false; Freigabe2button.caption := 'FreigabeMotor2'; end; procedure TForm1.ZaehlerstandResetButtonClick(Sender: TObject); begin Zaehlerstand := 0; ZaehlerstandEdit.text := IntToStr(zaehlerstand); end;
procedure TForm1.Timer1Timer(Sender: TObject); var daten_ein : byte; begin daten_ein := Inport(BA+1); If (daten_ein AND 8 = 0) then Zustand0Edit.text :='belichtet' else Zustand0Edit.text :='verdunkelt'; If (daten_ein AND 32 = 0) then Zustand1Edit.text :='belichtet' else Zustand1Edit.text :='verdunkelt'; If (daten_ein AND 128 = 0) then Zustand2Edit.text :='verdunkelt' else Zustand2Edit.text :='belichtet'; If (Freigabe1 = true) AND (zaehlerstand < Anzahl) AND ((daten_ein AND 32) <> 0) then begin Motor1Edit.Text := 'luft'; Outport(BA,10); if (daten_ein AND 8)=0 then if LS0_alt =1 then begin Zaehlerstand :=Zaehlerstand +1; ZaehlerstandEdit.Text := IntToStr(Zaehlerstand); LS0_alt :=0; end else begin {keine Aktion} end else LS0_alt :=1;

46

Physik-Technik
end else begin Outport(BA, (Inport(BA) AND 12) ); {gezielt Motor1 ausschalten, ohne die anderen Ausgnge zu beeinflussen; Ausgang 3 wird fr die Energieversorgung der Lichtschranken benutzt; alle anderen Ausgnge sollen abgeschaltet sein} Motor1Edit.Text := 'steht'; end;

47

If ((Freigabe2 = true) AND (Zaehlerstand =Anzahl) AND ((daten_ein AND 128)<>0)) then begin Outport(BA,12); Motor2Edit.Text := 'luft'; end else begin Outport(BA, (Inport(BA) AND 10)); {gezielt Motor2 ausschalten, ohne die anderen Ausgnge zu beeinflussen; Ausgang 3 wird fr die Energieversorgung der Lichtschranken benutzt; alle anderen Ausgnge sollen abgeschaltet sein} Motor2Edit.Text := 'steht'; If (daten_ein AND 128= 0) then begin Zaehlerstand :=0; ZaehlerstandEdit.Text:=IntToStr(Zaehlerstand); end; end; end; end.