Mobile Times Business Club
Startseite : Mobility : OPL Kurs
OPL OPL Kurs, Teil 8 Aktualisierung
2007-03-01
01: Einführung
02: Menüs und mehr
03: Basics, Zufall & Mathetrainer
04: Spielend lernen - Würfel, Bandit & Lotto
05: Datenbanken - Neu/Ändern/Löschen
06: Datenbanken - Suchen/Gehen Zu
07: Gezielte Textausgabe
08: Fensterl'n mit dem Psion
09: Zeichnen mit Grips
Fensterl'n mit dem Psion
In der letzten Folge haben wir uns mit der Positionierung und Formatierung von Text auseinandergesetzt. Dabei haben wir uns auf das Standardfenster beschränkt. Dieses Mal erweitern wir den Horizont und stoßen weitere Fenster auf.
    Für viele Programme ist die Verwendung von Fenstern ein hervorragendes Mittel, bestimmte Aufgaben bequem und elegant zu lösen. Darüber hinaus sind neben der eigentlichen Grafik gerade Fenster ganz besonders geeignet, dem eigenen Programm ein "Gesicht" zu geben.
    Zu Ihrer Erinnerung: Ein Fenster ist ein selbst definierter, rechteckiger Bereich auf dem Bildschirm mit unabhängigen eigenen Eigenschaften. Der Inhalt des Fensters wird vom Betriebssystem eigenständig verwaltet, so daß man selber weniger Rücksicht beim Programmieren nehmen muß.

Ein anschauliches Beispiel
Unter Verwendung des Standardfensters wollen Sie erreichen, daß z.B. in der rechten oberen Ecke des Bildschirms ständig das aktuelle Datum angezeigt wird. Der Rest des Bildschirmes wird für andere Aufgaben benutzt, muß aber von Zeit zu Zeit mit CLS oder gCLS gelöscht werden. Die Befehle zum Löschen des Bildschirmes arbeiten leider nicht selektiv, so daß unerwünschterweise auch das Datum mitgelöscht wird.
    Wenn Sie das Datum nun nicht immer wieder neu schreiben wollen, benutzen Sie einfach ein kleines separates Fenster und schreiben es einmalig dort hinein. Der nächste Löschbefehl im Standardfenster ist in einem solchen separaten Fenster nicht wirksam und der gewünschte Effekt erreicht!
    Da der Bildschirm lediglich das Ausgabemedium ist, hat er für die Bewältigung des Problems eine Menge Rechenarbeit zu leisten - aber uns braucht das nicht zu kümmern. Wir genießen einfach das Ergebnis.

Fenster erzeugen
Auf den Psion Serie 5 lassen sich bis zu 64 Fenster gleichzeitig anlegen ("öffnen") und verwenden.
    Für das Anlegen eines Fensters steht ein komplexer Befehl mit mehreren Parametern bereit:
gCREATE (xpos%, ypos%, breite%, höhe%, sichtbar%)
    Über die Parameter in der Klammer, allesamt Integerzahlen, teilt man mit, wo das Fenster auf dem Bildschirm erscheinen soll und welche Abmaße es hat. Das verwendete Maß ist "Pixel". Der fünfte Parameter sorgt dafür, daß das Fenster sofort auf dem Bildschirm sichtbar wird (sichtbar%=1) oder eben nicht (sichtbar%=0). Ein Grund, ein Fenster unsichtbar anzulegen, besteht darin, es erst mit dem Inhalt zu füllen und danach sichtbar zu machen. Der Betrachter soll den Bildaufbau nicht sehen können, insbesondere, wenn es sich um langsam aufbauende Grafiken handelt. Ein gVISIBLE ON ist dann in der Folge gewissermaßen der Einschalter für das Fenster. Für einen neuen Bildaufbau läßt es sich mit gVISIBLE OFF aber auch erneut verstecken:
Fenster 1
PROC fenster1:
   GLOBAL win%
   win%=gCREATE (25,25,200,50,0)
   gBORDER 0
   gAT 5,15 : gPRINT "Fenster Nr" , win%
   GET : gVISIBLE ON
   GET : gVISIBLE OFF
   GET
ENDP
    Im Beispiel wird ein unsichtbares Fenster mit einer Umrahmung angelegt, in das ein Text geschrieben wird. Nach einem Tastendruck wird es sichtbar und wieder unsichtbar.
    Der Befehl "gCREATE()" liefert nach der Ausführung quasi eine Art Fertigmeldung in Form einer Zahl ab, die in diesem Falle die Nummer des Fensters enthält. Dieser Wert wird hier zur Weiterverwendung in der Variablen win% aufbewahrt. Was wir damit anfangen können, zeigt das Beispiel ebenfalls. Der tiefere Sinn besteht allerdings darin, das Fenster gewissermaßen mit einem Namen ansprechen zu können, sonst haben Sie keine Chance, jemals wieder auf andere Fenster (einschließlich dem Standardfenster) zugreifen zu können.

"Du bist gemeint"
Wenn Sie ein Fenster neu öffnen, ist es automatisch das "aktuelle", mit dem man sofort etwas anfangen kann.
    Will man in ein beliebiges anderes wechseln, muß man das auch sagen und die Fenster-Nummer, oder wahlweise die Variable, die die Nummer enthält, kennen. Der Befehl dazu heißt:
"gUSE fensternummer%"
    Probieren wir das gleich aus:
Fenster 2
PROC m:
   GLOBAL win1%, win2%, win3%, x%, y%
   win1%=gIDENTITY
   win2%=gCREATE(25,25,200,50,1) : gBORDER 0
   win3%=gCREATE(50,50,200,50,1) : gBORDER 0
   GET : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win2% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win1% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   REM 1, Marke für Ergänzungen
   REM 2, Marke für Ergänzungen
   REM 3, Marke für Ergänzungen
   GET
ENDP
    Beim Programmstart steht lediglich das Standardfenster zur Verfügung. Das fragen wir gleich nach seiner Identifikationsnummer ("ID), schließlich wollen wir irgendwann auch einmal wieder dahin zurückkehren.
"gIDENTITY"
    ist der entsprechende Befehl, der die gewünschte Angabe liefert. Die ID für das Standardfenster steht eigentlich mit "1" fest, aber der Pingeligkeit halber haben wir auch dort nachgefragt...
    Im weiteren erzeugen wir zwei sofort sichtbare Fenster. Erst auf weitere Tastendrücke (Haltepunkte in vertrauter Weise mit GET...) werden die Fenster nun mit Text beschrieben. In welches Fenster geschrieben wird, teilen wir dem Betriebssystem per "gUSE id%" mit. Daß wir uns tatsächlich im angegebenen Fenster befinden, bestätigt uns der ausgegebene Wert von "gIDENTITY".
    Ist die Fenster-ID einmal genannt, beziehen sich alle weiteren Zeichen- und Schreibbefehle auf eben dieses. Bis zur nächsten Änderung.

Der Reihenfolge nach
Wenn Sie aufmerksam hinsehen, bemerken Sie, daß neue Fenster immer oben aufgelegt werden, gerade wie beim Ausspielen von Spielkarten. Dadurch können schon mal weiter unten liegende Fenster verdeckt werden - ein Effekt der durchaus auch erwünscht sein kann. Noch dazu, weil man die Schichtungsebene der Fenster beliebig ändern kann. Das Zauberwort lautet:
"gORDER id%,ebene%"
    Dabei trägt die oberste Ebene die Nummer 1. Gibt man eine Ebene an, deren Nummer größer ist, ist die Anzahl der offenen Fenster, landet das Fenster automatisch in der tiefstmöglichen Ebene - ohne Fehlermeldung. Wenn man also nicht aufpaßt, verschwindet ein kleines Fenster sogar völlig hinter dem großen Standardfenster!
    Die Ebenen-Reihenfolge läßt sich frei festlegen.
    Dieses ließe sich dadurch aber ebenfalls als großer Vorhang ausnutzen.
    Tragen Sie die folgenden Zeilen im obigen Programm "Fenster 2" anstelle der Zeile "REM 1" ein und verfolgen Sie, was geschieht...
GET : gORDER win2%,100
GET : gORDER win2%,1
Fenster 2.1
PROC m:
   GLOBAL win1%, win2%, win3%, x%, y%
   win1%=gIDENTITY
   win2%=gCREATE(25,25,200,50,1) : gBORDER 0
   win3%=gCREATE(50,50,200,50,1) : gBORDER 0
   GET : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win2% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win1% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gORDER win2%,100
   GET : gORDER win2%,1
   REM 2, Marke für Ergänzungen
   REM 3, Marke für Ergänzungen
   GET
ENDP
    Ist Ihnen nicht klar, welches Fenster in welcher Ebene liegt, aber Sie benötigen diese Angabe dringend, benutzen Sie "gRANK". Das liefert die Ebene des aktuellen Fensters zurück. Der Wert kann natürlich auch wieder in einer Variablen gespeichert werden. Ersetzen Sie "REM 2" im Programm "Fenster 2" durch die Zeilen:
GET
gUSE win1% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
gUSE win2% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
Fenster 2.2
PROC m:
   GLOBAL win1%, win2%, win3%, x%, y%
   win1%=gIDENTITY
   win2%=gCREATE(25,25,200,50,1) : gBORDER 0
   win3%=gCREATE(50,50,200,50,1) : gBORDER 0
   GET : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win2% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win1% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gORDER win2%,100
   GET : gORDER win2%,1
   GET
   gUSE win1% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
   gUSE win2% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
   REM 3, Marke für Ergänzungen
   GET
ENDP

Wo bin ich?
Neben diesen Informationen erfahren Sie weitere Eigenschaften von Fenstern per "gX" und "gY" (Cursorposition innerhalb des aktiven Fensters in Pixel) sowie "gORIGINX" und "gORIGINY" (Position der linken oberen Ecke des aktiven Fensters im Statusfenster, in Pixel.) Probieren Sie das aus, indem Sie im Programm "Fenster 2" die Zeile "REM 3" durch folgenden Programmtext ersetzen:
GET
gCLS : gBORDER 0
gAT 5,15
gPRINT "Fenster ID:" ,gIDENTITY
x%=gX : y%=gY
gAT 5,30
gPRINT "Cursor. X=" ,x%, "Y=" ,y%
gAT 5,4
x%=gORIGINX : y%=gORIGINY
gPRINT "Fenster: X=" , x%, "Y=" ,y%
Fenster 2.3
PROC m:
   GLOBAL win1%, win2%, win3%, x%, y%
   win1%=gIDENTITY
   win2%=gCREATE(25,25,200,50,1) : gBORDER 0
   win3%=gCREATE(50,50,200,50,1) : gBORDER 0
   GET : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win2% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gUSE win1% : gAT 5,15 : gPRINT "Fenster" , gIDENTITY
   GET : gORDER win2%,100
   GET : gORDER win2%,1
   GET
   gUSE win1% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
   gUSE win2% : gCLS : gBORDER 0 : gAT 5,15 : gPRINT "EBENE." , gRANK
   GET
   gCLS : gBORDER 0
   gAT 5,15
   gPRINT "Fenster ID:" ,gIDENTITY
   x%=gX : y%=gY
   gAT 5,30
   gPRINT "Cursor. X=" ,x%, " Y=" ,y%
   gAT 5,4
   x%=gORIGINX : y%=gORIGINY
   gPRINT "Fenster: X=" , x%, " Y=" ,y%
   GET
ENDP
    Weitergehende Informationen stellt "gINFO32" zur Verfügung, aber für den Anfang kommen Sie mit den genannten Befehlen aus.

Zwischentöne
Nachdem Sie nun über das Basiswissen verfügen, gehen wir auf ein bisher ausgespartes Thema ein, nämlich die Darstellung von Grautönen.

Grautöne - kein einfaches Thema.
Das Standardfenster stellt neben schwarz und weiß dazwischenliegend Grautöne dar. Reine schwarz/weiß Darstellung erreicht man mit "DEFAULTWIN 0", der 16-Farb-Modus wird durch "DEFAULTWIN 2" eingestellt.
    Besonders im 16-Farb-Modus wird der Farb/Grauton für Stift und Zeichenbefehle vorzugsweise mit dem neuen Befehl "gCOLOR rot%, grün%, blau%" eingestellt. Die Einzelwerte der Parameter dürfen von 0 (dunkel) bis 255 (hell) reichen. Sind alle drei Farbwerte gleich groß, entsteht ein Grauton. Wird die Palette auch in der Vierfab- oder Zweifarbdarstellung verwendet, gleicht das Betriebssystem die Farbtöne an das jeweils darstellbare Spektrum an.
    Sie können sich sicherlich vorstellen, daß die Darstellung von mehreren Grautönen in diesem Fall nicht mehr über Ebenen gelöst wird. Die Folge: Jedes Zeichen und Schreiben erfolgt direkt, d.h., wenn nach schwarz mit grau geschrieben wird, ist das Grau sofort und "obenliegend" sichtbar. Anstelle von "gCOLOR()" wird auch "gGREYx%" noch immer unterstützt und daher auch bequem verwendbar. Für x%=1 wird ein "leichtes Grau" abgebildet. unser Beispiel verwendet 6 Farb-/Graustufen.
Fenster 4
PROC fenster4:
   gCREATE (25,25,200,50,1,2) : gBORDER 0
   GET :  gAT 40,15 : gFILL 50,20,0
   GET :  gAT 50,30
   gGREY 1
      REM gCOLOR 128,128,128
      REM anstelle gGREY 1
   gPRINT "GANZ IN GRAU"
   GET
ENDP
    Wer den Workshop am EPOC32/r5-Emulator nachvollzieht, kann einmal die Farbzusammensetzung in der REM-Zeile verändern und nachsehen, was am Bildschirm passiert, wenn dann das REM entfernt wird...
    gMODE und gTMODE behalten für spezielle Anwendungen weiterhin ihre Berechtigung, der voreingestellte Wert "0" bewirkt, daß grundsätzlich alles bereits Vorhandene mit der aktuellen Farbeinstellung überschrieben wird.
    Je mehr Farben zum Einsatz kommen, desto höher ist der Speicherverbrauch!

Fensterinhalte sichern
Sie haben die Möglichkeit, die Inhalte von beliebigen Fenstern zu sichern, so daß Sie in der Lage sind, sie wiederzuverwenden.
    Besonders einfach ist der Vorgang, wenn ein komplettes Fenster abgespeichert werden soll:
gSAVEBIT "bildname"
    Das funktioniert aber auch mit Fensterausschnitten. Voraussetzung ist, daß der Cursor im Fenster an die linke obere Ecke des Ausschnittes positioniert wird. Dem Abspeicherbefehl braucht man lediglich noch die Breite und Höhe des zu sichernden Bereiches als Parameter mitzugeben:
gAT 20,20 : gSAVEBIT
name$,breite%,höhe%
    Wie man im Beispiel sieht, läßt sich anstelle des direkten Dateinamens wie üblich auch eine Stringvariable, in der der Dateiname steht, verwenden. Die Daten werden im Wurzelverzeichnis, ohne Datei-Endung abgelegt.
    Es handelt sich um eine sogenannte Bitmap-Datei, die im MBM-Format abgelegt wird. MBMs lassen sich durch die Verwendung von SKIZZE und dort durch "Hinzuladen EPOC-Grafik" ansehen und auch weiterverarbeiten (Speichern unter...).
Fenster 5
PROC fenster5:
   GLOBAL win%
   win%=gCREATE (50,50,110,60,1,1) REM 4 Graustufen
   gBORDER 0
   gAT 10,10 
   gFILL 80,30,0
   gGREY 1
   gAT 20,20
   gFILL 80,30,0
   gSAVEBIT "testbild_"
   GET
ENDP

Fenster und Farben - speichern und wiederverwenden.
Einmal gespeichert, stehen solche Dateien natürlich auch wieder einem geeigneten OPL-Programm zur Verfügung. Bevor man sie allerdings verwenden kann, müssen die Grafiken erst wieder geladen werden. Einfachste Variante:
gLOADBIT (name$)
    Möchte man nicht das Risiko eines versehentlichen Überschreibens eingehen, setzt man im folgenden die Variable schreib% auf Null. Handelt es sich um eine Bitmapdatei, die mehrere Einzelbilder enthält, gibt man in der Variablen i% auch die Bildnummer an (für Bild 1 ist i%=0):
gLOADBIT (name$, schreib%,i%)
    Im MBM-Format können durch externe Programme mehrere "echte" Bilder zusammengefaßt werden. Jedes wird dann durch seine Nummer aufgerufen. Von OPL aus ist das kombinierte Abspeichern allerdings nicht ohne weiteres zu leisten.
    Beim Laden einer Bitmap wird ein unsichtbares Fenster geöffnet, das bei der Anzahl der erlaubten offenen Fenster mitzählt. Schließen Sie grundsätzlich alle nicht benötigten Fenster und Bitmaps! Der Befehl ist, wie bereits genannt, "gCLOSE fenster%". In der Variablen fenster% müssen Sie die betreffende Fenster-ID übergeben.
    Die nun gerade geladene Bitmap-Grafik muß jetzt noch in ein geöffnetes Fenster oder auch das Standardfenster übertragen werden, sonst kann der Inhalt nicht sichtbar werden. Da durch das Laden das Bitmap-Fenster zum aktuellen wird, kehrt man zuerst mittels "gUSE" in das Fenster zurück, in dem die Grafik abgelegt werden soll. Schließlich kopiert man die Grafik:
gCOPY id,xpos%,ypos%,breite%,höhe%,modus%
    Dem Befehl "gCOPy" gibt man neben der Nummer des Bitmap-Fensters den Bereich mit, aus dem heraus kopiert werden soll, also die Ursprungskoordinaten links oben sowie Breite und Höhe des Bereiches. Soll die gesamte Grafik Verwendung finden, sind das also:
0,0,gWIDtH,gHEIGHT.
    Zu guter Letzt wird das ganze noch durch die Angabe des Modus' ergänzt, dessen Werte den Angaben bei "gGMODE" entsprechen.
Fenster 6
PROC fenster6: REM Grafik laden
   GLOBAL win%, bm%, b%, h%
   win%=gCREATE (50,50,150,100,1,1) REM 4 Graustufen
   gBORDER 0
   bm%=gLOADBIT ("testbild_")
   b%=gWIDTH
   h%=gHEIGHT
   gUSE win%
   gAT 20,20
   GET
   gCOPY bm%,0,0,b%,h%,0
   gCLOSE bm%
   GET
ENDP
    Nicht verschweigen wollen wir Ihnen, daß man Bitmap-Fenster mit OPL auch selber erzeugen kann:
("gCREATEBIT breite%,höhe%")
    Jedoch können wir keine Vorteile für die Nutzung entdecken. Im Gegenteil - es sind eine Reihe von Fehlern möglich, wenn man die üblichen Fensterbefehle anwendet. So haben wir darauf verzichtet, ohne daß ein Nachteil daraus erwächst...
    Zusammen mit dem vorhergehenden OPL-Workshop (alle grafischen Textausgaben lassen sich auch und gerade in Fenstern vorteilhaft einsetzen!) verfügen Sie nun über eine gute Grundlage, die bisherigen Demo-Programme oder auch die eigenen mit einer Form zu versehen, die sich sehen lassen kann.
    Beim nächstem Mal gehen wir dann auf die direkten grafischen Befehle ein. Bis dahin gilt wie immer:
    Experimentieren Sie fleißig!


OPL am Psion von Rudolf Pöchacker (http://members.xoom.com/poechacker/)
Valid HTML 4.01! Copyright © 2002-2007 Mobile Times Business Club
Zurück zum Menü
Nach Oben