Schleifen Sie den GEM-Juwel (2)

Nachdem wir im ersten Teil unseres GEM-Kurses das RCS unter die Lupe nahmen, zeigen wir Ihnen heute, wie Sie Resourcen unter GFA-Basic nutzen.

Wenn Sie dem letzten Beispiel folgten und alles klappte, hat das RCS drei Dateien gespeichert: die RSC-Datei selbst (Endung .RSC), eine Definitionsdatei (.DFN, bei manchen RCS auch .RSD) sowie ein GFA-Listing (.LST).

In der RSC-Datei befinden sich alle Informationen, die notwendig sind, damit GEM die neue Dialogbox zeichnet. Die Definitionsdatei enthält einige zusätzliche Daten, nämlich die Typen und Namen der Objektbäume. Diese Angaben benötigt das GEM nicht, sie sind daher für die Programmierung unerheblich. Löschen Sie die Datei trotzdem nicht, sie gewinnt unter Umständen doch an Bedeutung: Wenn Sie die Resource später ändern, definieren diese Informationen die Objekte im RCS. Fehlt die Datei, müssen Sie diese Definition per Hand nachholen. Das ist zwar nicht schwer, aber bei größeren Dateien arbeitsaufwendig. Besonders wenn Sie fremde Resourcen ändern wollen, bei denen ja meist die DFN-Datei fehlt, bleibt Ihnen dieser Schritt nicht erspart.

Dabei gehen Sie am besten folgendermaßen vor: Nach dem Laden in das RCS sind die Elemente der Resource mit einem Fragezeichen gekennzeichnet. Beim Anklicken der Parts fragt das Programm nach dem Datentyp. Geben Sie bei jedem Element zunächst DIALOG ein. Nach dem Öffnen des Parts erkennen Sie leicht den wahren Typ. Bei einem Menübaum sehen Sie die Menüleiste; auf einen Mausklick klappen die Einträge herunter. Außerdem stehen die Menübäume erfahrungsgemäß (aber nicht immer!) an erster Stelle der Resource. Die anderen Elemente können Sie als Dialogboxen belassen, denn Alertboxen und FREE's erkennt das RCS selbständig, und zwischen Panels und Dialogen besteht (siehe Teil 1) kein großer Unterschied.

Zurück zu unseren Dateien. Die letzte noch verbliebene Datei ist das *.LST File. Es liegt im ASCII-Format vor und läßt sich somit direkt in GFA-Basic mergen. In unserem.Fall sieht die Datei folgendermaßen aus:

LET TREE18=0 !RSC_TREE
LET BUTTON1&=3 !Obj in # 0 
LET BUTTON2&=4 !Obj in # 0

Falls Sie nicht das RCS von Digital Research RCS V2.1 benutzen, sehen Sie wahrscheinlich eine Datei, die für C gedacht ist (Endung meist *.H). Diese lautet dann so:

/* resource set indices for BSPl */
# define TREE1 0 /* form/dialog */
# define BUTTONI 3 /* BUTTON in tree TREEI */
# dehne BUTTON2 4 /* BUTTON in tree TREE1 */

Damit kann GFA-Basic natürlich nichts anfangen und versieht jede Zeile mit einem Pfeil. Sie müssen deshalb die Datei per Hand in die Form des ersten Listings umschreiben.
Aber welchen Zweck erfüllt diese Datei? Nun, Sie erkennen in dem Listing vielleicht die Bezeichnungen wieder, die Sie den Elementen der Resource gegeben haben. TREE1 lautete die Bezeichnung für die Dialogbox, und BUTTONl und 2 waren die Namen für die beiden Knöpfe. TREEl mit dem Wert 0 ist die erste Box in der Resource, BUTTON 1 ist das dritte Objekt in der Box (die ersten beiden sind die Strings) usw. Unter Umständen weichen Ihre Werte für die Buttons von unserem Beispiel ab, das ist kein Grund zur Besorgnis.

Das RCS teilt Ihnen durch dieses Listing mit, unter welchen Variablenwerten Sie die einzelnen Objekte ansprechen. Natürlich können Sie auch darauf verzichten und den Objekten einfach keinen Namen geben, dann müssen Sie allerdings auch selbst herausfinden, welches Element Sie auf welche Weise ansprechen. Etwas umständlich, besonders weil die Numerierung mit jeder Änderung an der Resource wechseln kann. Es empfiehlt sich also immer, die Objekte sorgfältig zu benennen.
So weit, so gut, jetzt können wir uns endlich daran machen, die Resource aufzurufen. Dazu müssen wir sie natürlich erst einmal laden. GFA-Basic 3.0 besitzt dazu eine eigene Funktion. Unter GFA Basic 2.0 ist die Sache etwas komplizierter; die entsprechende Anpassung finden Sie auf unserer Leserservice-Diskette, genauso wie für alle anderen Beispiele. So rufen Sie die Funktion auf:

R%=RSRC_LOAD(name$)

wobei name$ der Dateiname und R% ein Rückgabewert ist. R% hat nur eine Bedeutung, wenn er Null wird. Dann ist nämlich ein Fehler aufgetreten - Datei nicht gefunden, Diskette kaputt oder ähnliche freudige Überraschungen. Wenn Sie soviel Vertrauen haben, daß dieser Fall nie eintritt, können Sie die Funktion auch mit VOID aufrufen, dann »vergißt« sie den Rückgabewert. Der ST reserviert bei diesem Befehl erst den notwendigen Speicherbereich und lädt dann die Datei dorthin. Im nächsten Teilschritt stellen wir fest, wo genau (d.h. ab welcher Adresse) sich die Resource jetzt befindet. Auch dazu gibt es wieder eine Funktion, sie lautet R%=RSRC_GADDR(O,treel&,tree$) wobei GADDR für »Get Address« steht.

Für R% gilt dasselbe wie oben. Die Übergabe von treel& bestimmt, welcher Objektbaum gemeint ist. In unserem Fall gibt es nur einen, nämlich die Box. Hätten wir noch einen zweiten Baum in derselben Resource, müßten wir die entsprechende Variable angeben, also etwa tree2& mit dem Wert 1. Nicht zu verwechseln damit ist der Rückgabewert tree%, in dem uns das GEM mitteilt, in welchen Speicherbereich es die Box verfrachtet hat - was ja der Sinn des Aufrufes war. Diese Variable brauchen wir später.

Bevor die Box endgültig auf dem Bildschirm erscheint, muß sie zentriert, d. h. an die Auflösung angepaßt werden. Auch das nimmt uns das GEM ab, und zwar mit der Funktion

FORM_CENTER(tree%,x%,y%,w%,h%)

Der erste Parameter enthält die Adresse, an der sich der zu zentrierende Objektbaum befindet. Diese Adresse haben wir mit RSRC__GADDR schon herausgefunden und übergeben deshalb einfach die Variable tree%. In x% und y% stehen nach Funktionsaufruf die Koordinaten der linken oberen Ecke der Box, in w% und h% ihre Breite bzw. Höhe. Die Werte interessieren uns aber im Moment nicht. Statt dessen zeichnen wir jetzt endlich die Box, und zwar mit ~OBJC-DRAW(tree%,0,8,0,0,639,399) Der Parameterwulst hat folgende Be-. deutung: Zuerst gibt tree% wieder den Objektbaum an. Die zweite Zahl bestimmt, ab welchem Element das Zeichnen beginnt. 0 bedeutet dabei ganze Box - und nicht, wie im GFA Handbuch angegeben, nur erstes Objekt. Bei einer 3 beispielsweise wird nur das dritte Objekt des Baumes gezeichnet, in unserem Fall also nur ein Button - was nicht allzu sinnvoll ist. Der dritte Parameter gibt die gewünschte Objekttiefe an. Was das konkret bedeutet, klären wir nächstes Mal. Bis dahin belassen Sie es beim Wert B. Die letzten vier Parameter bestimmen einen Bildschirmausschnitt, der die Ausgabe begrenzt (entspricht dem Befehl CLIP). Wir nehmen den ganzen Bildschirm, also lauten die Werte in der hohen Auflösung 0,0,639 und 399. Somit ist die Box auf dem Bildschirm, benutzen können wir sie aber noch nicht. Dazu bedarf es eines weiteren Befehles, nämlich

O%=FORM_DO(tree%,0)

Die 0 gibt dabei wieder das Startobjekt an. In O% steht nach dem Funktionsaufruf die Nummer des Objektes, mit dem wir die Box verlassen haben. Erinnern wir uns: GEM nimmt beim Aufruf einer Resource (hier mit FORM-D0) die Kontrolle über den Programmablauf an sich und gibt sie erst wieder ab, wenn der Benutzer ein mit Exit deklariertes Objekt anklickt - in unserem Fall einen der beiden Buttons. Fehlt so ein Objekt, hängt der ST, und zwar bis ans Ende seiner Tage - oder bis zum nächsten Reset. Beachten Sie bitte, daß Sie das. Programm nicht abbrechen können, während es die Box abfragt - denn GFA Basic hat ja im Moment nichts zu sagen. O% hat nach dem Funktionsaufruf den Wert von BUTTON1& oder BUT TON2& angenommen, je nachdem, mit welchem Knopf Sie die Box verlassen haben. Die Variable werten wir noch aus, und dann sind wir auch schon fertig. Vor Beenden des Programmes geben wir den von der Resource belegten Speicher frei, sonst konfrontiert Sie der Computer nach einigen Durchläufen mit einem Absturz wegen Speichermangels. Die Freigabe erfolgt durch

~RSRC_FREE()

Speichern Sie bei der Arbeit mit Resourcen das Programm vor jedem Durchlauf, man weiß nie, ob man es sonst noch mal wiedersieht. Zur Übersicht das fertige Programm, hier noch etwas erweitert:

LET tree1&=0 !RSC TREE
LET button1&=3 !Obj in # 0
LET button2&=4 ! Obj in # 0
~RSRC_LOAD("BSP1.RSC") !Resource laden und Speicher reservieren
~RSRC_GADDR(0,0,tree%) !Adresse des Objektbaums bestimmen
REPEAT
~FORM_CENTER(tree%„x%,y%, w%,h%) !Box zentrieren
~OBJC-DRAW(tree%,0,7,0,0, 639,399) !Box zeichnen
o%=FORM_DO(tree%,0) !Resource abfragen
IF o%=button1& !Auswerten
   PRINT "Weitermachen"
ENDIF 
UNTIL o%=button2& 
PRINT "Abbrechen"
~RSRC_FREE()

Der »Kern« des Programmes, also die Anweisungen zum Laden und Verwalten der RSC-Datei, ist universell einsetzbar, d.h. Sie können mit dem Grundgerüst auch jede fremde Resource laden. Nur die Auswertung müssen Sie natürlich anpassen.

Wenn Sie das Programm jetzt ablaufen lassen, stellen Sie fest, daß die Buttons nach dem ersten Anklicken ihren selektierten Zustand behalten, sie bleiben also invers. Erst ein neuerliches Anklicken färbt sie wieder normal. Diesen Zustand ändern Sie durch einen Befehl. Er lautet

OB_STATE(tree%,obj&)=s%

Obj& ist die Nummer des Objektes im Objektbaum, in unserem Fall BUTTON1& oder BUTTON2&. S% gibt den Zustand an, den das Objekt annehmen soll. Zur Wahl stehen dabei Zustand Wert

SELECTED (angewählt) 1
CROSSED (durchgestrichen) 2
CHECKED (abgehakt) 4
DISABLED (ausgeschaltet) 8
OUTLINED (umrandet) 16
SHADOWED (schattiert) 32

Um einen dieser Effekte zu erreichen, übergeben Sie einfach den entsprechenden Wert. Wollen Sie mehrere Effekte kombinieren, sind die Zahlen zu addieren, beispielsweise für schattiert und abgehakt 32+4=36. Sie können den Wert natürlich auch bitweise zusammensetzen, hier also S%=&X100100.

Wollen Sie das Objekt normal darstellen, ist S% gleich 0 - wie in unserem Fall. Also:

OB_STATE(tree%,o%)=0

Fügen Sie diese Zeile vor das UNTIL ein.

Zu beachten ist, daß dieser Befehl das Objekt nur intern ändert. Wollen Sie die Änderung auch sehen, müssen Sie die Box mit OBJC-DRAW noch einmal zeichnen. Deshalb bleibt auch der Abbruch-Button nach Programmende scheinbar angewählt. Natürlich können Sie die Eigenschaften auch im RCS festlegen:

Ein Klick auf das rechte Icon der dritten Zeile läßt ein Pull-Down-Menü herunterklappen, dessen untere sechs Punkte die Effekte enthalten. Eine Gegenfunktion, um den Status eines Objektes zu erfragen, gibt es natürlich auch. Sie lautet ebenso wie der Befehl

S%=OB_STATE (tree%, obj% )

wobei die Werte die gleiche Bedeutung wie oben haben.

Zu den einzelnen Varianten noch ein paar Erklärungen: Das Durchstreichen eines Objektes erfolgt immer in der Farbe Weiß (äußerst sinnvoll!) und wird daher auch so gut wie nie benutzt. Bei CHECKED erscheint der Haken in der linken oberen Ecke des Objektes. Ein als DISABLED gekennzeichnetes Objekt erscheint, sofern es Text enthält, in heller Schrift und ist nicht anwählbar. OUTLINE verpaßt dem Part keinen zweiten Rahmen, sondern versetzt einen bereits vorhandenen um einige Pixel nach außen.

Damit lassen wir es vorerst bewenden, widmen wir uns den Alertboxen. GFA Basic bringt solche Boxen mit Hilfe der Funktion ALERT relativ komfortabel auf dein Bildschirm. Das GEM gestaltet die Boxen noch etwas leistungsfähiger. Anstatt. vier Zeilen ä 30 Buchstaben stehen hier fünf Zeilen mit je 40 Buchstaben zur Verfügung, die Buttons dürfen je 20 Zeichen enthalten statt nur acht - zumindest offiziell. Aber leider macht uns hier das GEM (Graphics Error Manager) einen Strich durch die Rechnung: Ab einer bestimmten Zeichenzahl bringt es einiges durcheinander und die Box nicht mehr korrekt auf den Bildschirm (Bild 1). Also ist Einschränkung geboten: als Text nur 30 Zeichen pro Zeile, die Buttons nur zehn Buchstaben lang. Fünf Zeilen sind erlaubt.

Dabei ist allerdings zu beachten, daß die Box höchstens ein Viertel der gesamten Bildschirmfläche einnimmt sonst wird's wieder bombig. In der hohen Auflösung ist das gewöhnlich kein Problem, aber in den niedrigeren Auflösungen müssen Sie aufpassen und gegebenenfalls den Text kürzen.

Der Befehl, um eine Alertbox über das GEM zu erzeugen, lautet

R%=FORM_ALERT(button,string$)

wobei der Parameter button den Wert des Default-Knopfes enthält, also des Buttons, den ein Druck auf < Return > aktiviert. String$ enthält den Text sowohl für die Mitteilung als auch für die Buttons. Er hat folgendes Format: [N][TEXT][BUTTONS] N ist eine Ziffer zwischen 0 und 3, die das Icon der Alertbox festlegt. Dabei bedeutet

0 = Kein Symbol
1 = Ausrufezeichen
2 = Fragezeichen
3 = Stopschild

Für TEXT stehen die Zeichen, die in der Box erscheinen sollen. Der senkrechte Strich »I« trennt dabei die einzelnen Zeilen, genau wie beim Befehl Alert im normalen GFA-Basic.

BUTTONS enthält die Beschriftung der Buttons, wieder durch den Strich getrennt. Ein weiteres Problem dabei: Wenn die Länge aller Buttontexte zusammen mehr als fünf Zeichen über die längste Textzeile geht, werden Teile der Buttons verschluckt. In so einem Fall müssen Sie die Textzeilen mit Leerzeichen auffüllen, dann stimmt die Sache wieder.

R% enthält nach Funktionsaufruf wieder den Button, der in der Box angeklickt wurde. Die Routine für eine Alertbox sieht demzufolge so aus:

string$="[1][Ein Beispiel für eine mit GEM|erzeugte Alertbox. Sie kann|
15 Zeilen mit je 30 Zeichen |enthalten. Die Buttons dürfen |10 Buchstaben 
lang sein.] [Gigantisch |Phänomenal | Pfundig !!]"
r%=FORM_ALERT(1,string$)

Diese Box sollte so aussehen wie in Bild 1. Wenn Ihre Box nur Müll produziert, ist wahrscheinlich eine der Textzeilen zu lang. In so einem Fall müssen Sie den Text umverteilen.

Soviel zu den Alertboxen. Wie immer finden Sie alle Programmbeispiele au der Leserservice-Diskette. Nächstes Mal beschäftigen wir uns mit Texteingaben und nehmen außerdem die Hierarchien innerhalb einer Resource unter die Lupe.


Marc Kowalsky
Aus: ST-Magazin 12 / 1989, Seite 102

Links

Copyright-Bestimmungen: siehe Über diese Seite