4.18 Display und zugehörige Objekte
4.18.1 ÜberblickJede große Applikation (z.B. Write, R-BASIC) zeigt ihre Dokumente in eigenen Fenstern an. Diese Fenster gehören der Objektklasse Display an. Displayobjekte enthalten ähnlich wie Dialoge weitere UI-Objekte, z.B. Views, Memos, Buttons oder Listen. Der Bereich, in dem die Displays dargestellt werden, ist ein Objekt der Klasse DisplayGroup. Die DisplayGroup managet die Displays, organisiert z.B. dass sie überlappend dargestellt werden oder sich den Platz aufteilen. Dabei hat die DisplayGroup selbst keine UI, mit der der Nutzer interagieren kann. Das übernimmt ein Objekt der Klasse DisplayControl, das sich üblicher Weise im "Fenster" Menü befindet. Der Vorteil von dieser Trennung ist, dass man mehrere DisplayGroups haben kann, die alle über das Fenster-Menü gesteuert werden.
Displays, DisplayGroup und DisplayControl arbeiten im Hintergrund eng zusammen. Im Kern ist es so, dass die DisplayGroup weiß, welche Displays (Fenster) es gibt, da sie die Children der DisplayGroup sind. Sie sendet eine Message an das DisplayControl, das daraufhin eine Liste der vorhandenen Fenster aufbaut. Wählt der Nutzer aus dieser Liste ein Display aus so sendet das DisplayControl eine Message an die DisplayGroup. Diese wiederum wählt das geforderte Display aus. Genauso verhält es sich, wenn der Nutzer den Eintrag "Überlappend", "Bildschirmfüllend" oder "Aufteilen" auswählt. Die DisplayGroup bekommt den Befehl vom DisplayControl und organisiert die Anzeige entsprechend. Im Gegenzug bekommt das DisplayControl eine Message, wenn der Nutzer z.B. auf ein bestimmtes Display klickt und es so zum aktiven Fenster macht. All das passiert ohne weiteres Zutun des Programmierers.
Das System organisiert diese Zusammenarbeit intern über die Target-Hierarchie. Das stellt auch sicher, dass die Zusammenarbeit mit mehreren DisplayGroups funktioniert. Hintergrundinformationen zur Target-Hierarchie finden Sie im Handbuch Spezielle Themen, Vol. 2, Kapitel 12. Für die Verwendung von Display, DisplayGroup und DisplayControl müssen Sie in diesem Zusammenhang folgendes wissen:
^4.18.2 DisplayAbstammung:
Das Displayobjekt erbt alle Eigenschaften und Fähigkeiten der GenericClass. Von besonderer Bedeutung sind dabei die Fähigkeiten zum Geometriemanagement, insbesondere die Window-bezogenen Hints (Kapitel 3.3.7: Spezielle Hints für Window-Objekte) sind hier von Bedeutung. Beachten Sie, dass insbesondere die Größe eines Displayobjekts im Zusammenspiel mit der DisplayGroup geändert werden kann. Es ist deshalb leicht möglich, dass Sie widersprüchliche Hints setzen. So verhindert z.B. der Hint "NotMaximizable", dass sich das Display bildschirmfüllend darstellt. Displays können in drei Modi dargestellt werden:
Spezielle Instance-Variablen:
Methoden:
Action-Handler-Typen:
Ein einfaches Displayobjekt, dass ein Memo als Child enthält, sieht so aus: | |||||||||||||||||||||||||||||||||||||||||
Display Disp1 Caption$ = "Erlkönig"' , 0 Children = Memo1 End OBJECT Memo Memo1 text$ = "Wer reitet so spät durch Nacht und Wind?" ExpandWidth:ExpandHeight backColor = WHITE End Object | |||||||||||||||||||||||||||||||||||||||||
Minimized und Maximized StateDie folgenden Instancevariablen bestimmen ob das Displayobjekt minimiert (versteckt), maximiert (bildschirmfüllend) oder überlappend dargestellt wird.Hinweis: Da Primary-Objekte von Displays abstammen erben Sie die im Folgenden aufgelisteten Fähigkeiten.
minimizedStateMinimizedState enthält die Information ob das Displayobjekt "minimiert" ist oder nicht.
Syntax UI-Code: minimizedState = TRUE
Der Defaultwert ist FALSE.
Schreiben: <obj>.minimizedState = <Wert>
Lesen: <numVar> = <obj>.minimizedState
MinimizedOnStartupMinimizedOnStartup bewirkt, dass das Displayobjekt am Programmstart minimiert ist.Syntax UI-Code: MinimizedOnStartup NotMinimizableNotMinimizable bewirkt, dass das Displayobjekt nicht minimiert werden kann. Der entsprechende Button in der Titelbar des Displayobjekts wird entfernt und das Setzen der Instancevariablen minimizedState bleibt wirkungslos.Syntax UI-Code: NotMinimizable maximizedStateMaximizedState enthält die Information, ob das Displayobjekt "bildschirmfüllend" (maximizedState = TRUE) dargestellt wird oder nicht.
Syntax UI-Code: maximizedState = TRUE
Der Defaultwert ist FALSE.
Schreiben: <obj>.maximizedState = <Wert>
Lesen: <numVar> = <obj>.maximizedState
MaximizedOnStartupMaximizedOnStartup bewirkt, dass das Displayobjekt am Programstart maximiert dargestellt wird.
Syntax UI-Code: MaximizedOnStartup NotMaximizableNotMaximizable bewirkt, dass der Nutzer das Displayobjekt nicht maximieren kann. Das Display bleibt im "überlappenden" Modus, auch wenn die anderen Displays bildschirmfüllend sind.Syntax UI-Code: NotMaximizable Weitere HintsNotResizableNotResizable bewirkt, dass der Nutzer die Größe des Displayobjekts nicht ändern kann, wenn es im Modus "überlappend" dargestellt wird.Syntax UI-Code: NotResizable NotRestorableNotRestorable bewirkt, dass ein Wechsel in den "minimiert" Modus nicht zurückgenommen werden kann. Verwenden Sie diesen Hint mit Vorsicht.Syntax UI-Code: NotRestorable Schließen von DisplaysGroße Applikationen wie GeoWrite oder R-BASIC stellen Ihre Dokumente in Fenstern dar, die Display-Objekte sind. Wird ein Dokument geschlossen so muss auch das zugehörige Display-Objekt vom Schirm genommen werden. Falls das Display beim Öffnen des Dokuments, also zur Laufzeit, mit der Routine CreateObject erzeugt wurde muss es dann auch wieder mit der Routine DestroyObject wieder vernichtet werden. Bitte lesen Sie die Dokumentation dieser Routinen sorgfältig.Werden die Fenster (Display-Objekte) überlappend dargestellt so findet sich im Systemmenü des Displays der Eintrag "Schließen". Er ist per Default inaktiv. Um ihn zu aktivieren müssen Sie die Instancevariable userDismissable des Display-Objekts auf TRUE setzen. Klickt der Nutzer jetzt auf diesen Eintrag wird der OnClose Handler des Displayobjekts aufgerufen. Dieser Handler muss alle notwendigen Schritte auslösen um das Dokument zu schließen und das Display-Objekt vom Schirm zu nehmen. Ist kein OnClose Handler gesetzt so passiert nichts. Hinweis: Primary-Objekte stammen von Displays ab. Sie implementieren jedoch ihr eigenes Handling zum Schließen eines Programms. Die folgenden Instancevariablen sind für Primaries daher nicht verfügbar.
userDismissableUserDismissable = TRUE aktiviert den Eintrag "Schließen" im Systemmenü des Displayobjekts. Der Defaultwert ist FALSE. Das Systemmenü ist nur sichtbar, wenn die Displays überlappend dargestellt sind.Wenn der Nutzer auf "Schließen" im Systemmenü des Displayobjekts klickt wird der OnClose Handler des Objekts aufgerufen.
Syntax UI-Code: userDismissable = TRUE
Der Defaultwert ist FALSE.
Schreiben: <obj>.userDismissable = <Wert>
Lesen: <numVar> = <obj>.userDismissable
OnCloseDer OnClose Handler wird gerufen, wenn der Nutzer auf den Eintrag "Schließen" im Systemmenü des Displayobjekts klickt. Das Systemmenü ist nur sichtbar, wenn die Displays überlappend dargestellt sind. Um den Eintrag "Schließen" im Systemmenü des Displayobjekts zu aktivieren müssen Sie die Instancevariable userDismissable des Displayobjekts auf TRUE setzen.Der OnClose Handler muss als DialogAction deklariert sein.
Syntax UI-Code: OnClose = <Handler>
Schreiben: <obj>.OnClose = <Handler>
Lesen: --
CloseDie Methode Close ruft den OnClose Handler des Objekts auf. Dieser Handler muss dann alle weiteren Schritte auslösen. Ist kein OnClose Handler definiert so passiert auch nichts.Syntax BASIC Code: <obj>.Close ^4.18.3 DisplayGroupDas DisplayGroup Objekt interagiert mit den Displays um sie anzuordnen, ihre Größe festzulegen usw.
Per Default ist eine DisplayGroup so eingestellt, dass die Displays am Programmstart im bildschirmfüllenden Modus angezeigt werden. Wenn Sie das nicht möchten setzen Sie im UI-Code die Instancevariable fullSizeState auf FALSE. Um die Displays am Programmstart "aufgeteilt" darzustellen müssen Sie in Ihrem OnStartup Handler die Methode "TileDisplays" für das DisplayGroup Objekt aufrufen. Spezielle Instance-Variablen:
Methoden:
Eine typische Konfiguration einer DisplayGroup sieht so aus: | |||||||||||||||||||||||||||||||||||||||||
DisplayGroup DGroup children = Disp1, Disp2, Disp3 initialSize = 800, 400 defaultTarget fullSizeState = FALSE ExpandWidth ExpandHeight SizeIndependentlyOfDisplays End OBJECT | |||||||||||||||||||||||||||||||||||||||||
FullSizeStateDie Instancevariable fullSizeState enthält die Information, ob die Displays in der DisplayGroup überlappend (fullSizeState = FALSE) oder bildschirmfüllend (fullSizeState = TRUE) dargestellt werden. Sie können den Wert zur Laufzeit ändern um den entsprechenden Zustand einzustellen.Um die Displays gleichmäßig in der DisplayGroup aufzuteilen verwenden Sie die Methode "TileDisplays" (siehe unten).
Syntax UI- Code: fullSizeState = FALSE
Der Defaultwert ist TRUE
Schreiben: <obj>.fullSizeState = TRUE | FALSE
Lesen: <numVar> = <obj>.fullSizeState
activeDisplayDie Instancevariable activeDisplay enthält das aktuell aktive Displayobjekt. Ist kein Displayobjekt "aktiv" enthält activeDisplay das zuletzt aktive Displayobjekt. Sollte die DisplayGroup keine Displays enthalten so liefert activeDisplay ein Null-Objekt.Syntax Lesen: <objVar> = <obj>.activeDisplay NoFullSizeModeNoFullSizeMode verhindert, dass die Displays in der DisplayGroup bildschirmfüllend angezeigt werden. Am Programmstart werden die Displays per Default trotzdem immer bildschirmfüllend angezeigt. Setzen Sie daher im UI-Code zusätzlich die Instancevariable fullSizeState auf FALSE.Syntax UI-Code: NoFullSizeMode NoOverlappingModeNoOverlappingMode verhindert, dass die Displays in der DisplayGroup überlappend angezeigt werden.Syntax UI-Code: NoOverlappingMode TileDisplaysDie Methode TileDisplays ordnet die Displays "aufgeteilt" an. Der Aufruf dieser Methode hat die gleiche Wirkung als ob der Nutzer im DisplayControl den Eintrag "Aufteilen" anklickt.Syntax BASIC Code: <obj>.TileDisplays TileHorizontallyTileHorizontally bewirkt, dass die Displays in der DisplayGroup nebeneinander angeordnet werden, wenn sie "aufgeteilt" werden. Um die Displays aufzuteilen kann der Nutzer im DisplayControl den entsprechenden Eintrag anklicken oder man ruft die Methode "TileDisplays" auf.Syntax UI-Code: TileHorizontally TileVerticallyTileVertically bewirkt, dass die Displays in der DisplayGroup übereinander angeordnet werden, wenn sie "aufgeteilt" werden. Um die Displays aufzuteilen kann der Nutzer im DisplayControl den entsprechenden Eintrag anklicken oder man ruft die Methode "TileDisplays" auf.Syntax UI-Code: TileVertically SizeIndependentlyOfDisplaysSowohl die Anordnung der Displays als auch die Größe der DisplayGroup werden zwischen Displays und DisplayGroup automatisch ausgehandelt. In einigen Situationen kann das dazu führen, dass die DisplayGroup nicht so aussieht, wie Sie sich das wünschen, z.B. dass sie zu klein ist, oder dass die Geometrie der Displays nicht stimmt. Verwenden Sie in diesen Fällen den Hint SizeIndependentlyOfDisplays um die Geometrie der DisplayGroup und die Geometrie der Displays voneinander zu entkoppeln.Tipp: Setzen Sie diesen Hint immer. Nur wenn Sie den Eindruck haben, dass die Geometrie nicht stimmt versuchen Sie es ohne ihn. Syntax UI-Code: SizeIndependentlyOfDisplays SelectDisplaySelectDisplay(n) wählt ein Display als aktives Display aus. Die Zählung beginnt dabei bei Null.Tipp: Um herauszubekommen wie viele Displays zu einem DisplayGroup Objekt gehören fragen Sie die Instancevariable numChildren der DisplayGroup ab.
Syntax BASIC Code: <obj>.SelectDisplay (<Wert>)
<Wert> Nummer des auszuwählenden Displays
Die Zählung beginnt bei Null.
^4.18.4 DisplayControlDas DisplayControl arbeitet automatisch mit den Displays und der DisplayGroup zusammen. Das funktioniert sogar, wenn Sie mehrere DisplayGroup Objekte haben. Der Programmierer muss dazu nichts weiter tun als die Objekte in seinen Tree einbinden. Außerdem muss das DisplayGroup Objekt (falls Sie mehrere haben: genau eines) den Hint defaultTarget gesetzt haben. Abstammung:
Spezielle Instance-Variablen:
dcFeaturesDcFeatures bestimmt, welche Elemente der Controller-UI angezeigt werden. Per Default werden alle Elemente angezeigt.
Syntax UI-Code: dcFeatures = <Wert>
Schreiben: <obj>.dcFeatures = <Wert>
Lesen: <numVar> = <obj>.dcFeatures
Folgende Werte sind für dcFeatures verfügbar:
NameOnPrimaryIfMaximizedDiese Instancevariable bestimmt, ob der Name des aktuell aktiven Displays in der Titelzeile des Primary-Objekts angezeigt werden soll.
Syntax UI-Code: nameOnPrimaryIfMaximized = TRUE
Der Defaultwert ist FALSE.
Schreiben: <obj>.nameOnPrimaryIfMaximized = <Wert>
Lesen: <numVar> = <obj>.nameOnPrimaryIfMaximized
Beispiel. Beachten Sie, dass das DisplayControl keinen Verweis auf die Display-Group enthält. Das wird intern über die Target Hierarchie geregelt. | |||||||||||||||||||||||||||||||||||||||||
Menu WindowMenu Caption$ = "Fenster" , 0 Children = DControl End OBJECT DisplayControl DControl nameOnPrimaryIfMaximized = TRUE End OBJECT | |||||||||||||||||||||||||||||||||||||||||
^ |