2.0 Grundlegende Konzepte2.1.0 Objekte und Objekt-Bäume (Trees) ^2.1 Objekte und Objekt-Bäume (Trees)2.1.1 ÜberblickObjekte sind unter GEOS in sogenannten Bäumen (Trees) organisiert. Jedes Objekt hat genau ein Parent (Eltern) und kann kein, ein oder mehrere Children (Kinder) haben. Der Objekt-Tree eines Programms im 'klassischen' BASIC-Modus sieht wie folgt aus (vergleiche UI-Code im Anschnitt 1.1):
Die gelb hinterlegten Objekte werden dabei vom Primary-Objekt automatisch angelegt und erscheinen daher nicht im UI-Code. Das Parent des Primary-Objekts ist das Application-Objekt, seine Children sind das FileMenu und das Bitmap-Objekt. Aus der Sicht des FileMenu ist sein Parent-Objekt das Primary, die Children des FileMenu sind zwei Groups (Gruppen), die jeweils den BreakButton bzw. den ExitButton enthalten. Das DemoBitmap-Objekt ist kein direkter Teil des Trees, es ist das Content-Objekt des DemoView-Objekts (siehe Kapitel 4.9). Der Objekttree eines Programms dient sowohl der Kommunikation der Objekte untereinander (was in R-BASIC meist intern stattfindet) als auch der Anordnung der Objekte auf dem Bildschirm. Children zeichnen sich immer in den Grenzen, die ihnen das Parent vorgibt. Außerdem legt das Parent-Objekt fest, ob die Children neben- oder untereinander angeordnet werden und wie sie sich den vorhandenen Platz aufteilen. Details dazu finden Sie im Kapitel über das Geometriemanagement. R-BASIC unterstützt die Arbeit mit Objekt-Trees sehr ausführlich. Sie können Informationen über das Parent und die Children eines Objekts erhalten, Objekte aus dem Tree entfernen und an anderer Stelle einfügen.
GenericClass Tree und VisualClass TreeIn R-BASIC Programmen gibt es zwei Arten von Objekt-Trees: den GenericClass Tree und den VisualClass Tree. Gelegentlich wird auch der allgemeine Term 'UI-Tree' verwendet. Welcher Tree gemeint sein kann, ergibt sich dann aus dem Kontext. Der GenericClass Tree (kurz: generic Tree) enthält die 'normalen' GEOS-Objekte, wie Primary, Listen, Text-Objekte aber auch z.B. Dialogboxen. Sie stammen alle von der GenericClass ab. GenericClass-Objekte können nur auf dem Bildschirm erscheinen, wenn von ihnen ein vollständiger Pfad zum Application-Objekt führt. Das bedeutet, dass das Objekt selbst, sein Parent, dessen Parent oder ein anderes 'übergeordnetes' (Parent-) Objekt letztlich mit dem Application-Objekt verbunden ist. Mit Objekten oder Objekt Trees, die nicht vollständig in den Tree eingebunden sind, kann man trotzdem arbeiten, d.h. man kann Instance-Variablen lesen und schreiben. Die veränderten Werte werden wirksam, sobald das Objekt vollständig in den Tree eingebunden ist und auf dem Bildschirm erscheint. Der VisualClass Tree (kurz: visual Tree) enthält Objekte, von der VisualClass abstammen. Das Top-Objekt (oberstes Parent) ist ein VisContent oder BitmapConten-Objekt. Der Tree erschient auf den Bildschirm, sobald das Top-Objekt einem View-Objekt als 'content' (=Inhalt) zugewiesen wird. Das View managed dann wie der visual Tree dargestellt wird. Details dazu finden Sie im Abschnitt über View- und Content-Objekte (Kapitel 4.9) sowie im Kapitel über die VisualClass (Kapitel 5). In vielen Fällen besteht der 'VisualClass Tree' ausschließlich aus dem VisContent bzw. BitmapContent-Objekt. Einfache BASIC-Programme haben oft gar keinen VisualClass Tree. Komplexe Programme können mehrere Visual Trees haben und machen ggf. ausführlich von der Möglichkeit, Objekte anzulegen, wieder zu vernichten und im Tree zu verschieben, gebrauch. Achtung! Es ist illegal, den GenericClass Tree und den VisualClass Tree zu mischen, d.h. in den GenericClass Tree Objekte einzufügen, die von der VisualClass abstammen und umgekehrt. Die Verbindung passiert ausschließlich über die 'Content' Instance-Variable eines View-Objekts.
2.1.2 Arbeit mit ObjektenDie hier vorgestellten Möglichkeiten sind sowohl auf den GenericClass Tree als auch auf den VisualClass Tree anwendbar.
Instance-Variablen:
Methoden
Routinen
Class$Class$ enthält den Namen der Objektklasse im Klartext, z.B. 'MEMO', oder 'DYNMAIC_LIST'. Class$ kann nur gelesen werden. Ist das Objekt kein gültiges BASIC-Objekt, z.B. ein Null-Objekt, liefert Class$ einen leeren String.Syntax Lesen: <stringVar> = <obj>.Class$ ChildrenChildren legt im UI-Code fest, dass die aufgezählten Objekte Children des aktuellen Objekts sind. Syntax im UI-Code: Children = <objektListe> Beispiel: | |||||||||||||||||||||||
Primary MyPrimary Children = InfoMenu, MainGroup, BitmapArea END Object | |||||||||||||||||||||||
|
Die hinter Children auftauchenden Objekte müssen an anderer Stelle im UI-Code vereinbart sein. Jedes Objekt darf nur in maximal einer Children-Liste auftauchen. Ein Objekt nirgends als Child zu spezifizieren ist ok. Die Anzahl der Objekte in einer einzigen Childrenliste ist auf 25 begrenzt. Wenn Sie mehr Children spezifizieren wollen können Sie mehrere Childrenanweisungen für ein Objekt verwenden. Beispiel: | |||||||||||||||||||||||
Group MyBigGroup Children = Button1, Group1 Children = Button2, Group2 END Object | |||||||||||||||||||||||
|
Beachten Sie, dass der Compiler die Children-Anweisungen nicht sofort ausführt, sondern sie zunächst auf eine Stapelspeicher (Stack) legt um sie am Ende des UI Compilevorgangs in umgekehrter Reihenfolge auszuführen. Die beiden Children-Anweisungen im obigen Beispiel sind also identisch mit: | |||||||||||||||||||||||
Group MyBigGroup Children = Button2, Group2, Button1, Group1 END Object | |||||||||||||||||||||||
Im BASIC-Code kann lesend auf die Child-Objekte eines Objekts zugegriffen verwenden:
Syntax Lesen: <objVar> = <obj>.Children ( index )
index gibt die Nummer des Child-Objekts an
Wertebereich 0 .. numChildern - 1
Beispiel Basic-Code: | |||||||||||||||||||||||
DIM obj, obj2 AS OBJECT obj = MyPrimay.Children(0) ! erstes Child-Objekt lesen Print obj.Caption$ | |||||||||||||||||||||||
numChildrenNumChildren kann nur im BASIC-Code auftreten und kann nur gelesen werden. Es liefert die Anzahl der direkten Children des Objekts. Sollten die Child-Objekte eigenen Children haben, werden diese nicht mitgezählt. Syntax Lesen: <numVar> = <obj>.numChildren Beispiel: | |||||||||||||||||||||||
DIM n AS WORD n = MyPrimary.numChildren Print "MyPrimary hat";n;"Children" | |||||||||||||||||||||||
parentParent kann nur im BASIC-Code auftreten. Es kann gelesen und geschrieben werden. Im UI-Code können sie das Parent nicht direkt setzen, sondern müssen über die Children-Liste gehen. Lesen: Parent liefert das Parent-Objekt. Sollte das Objekt kein Parent haben, wird ein Null-Objekt zurückgegeben (analog der NullObj() Funktion). Syntax Lesen: <objVar> = <obj>.parent Beispiel: | |||||||||||||||||||||||
DIM obj AS OBJECT
obj = MyView.parent
IF obj = NullObj() THEN
Print "MyView hat kein Parent"
ELSE
Print "'Caption$ = "; obj.Caption$
END IF
| |||||||||||||||||||||||
Schreiben: Parent weist einem Objekt ein neues Parent-Objekt zu. Damit wird das Objekt im UI-Tree verschoben. R-BASIC handelt alle dafür notwendigen Schritte. Sie können auch ein Null-Parent zuweisen (mit der Funktion NullObj() ). Das Objekt wird versteckt, ist aber bereit an gleicher oder anderer Stelle wieder eingefügt zu werden.
Syntax Schreiben: <obj>.parent = <obj2> , index
index: Position (= neue ChildNr, beginnend bei Null),
an der das Objekt eingefügt werden soll.
0: als erstes Child, 1: als 2. Child usw.
Sonderfall: -1 als letztes Child
Beispiel: Ausgangssituation im UI-Code | |||||||||||||||||||||||
Group MyGroup1 Children = MyButton1, MyButton2, MyButton3, MyButton4 END Object Group MyGroup2 Children = MyButton5 END Object | |||||||||||||||||||||||
|
Beispiele BASIC-Code: | |||||||||||||||||||||||
! Button5 nach Group1 verschieben, als erstes Child
MyButton5.Parent = MyGroup1, 0
! Button5 nach Group1 verschieben, als vorletztes Child
! Die Reihenfolge ist dann
! MyButton1, MyButton2, MyButton3, MyButton5, MyButton4
MyButton5.Parent = MyGroup1, 3
! Button5 aus dem Tree entfernen
MyButton5.Parent = NullObj() , 0
! Button5 wieder zu Grpup2 hinzufügen, als letztes Child
MyButton5.Parent = MyGroup2, -1
| |||||||||||||||||||||||
Beachten Sie, dass sich die Child-Nummern der Objekte, die sich hinter dem eingefügten Objekt befinden, verändern.
FindChildDie Methode FindChild untersucht, ob zwei Objekte im Child-Parent Verhältnis zueinander stehen.
Syntax: <numVar> = <obj>.FindChild( <childObj> )
<obj>: Variable oder Ausdruck vom Typ OBJECT
<childObj>: Variable oder Ausdruck vom Typ OBJECT
Es wird geprüft ob <childObj> ein Child von <obj> ist.
Rückgabewert:
0 .. N <childObj> ist ein Child von <obj>
Der Wert ist die Childnummer, die Zählung beginnt bei Null.
- 1 <childObj> ist kein Child von <obj>
ObjInfo$Die Stringfunktion ObjInfo$ liefert interne Informationen über das Objekt. Sie können die Funktion zur Fehersuche in Objekt-Trees verwenden. Der String könnte z.B. so aussehen: ObjReferenz=18:34, Typ=3 (BUTTON) * [Gen]Die ObjektReferenz identifiziert ein Objekt eindeutig. Die erste Zahl beschreibt den Objektblock, in der sich das Objekt befindet. Der Typ beschreibt die Objekt-Klasse eindeutig. Zusätzlich ist der Klassen-Name noch im Klartext angegeben. Syntax: <stringVar> = ObjInfo$ ( <obj> ) <obj>: Variable oder Ausdruck vom Typ OBJECT ^2.1.3 Verwaltung von ObjektblöckenDiese Kapitel richtet sich an fortgeschrittene Programmierer. R-BASIC ist daraufhin optimiert, die Verwaltung der Objektblöcke weitgehend automatisch zu erledigen. Dieses Kapitel enthält grundlegende und Hintergrundinformationen für den Fall, dass Sie ein Problem mit der Objektblockgröße haben (Kapitel 2.1.4) oder dass Sie Objekte zur Laufzeit des Programms anlegen wollen (Kapitel 2.1.5).
BASIC-Anweisungen
GEOS und damit R-BASIC verwaltet den Speicher in 'Blöcken' von einigen Kilobytes Größe. Das gilt auch für Objekte. Die Instance-Daten (persönliche Daten) eines Objekts nehmen einige 10 bis einige 100 Byte ein. Es werden daher immer mehrere Objekte gemeinsam in einem Speicherblock abgelegt. Einen solchen Speicherblock nennt man 'Objektblock'. Jedes Mal, wenn auf die Instance-Daten eines Objekts zugegriffen werden muss, z.B. weil das Objekt sich auf dem Schirm darstellt oder weil Sie es angeklickt haben und es auf den Mausklick reagiert, wird der gesamte Objektblock in den Hauptspeicher geladen. Die Aufteilung der Objekte auf Objektblöcke ist prinzipiell völlig unabhängig von der Verbindung der Objekte im generic Tree oder im visual Tree. Auf modernen Rechnern ist der geringe Performanceverlust, der auftritt, wenn man Objekte 'Kreuz und Quer' über viele Objektblocks verlinkt, zu vernachlässigen. Trotzdem ist es schon aus Gründen der Übersichtlichkeit ratsam, zusammengehörende Objekte, z.B. alle Objekte einer Dialogbox, im UI-Code zusammenhängend zu deklarieren. R-BASIC platziert sie dann automatisch im gleichen Objektblock.
GetObjBlockHandle
Syntax: <handleVar> = GetObjBlockHandle( <obj> )
<obj>: Variable oder Ausdruck vom Typ OBJECT
<handleVar>: Variable vom Typ HANDLE
Um unter R-BASIC mit Objektblöcken arbeiten zu können, benötigen Sie ein Handle auf den Objektblock. Die Funktion GetObjBlockHandle() liefert das Handle des Objektblocks, in dem sich das übergebene Objekt befindet.
GetObjBlockSize
Syntax: <numVar> = GetObjBlockSize( <han> )
<han>: Variable oder Ausdruck vom Typ HANDLE
Es muss das Handle eines Objektblocks sein.
Die Funktion GetObjBlockSize() liefert die aktuelle Größe des Objektblocks, dessen Handle der Funktion übergeben wurde. Der GEOS Speichermanager ist auf Blockgrößen von 6 kByte bis 8 kByte optimiert. Natürlich kann er auch mit Blöcken von wenigen Bytes umgehen, z.B. mit Objektblöcken, die nur ein einziges Objekt enthalten - das ist jedoch nicht effizient und kostet unnötig Systemhandles (jeder Block benötigt sein eigenes Handle). Werden die Blöcke hingegen zu groß kann es länger dauern bis der Speichermanager einen Platz im Hauptspeicher für diesen Block gefunden hat. Unter Umständen muss er dazu andere Blöcke, die gerade nicht benutzt werden auf die Festplatte auslagern. Das kann dauern. Blockgrößen von 10 oder 16 Kilobytes sind dabei noch kein echtes Problem, bei Blockgrößen von z.B. 40 kByte oder mehr kann es jedoch zu den gefürchteten 'Hauptspeicher voll' Meldungen kommen. Um diesbezügliche Probleme zu vermeiden geht R-BASIC beim Compilieren des UI-Codes folgendermaßen vor: Vor dem Anlegen eines neuen Objekts prüft es die Größe des aktuell verwendeten Objektblocks. Sollte dieser bereits mehr als 6 kByte groß sein, so wird vor dem Anlegen des neuen Objekts ein weiterer Objektblock angelegt. Das neue und alle folgenden Objekte werden dann in dem neuen Objektblock gespeichert. Dabei berücksichtigt R-BASIC, dass einige Objekte zur Laufzeit weiteren Speicher benötigen oder benötigen könnten. Beispielsweise speichern drei der vier Text-Objekte (Memo, InputLine und VisText) ihren Text in ihrem eigenen Objektblock. Die Instance-Variable maxLen gibt an, wie viele Zeichen der Text maximal enthalten kann. R-BASIC berücksichtigt das bei der Berechnung der Objektblockgröße. Deswegen sind Objektblocks, die Text-Objekte enthalten, anfangs häufig kleiner als 6 kByte. Ähnliches gilt für DynamicList-Objekte. Diese erzeugen zur Laufzeit ihre eigenen Children. R-BASIC berücksichtigt das pauschal mit 1,5 kByte, was in den meisten Fällen völlig ausreicht.
CreateObjBlockSyntax: <handleVar> = CreateObjBlock ( ) Die Funktion CreateObjBlock( ) legt einen neuen, leeren Objektblock an. Sie liefert das Handle des Objektblocks zurück. Dieses benötigen Sie, wenn Sie neue Objekte in diesem Block anlegen wollen (CreateObject(), siehe Kapitel 2.1.5) oder den Objektblock später wieder vernichten wollen.
DestroyObjBlock
Syntax: DestroyObjBlock <han>
<han>: Variable oder Ausdruck vom Typ HANDLE
Es muss das Handle eines Objektblocks sein.
Die Anweisung DestroyObjBlock vernichtet einen Objektblock und gibt den damit verbundenen Speicher wieder frei. Wichtig:
^2.1.4 Beeinflussung der Objektblöcke im UI-CodeDiese Kapitel richtet sich an fortgeschrittene Programmierer. R-BASIC kümmert sich um Objektblöcke und die damit zusammenhängenden Dinge weitgehend selbständig. Die meisten Programmierer werden daher niemals selbst mit der Verwaltung von Objektblöcken zu tun haben. Es gibt jedoch einige wenige Situationen die das direkte Eingreifen des Programmierers erfordern. Das sind konkret:
UI-Anweisungen
Nach dem Compilieren erhalten Sie eine Tabelle, die wie folgt aussehen könnte. Die Spalte 'Ab Zeile' enthält die Zeile im UI-Code, in der ein neuer Objektblock angelegt wurde. Daraus können Sie ermitteln welche Objekte in welchem Objektblock gespeichert sind. 'Größe' enthält die anfängliche Größe des Objektblocks in Byte. 'Objekte' enthält die Anzahl der im Objektblock gespeicherten Objekte. Beachten Sie, dass das Application-Objekt in einen eigenen Objektblock compiliert wird. | |||||||||||||||||||||||
Objektblöcke compiliert: 3 Ab Zeile Größe Objekte 36 4280 33 196 1592 5 Interner Objektblock: Application | |||||||||||||||||||||||
|
Wie bereits oben erwähnt brauchen Sie hier im Normalfall nicht einzugreifen, insbesondere dann nicht, wenn Ihnen die Blockgrößen sehr klein erscheinen. R-BASIC wählt einen guten Kompromiss auf anfänglicher Blockgröße und dem möglichen Blockwachstum zur Laufzeit. Ein nachträgliches Verschieben eines Objekts in einen anderen Block ist leider nicht möglich. Es gibt jedoch einige Situationen, die R-BASIC nicht vorhersehen kann. Diese sind im Folgenden erklärt. Sie beziehen sich alle auf Veränderungen der Objekte zur Laufzeit. Als Richtwert kann gelten, dass Objektblöcke zur Laufzeit nicht größer als 14 bis 16 kByte werden sollten. Optimal sind weniger al 10 kByte. Wie Sie das herausbekommen ist weiter unten erklärt. Bei mehr als 20 kByte Blockgröße ist es dringend zu empfehlen gegenzusteuern.
Fall 1: DynamicList ObjekteEin häufiger Fall, in dem die Blockgröße kritisch anwachsen kann, sind dynamische Listen, die grafische Elemente anzeigen. Dynamische Listen erzeugen Ihre Children zur Laufzeit selbst. Dafür wird Platz im Objektblock benötigt. Es zählen dabei nur die gleichzeitig sichtbaren Listeneinträge. R-BASIC unterstellt der Liste bei der Berechnung der Objektblockgröße einen Platzbedarf von 2 kByte, das entspricht ca. 25 gleichzeitig angezeigten Listeneinträgen mit je 20 Zeichen Text-Caption. Aber auch ein realer Bedarf von 4 oder 6 kByte sind kein Problem - falls man nicht mehrere solcher Listen im gleichen Objektblock hat. Ein echtes Problem können aber viele Listeneinträge mit einer Grafik sein (Anweisung ItemGString). In diesem Fall ist es eine gute Idee das DynamicList-Objekt ein einem eigenen Objektblock, nur für dieses Objekt, unterzubringen. Dazu verwenden Sie die unten beschriebene Anweisung ForceNewObjBlock.
Fall 2: Grafische CaptionsAuch die 'Objekt-Beschriftung' (Caption$ oder grafische Captions) wird im gleichen Objektblock gespeichert wie das Objekt selbst. Text-Captions (Caption$) stellen dabei niemals ein Problem dar, da sie nur wenige Bytes umfassen. Wenn sie einen Text durch einen anderen ersetzen ändert sich die Objektblockgröße nur um wenige Bytes, ggf. wird sie sogar kleiner. Haben Sie jedoch im UI-Code eine Text-Caption (oder gar keine) angegeben und weisen einem Objekt zur Laufzeit eine Grafik als Caption zu (Anweisungen CaptionIcon, CaptionPicture, CaptionImage und CaptionGString), so wird auch diese im Objektblock des Objekts gespeichert. Wenn Sie dies bei mehreren Objekten tun kann das den Objektblock zu stark vergrößern. Beispielsweise nimmt ein Icon der Bitmap-Größe 48x30 Pixel im ungünstigsten Fall (TrueColor, unkomprimiert) ca. 4 kByte ein, bei 8 Bit unkomprimiert sind es immer noch 1,4 kByte. Weitere Informationen dazu finden Sie im Kapitel 3.1 (Caption: Die Objekt-Beschriftung). Auch hier gilt: Weisen Sie die Grafik bereits im UI-Code zu, erkennt R-BASIC die Größe und verteilt die fraglichen Objekte auf verschiede Objektblöcke.
Fall 3: TextobjekteDer hier beschriebene Fall ist kommt eher selten vor, aber man sollte ihn kennen. Wie bereits oben erwähnt speichern Textobjekte (außer LargeText) ihren Text in ihrem eigenen Objektblock. Wie groß dieser Text werden kann hängt von der Instance-Variablen maxLen des Textobjektes ab. Der Standardwert für maxLen ist 1024. Wenn Sie zur Laufzeit den Wert für maxLen deutlich vergrößern (gegenüber dem Wert, der beim Compilieren festgelegt wurde) und das auch ausnutzen (d.h. so viel Text dort speichern) wird der Objektblock größer als vom Compiler angenommen. Machen Sie das für viele Textobjekte aus dem gleichen Block kann es zu einem Problem werden. Es macht daher Sinn bei Textobjekten den Wert für maxLen im UI-Code so klein wie möglich, aber auch so groß wie nötig zu wählen. Dann löst R-BASIC das Problem für Sie, indem es die Objekte auf mehrere Blöcke verteilt.
Eine Verkleinerung des Wertes für maxLen zur Laufzeit stellt dagegen niemals ein Problem dar.
Wie erkennt man, ob es ein Problem gibt?Um Informationen über einen Objektblock zu erhalten muss man zuerst das 'Handle' des Blocks ermitteln. Die Funktion GetObjBlockHandle() liefert das Handle des Objektblocks, in dem sich das übergebene Objekt befindet. Danach kann man mit der Funktion GetObjBlockSize() die aktuell gültige Größe des Objektblocks ermitteln.Wenn Sie den Verdacht haben, dass ein Objektblock zu groß geworden ist, rufen Sie diese beiden Routinen für ein Objekt aus diesem Block, wie im folgenden Beispiel gezeigt: | |||||||||||||||||||||||
DIM han AS HANDLE DIM size han = GetObjBlockHandle(MyDanamicList) size = GetObjBlockSize (han) MsgBox Str$(size) | |||||||||||||||||||||||
|
Dabei ist es normal, wenn die Größe eines Objektblocks zur Laufzeit etwas größer ist, als in der Tabelle vom Compiler angegeben. GEOS arbeitet mit den Objektblocks. Z.B. fügt es bei einigen Objekten je nach Bedarf eigene (interne) Instance-Werte hinzu oder löscht diese wieder. Beim Löschen wird der Speicher zwar als 'frei' markiert, der Block aber nicht unbedingt sofort verkleinert. Daher ist es auch normal, wenn die Größe vom Mal zu unterschiedlich ist, auch wenn Sie 'gar nichts gemacht' haben. Sie können jedoch gut erkennen, ob der Objektblock eine kritische Größe (mehr als 16 bis 20 kByte) erreicht hat oder nicht.
Was kann man tun?Der einzige Weg, Einfluss auf die Verteilung der Objekte auf die Objektblöcke zu nehmen, ist, dem UI-Compiler anzuweisen, einen neuen Objektblock anzulegen.ForceNewObjBlockSyntax im UI-Code: ForceNewObjBlock Platzieren Sie den UI-Befehl ForceNewObjBlock (Erzwinge neuen Objektblock) je nach Situation vor oder nach dem kritischen Objekt. Es ist auch möglich die fraglichen Objekte (oder das einzelne Objekt) in zwei ForceNewObjBlock-Anweisungen einzuschachteln. | |||||||||||||||||||||||
ForceNewObjBlock DynamicList MyBigList .... END Object ForceNewObjBlock | |||||||||||||||||||||||
|
Findet der UI-Compiler eine ForceNewObjBlock-Anweisung schließt er den aktuell verwendeten Objektblock und legt für die folgenden Objekt einen neuen an.
Tipp: Legen Sie die fraglichen Objekte ans Ende aller UI-Anweisungen, dann werden die davor befindlichen Objektblöcke nicht unnötig eingekürzt.
2.1.5 Anlegen und Vernichten von Objekten zur LaufzeitDiese Kapitel richtet sich an fortgeschrittene Programmierer. Üblicher Weise legt R-BASIC die im UI-Code deklarierten Objekte an, wenn das Programm compiliert wird. R-BASIC bietet Ihnen aber auch die Möglichkeit, weitere Objekte zur Laufzeit anzulegen und wieder zu vernichten. Für GenericClass Objekte (z.B. Button oder Menu) wird diese Möglichkeit eher selten genutzt. Einige komplexe Programme, wie z.B. der Grafikbetrachter Gonzo, nutzen aber die gebotenen Möglichkeiten für VisualClass Objekte sehr intensiv. Gonzo legt für jede Grafikdatei, die es findet, ein eigenes Objekt an. Dieses Kapitel beschreibt, wie man Objekte zur Laufzeit anlegt, damit arbeitet, wieder vernichtet und was es dabei zu beachten gilt. Beachten Sie, dass die VisContent Objekte über eingebaute Methoden verfügen, die das Anlegen und Vernichten von VisObj-Objekten stark vereinfachen.
BASIC-Anweisungen
Die Befehle CreateObjBlock() und DestroyObjBlock sind im Kapitel 2.1.3 beschrieben.
CreateObject
Syntax: <objVar> = CreateObject (<han>, <objClass>)
<han>: Handle eines Objektblocks
<objClass>: Bezeichnung einer Objektklasse
Die Funktion CreateObject() legt ein neues Objekt in dem Objektblock an, dessen Handle der Funktion übergeben wurde. Als Objektklasse (dem 'Typ' des Objekts) sind alle R-BASIC Klassen, außer Application, zulässig. Beispiele: | |||||||||||||||||||||||
DIM o, p, q AS OBJECT
o = CreateObject (han, Button)
p = CreateObject (han, Dialog)
q = CreateObject (han, Menu)
| |||||||||||||||||||||||
|
Um das Objekt nutzen zu können müssen Sie noch seine Instance-Variablen initialisieren und das Objekt in den Tree einbinden.
Ausführliches Beispiel: siehe unten Hinweise:
DestroyObject
Syntax: DestroyObject <obj>
<obj>: Variable oder Ausdruck vom Typ OBJECT
Das Objekt wird vernichtet.
Die Anweisung DestroyObject vernichtet ein Objekt. Damit ein Objekt vernichtet werden kann darf es nicht mehr im Tree eingebunden oder auf andere Weise mit anderen Objekten verbunden sein. R-BASIC erzeugt einen Laufzeitfehler, wenn diese Bedingungen verletzt sind, um einen Absturz des Systems zu verhindern. Hinweis:
Beispiel: Anlegen eines Objekt-Trees | |||||||||||||||||||||||
DIM h as HANDLE DIM d, t, b as OBJECT h = CreateObjBlock() d = CreateObject(h, Dialog) d.Caption$ = "Neuer Dialog" d.Parent = DemoPrimary,1 t = CreateObject (h, Memo) t.Caption$ = "Text eingeben" t.justifyCaption = J_TOP t.Parent = d, 0 b = CreateObject(h, button) b.Caption$ = "Fertig" b.ActionHandler = TestAction b.Parent = d,1 | |||||||||||||||||||||||
|
Beispiel: Vernichten eines Objekt-Trees | |||||||||||||||||||||||
BUTTONACTION TestAction
Print "Button pressed!"
Print t.text$
b.Parent = NullObj(), 0
DestroyObject b
t.Parent = NullObj(), 0
DestroyObject t
d.Parent = NullObj(), 0
DestroyObject d
DestroyObjBlock h
END ACTION
| |||||||||||||||||||||||
^ |