Wer es bereits geschafft hat, in den Besitz eines heißbegehrten Falken zu kommen, mußte sich wohl oder übel damit abfinden, auf MultiTOS zu verzichten. Die bisher ausgelieferten Modelle des Falcon030 tragen die TOS-Versionsnummern 4.00 und 4.01 und haben damit, neben den erforderlichen Anpassungen an die neuen Fähigkeiten des Falcon im GEM, nur einige optische Verschönerungen erfahren.
True-Color-Icons, 3D-Buttons und Fenster im 3D-Look sind die auffälligsten Neuerangen, die ATARI am GEM vorgenommen hat. Erst auf den zweiten Blick entdeckt man im DESKTOP ein neues Feature, das zwar in jeder zweiten Anwendung auftaucht, dem Betriebssystem bisher allerdings unbekannt war: in den Dialogboxen des EXTRA-Menüs wurden Pop-Up-Menüs implementiert.
Pop-Up-Menüs sind zwar für das irgendwann kommende MultiTOS bereits dokumentiert, wurden aber im Falcon anscheinend schon jetzt eingebaut. Ein kurzer Test bringt es an den Tag: der Falcon beherrscht vier neue AES-Aufrufe, (wobei er einen netterweise mit einer Alertbox daran hindert, AES-Funktionen aufzurufen, die noch nicht implementiert sind). Es handelt sich um die - eigentlich erst im MultiTOS vorgesehenen - Aufrufe 36 bis 39, MENU_POPUP, MENU_ATTACH, MENU_START und MENU_SETTINGS, mit denen die einfache Verwendung von Pop-Up- und Submenüs möglich ist.
Die genauen Deklarationen entnehmen Sie bitte nebenstehendem Kasten.
Wir wollen uns im ersten Teil zunächst einmal nur mit den Pop-Up-Menüs beschäftigen. Im nächsten Heft werden wir dann daran gehen, Pop-Ups mit Hilfe des MENU_ATTACH-Aufrufes als Submenüs einzusetzen.
Als Pop-Up kann man im Prinzip jedes beliebige GEM-Objekt einsetzen. Es wird vom AES auf den Bildschirm gebracht; man kann dann mit der Maus entweder ein Objekt auswählen oder außerhalb des Pop-Ups klicken, um kein Objekt auszuwählen. Danach wird es wieder gelöscht, und man kann erfragen, ob und was selektiert wurde. Genaugenommen ist jedes Menü, das aus dem Menübaum herunterklappt, wenn man einen Menütitel anwählt, ein Pop-Up. Ein Pop-Up kann völlig unabhängig von anderen Objekten auf dem Desktop oder in einem Fenster oder z.B. als Auswahlbox zu einem "Pop-Up-Button" einer Dialogbox erscheinen.
Das einfachste Pop-Up besteht, wie ein normales Menü, aus einem "Kasten", in dem übereinander mehrere Texteinträge stehen. Der Kasten ist das Vaterobjekt und vom Typ G_BOX, die Einträge sind die Kinder und vom Typ G_STRING. Da dieses Pop-Up wie ein normales Menü aussieht und auch als Submenü eingesetzt werden kann, sollte man sich an die allgemeinen Konventionen halten, d.h. vor jedem Eintrag zwei Leerzeichen für das "Checked-Häkchen" freilassen und am Ende ein Leerzeichen. Bei Bedarf sind Trennstriche in Form von disabled Strings (?-------") zulässig. Solche Pop-Ups - und nur solche - können auf Wunsch vom GEM gescrollt werden und dürfen damit fast beliebig hoch sein.
Das Scrollen geschieht automatisch, wenn das Pop-Up größer als die festgelegte Scroll-Höhe ist, auch die dazu notwendigen Scroll-Pfeile werden vom Betriebssystem automatisch erzeugt. (Die meisten kennen das wahrscheinlich schon vom XCONTROL.ACC).
Wenn man auf automatisches Scrollen verzichtet, sind einem bei der Gestaltung beliebiger Pop-Up-Menüs kaum Grenzen gesetzt. Man muß nur dafür sorgen, daß alle selektierbaren Objekte auf der gleichen Ebene liegen und Kinder eines gemeinsamen Vaterobjekts sind. Man sollte jedoch immer überlegen, ob ein Pop-Up an dieser Stelle überhaupt sinnvoll ist. Das ist immer dann der Fall, wenn in einer Dialogbox aus einer Fülle von Möglichkeiten genau eine ausgewählt werden soll. Aus neueren, sauber programmierten Grafikprogrammen kennen wir Pop-Up-Buttons zum Auswählen von Linientypen, Fonts, Mustern, Farben usw. Und genau in so einem Fall sind Pop-Up-Buttons sinnvoller als normale Menüs, weil man sofort sehen kann, was zur Zeit angewählt ist. Trotz der Fülle der Gestaltungsmöglichkeiten sollte man Pop-Ups so einfach wie möglich halten und auf verwirrende Elemente verzichten. So tauchen z.B. immer wieder Pop-Ups auf, die eine Fenstertitelzeile besitzen; was nur zu Fehlbedienungen führt, weil man Pop-Ups weder verschieben noch in den Hintergrund klicken kann. Das Objekt-Flag hat übrigens bei den Pop-Up-Einträgen keine Bedeutung -die einzelnen Objekte müssen nicht SELECTABLE sein, und es muß auch kein EXIT-Objekt existieren.
Sollen Pop-Up-Menüs in Form von sogenannten Pop-Up-Buttons innerhalb von Dialogboxen auftauchen, sollte man sich an die Konventionen halten, die sich inzwischen weitgehend durchgesetzt haben.
Danach ist der Button selbst ein Objekt vom Typ G_BOXTEXT mit dem Objekt-Flag TOUCHEXIT und dem Objektstatus SHADOWED, damit man sofort erkennt, daß es sich um einen Pop-Up-Button handelt. Um den Pop-Up-Button im neuen Falcon-3D-Look erstrahlen zu lassen, muß man noch zusätzlich den Objektstatus DRAW_3D ($40) und im High-Byte des Objekttyps eine $02 setzen. (Mit diesen beiden Änderungen kann man übrigens auch jeden normalen Button in einen 3D-Button verwandeln.)
Im Gegensatz zum Submenü gibt es noch keine Möglichkeit, eine Verbindung zwischen dem Button und dem Pop-Up herzustellen, um es automatisch aufzurufen. Man muß also die Betätigung des Buttons normal abfragen und dann das Pop-Up selbst aufrufen. Hat man ein Pop-Up erstellt und ins Programm eingebunden, muß man noch eine MENU-Struktur anlegen (siehe Kasten). In diese neue AES-Struktur wird zunächst die Adresse des Pop-Up-Menü-Baumes eingetragen. Dann folgen der Index des Vaterobjekts der Pop-Up-Menü-Einträge (also des "Kastens") und der Index des Anfangsmenüeintrags, also des Eintrags, an dem das Pop-Up auf dem Bildschirm ausgerichtet wird. Zum Schluß kann man noch angeben, ob bei Bedarf gescrollt werden darf.
Wenn man die Größe des Pop-Up-Me-nüs benötigt, dann kann man sie am einfachsten durch FORM_CENTER ermitteln lassen. Bei mir passiert es nur am rechten Bildschirmrand, daß ein Pop-Up nicht ganz auf dem Bildschirm erscheint, an den drei anderen Seiten achtet das Betriebssystem darauf, daß es den Schirm nicht verläßt. Bevor man ein Pop-Up aufruft, muß man den Bildschirm mittels WIND_UPDATE (BEG_UPDATE) sperren - und ihn nach dem Aufruf selbstverständlich wieder mit WIND_UPDATE (END_UPDATE) freigeben. Bei Pop-Ups, die zu Buttons gehören, ermittelt man die x- und y-Koordinate des Pop-Ups, indem man die x- und y-Koordinate des Buttons mit der Funktion OBJC_OFFSET abfragt. Nach dem eigentlichen Aufruf des Pop-Ups mittels MENU_POPUP erhält man in me_return (int_out) eine Null, wenn kein Eintrag ausgewählt wurde (was passiert, wenn der Benutzer außerhalb des Pop-Ups geklickt hat). Ist me_return ungleich Null, erhält man in einer zweiten MENU-Struktur, die man bei MENU_POPUP in me_mdata übergeben hat, den Index des angewählten Eintrags. Wurde beim Anwählen dieses Eintrages eine der Shift-Tasten (dazu zählen auch Alternate und Control) gedrückt, so steht dies im allerletzten Wort der MENU-Struktur in der AES-üblichen Bit-Notation. Übergibt man sowohl in me_menu als auch in me_mdata die gleiche Adresse - also dieselbe Menüstruktur -, erhält man den angewählten Eintrag anstelle des Anfangseintrags zurück; dieses Verfahren sorgt dafür, daß der zuletzt gewählte Eintrag beim nächsten Aufruf wieder der Anfangseintrag ist.
Um alles andere muß man sich jedoch selbst kümmern: Das kann z.B. das Setzen des CHECKED-Status sein, um dem Benutzer mit einem Häkchen anzuzeigen, welches der zuletzt gewählte Eintrag war. Auch das Übertragen des gewählten Eintrags in den Pop-Up-Button muß man selbst erledigen.
Doch nun zur Praxis. Da es für den geneigten C-Programmierer inzwischen eine Fülle von Libraries gibt, mit denen man auf jedem ST/TT/Falcon Pop-Up-und Submenüs auf einfache Weise nachbilden kann, habe ich mich zur Demonstration der neuen AES-Aufrufe für OMIKRON.BASIC entschieden. Erstens kann man neue Betriebssystemfunktionen am besten mit einer Interpreter-Sprache testen, und zweitens läuft die Version 3.6 auf dem Falcon im Gegensatz zu GFA-BASIC in allen Auflösungen einwandfrei. Man benötigt Version 3.6 des OMIKRON.-BASIC Interpreters, die seit der letzten ATARI-Messe als kostenloses Update zur Version 3.5 erhältlich ist. Für komplexe Pop-Ups und solche innerhalb von Dialogboxen ist ein Resource-Construction-Set erforderlich; normale Text Pop-Ups kann man wesentlich einfacher ohne ein solches erstellen, zumal alle mir bekannten RCS zur Zeit noch kleine Probleme mit betriebssystemeigenen Submenüs haben. Das Projekt ist in mehrere Module aufgeteilt, die auf der Monatsdiskette als echte OMIKRON.LIBRARIES vorliegen und dann auch mit dem Befehl LIBRARY Xyz, "XYZ.LIB" nachgeladen werden können. Zusätzlich benötigen Sie die original "GEM.LIB", die ihrem Interpreter beiliegt. Alles weitere finden Sie in den Listings.
Programm 1: Erzeugen und Anzeigen eines Text-Pop-Ups ohne RCS
Programm 2: Demoprogramm für komplexe Pop-Up-Buttons in Dialogboxen
Modul 1: GEM33-Zusatz-Library; hier werden die vier neuen AES-Aufrufe definiert, die noch nicht in der GEM.LIB enthalten sind.
Modul 2: Popdef-Library zum Erstellen von eigenen Text-Pop-Ups ohne RCS; benötigt die OBJECT.LIB (Modul 4)
Modul 3: Pop-Up-Library zum Benutzen beliebiger Pop-Up-Menüs; benötigt die GEM33.LIB (Modul 1) und die OBJECT.LIB (Modul 4)
Modul 4: Object-Zusatz-Library für den vereinfachten Umgang mit GEM-Objekten
Auf der Monatsdiskette finden Sie außerdem die notwendigen Zusätze für die OM-BASIC.HLP-Datei, um die neuen AES-Funktionen einzubinden.
Im zweiten Teil werden wir uns den Submenüs zuwenden. Die Gem33-Library wird dabei genauso wieder Verwendung finden wie die Object-Library. Aber vor allem die Popdef-Library eignet sich besser als jedes RCS, um Submenüs zu erzeugen.
Kai Michael Speck
Literatur:
Hendricks, Herzlinger, Pittelkow: "Das Buch zum ATARI Falcon030", Data Becker Jankowski, Reschke, Rabich: "ATAR] Profibuch ST-STE-TT", Sybex
Hinweis: Aus Platzgründen haben wir die Listings des Artikels nicht abgedruckt. Sie finden sie aber vollständig auf unserer Monatsdiskette (die Redaktion).
dokumentiert ab AES-Version 4.0 (MultiTOS), bereits implementiert im AES 3.31 des zur Zeit ausgelieferten Falcon030
■ MENU_POPUP (AES 36)
Darstellung und Abarbeitung eines Pop-Up-Menüs.
GEM-Arrays:
control = 36
control+2 = 2 Einträge in int_in
control+4 = 1 Einträge in int_out
control+6 = 2 Einträge in addr_in
control+8 = 0 Einträge in addr_out
int_in = me_xpos absolute Bildschirmkoordinaten
int_in+2 = me_ypos der linken oberen Menüecke.
int_out = me_return 0 = Fehler: die Daten in me_mdata sind ungültig.
addr_in = me_menu Zeiger auf die MENU-Struktur des Popup-Menüs
addr_in+4 = me_mdata Zeiger auf die MENU-Struktur, in der die Daten des selektierten Menüeintrages stehen
BASIC-Aufruf: Menu_Popup ( Me_Menu%L , Me_Xpos% , Me_Ypos% , Me_Mdata%L)
Die neue AES-Struktur MENÜ:
struct MENU {
LONG mn_tree; Zeiger auf den Objektbaum des Menüs
WORD mn_menu; Index des den Menüeinträgen übergeordneten Objekts
WORD mn_item; Anfangsmenüeintrag - bestimmt Position des Menüs
WORD mn_scroll; 0 = nicht scrollen, 1 = scrollen
WORD mn_keystate; } Shift-Tastenstatus ([ALT], [CTRL] & [SHIFT])
■ MENU_ATTACH (AES 37)
GEM-Arrays:
control =37
control+2 = 2 Einträge in int_in
control+4 = 1 Einträge in int_out
control+6 = 2 Einträge in addr_in
control+8 = 0 Einträge in addr_out
int_in = me_flag 0 = abfragen, 1 = verbinden/Ändern, 2 = löschen
int_in+2 = me_item Index des Menüeintrages im Hauptmenü, mit dem das Submenü verbunden werden soll
int_out = me_return 0 = Fehler; die Daten in me_mdata sind ungültig.
addr_in = me_tree Zeiger auf den Objektbaum des Hauptmenüs
addr_in+4 = me_mdata Zeiger auf eine MENU-Struktur
BASIC-Aufruf: Menu_Attach ( Me_Mflag% , Me_Tree%L, Mejtem% , Me_Mdata%L)
■ MENU_ISTART (AES 38)
GEM-Arrays:
control = 38
control+2 = 1 Einträge in int_in
control+4 = 1 Einträge in int_out
control+6 = 1 Einträge in addr_in
control+8 = 0 Einträge in addr?out
int_in = me_flag 0 = abfragen, 1 = setzen
int_in+2 = me_menu Objektindex des Submenüeintrags
int_in+4 = me_item Objektindex des Vatermenüeintrags
int_out = me_return 0 = Fehler; das Submenü hat keine Verbindung
addr_in = me_tree Zeiger auf den Objektbaum des Hauptmenüs
BASIC-Aufruf: Menu_start ( Me_Flag% , Me_Tree%L , Me_lmenu% , Me_ltem%)
■ MENU_SETTINGS (AES 39)
Setzen und Abfragen der Pop-Up- und Submenüparameter.
GEM-Arrays:
control = 39
control+2 = 1 Einträge in int_in
control+4 = 1 Einträge in int_out
control+6 = 1 Einträge in addr_in
control+8 = 0 Einträge in addr_out
int_in = me_flag 0 = abfragen, 1 = setzen
int_out = me_return sollte immer = 1 zurückliefern
addr_in = me_values Zeiger auf eine MN_SET-Struktur
BASIC-Aufruf: Menu_Settings (Me_Flag% , Me_Values%L)
Die neue AES-Struktur MN_SET:
struct MN_SET { LONG Display; Anzeigeverzögerung LONG Drag; Auswahlverzögerung LONG Delay; Einfachklick Scroll-Verzögerung LONG Speed; Scroll-Verzögerung WORD Height; Scroll-Höhe (Anzahl der darzustellenden Einträge) }
Alle Verzögerungszeiten werden in Millisekunden gemessen.
Struct_Menu (Menu%L , Mn_Tree%L , Mn_Menu% , Mn_ltem% , Mn_Scroll% , Mn_Keystate%)
Anlegen der neuen AES-Struktur "MENÜ".
In Mn_Tree%L übergibt man die Adresse des Pop-Up-Menübaumes, in Mn_Menu% den Index des Vaterobjektes und in Mn_Item% den Anfangseintrag. Mn_Scroll% sollte 0 sein, es sei denn, es handelt sich um ein Text-Pop-Up, das gescrollt werden soll. Mn_Keystate% ist im Moment bedeutungslos. In Menu%L erhält man dann die Adresse der Struktur zurück.
■ FN Mn_Item% (Menu%L)
Anfangseintrag bzw. gewählten Eintrag der Struktur Menu%L abfragen.
■ FN Mn_Scroll% (Menu%L)
Scrollflag der Struktur Menu%L abfragen.
■ FN Mn_Keystate% (Menu%L)
Shift-Tastenstatus der Struktur Menu%L abfragen.
■ Mn_Item (Menu%L, ltem%)
Item% als Anfangseintrag der Struktur Menu%L setzen.
■ Mn_Scroll (Menu%L, Scroll%)
Scroll% als Scrollflag der Struktur Menu%L setzen.
■ Popup (Pop_Str%L , Tree%L , Ob%)
vollständige Bearbeitung eines Text-Pop-Ups bzgl. eines Pop-Up-Buttons. Das Text-Pop-Up, dessen Struktur in Pop_Str%L übergeben wird, wird relativ zum Button Ob% des Dialogbaumes Tree%L, gezeichnet. Der selektierte Eintrag wird dann automatisch mit einem Häkchen versehen und der Text in den Button übertragen.
■ FN Popup% (Pop_Str%L , X% , Y%)
beliebiges Popup zeichnen und selektierten Eintrag zurückliefern. Die fvfenüstruktur des Pop-Ups steht in Pop_Str%L, die absoluten Bildschirmkoordinaten in X% und Y%; die Funktion liefert den gewählten Eintrag oder eine 0 zurück.
■ Menu_Settings (Me_Flag%, Display%L , Drag%L , Delay%L , Speed%L , Height%)
Menü-Settings abfragen oder einstellen. Bei Me_Flag%=0 werden die aktuellen Settings zurückgeliefert; bei Me_Flag%=1 werden die Parameter als Settings definiert. Vereinfachte Version des AES-Aufrufes MENU_SETTINGS, in der Wirkung aber identisch.
■ Menu_Settings (Height%)
Setzen der Scroll-Höhe. Es wird nur die Scroll-Höhe geändert, alle anderen Settings bleiben unverändert.
■ FN Menu_Settings%
Abfragen der Scrollhöhe.
■ Def_Pop [(Max_W% , Max_H%)]
Definiton eines Pop-Ups einleiten; optional kann die Maximalbreite und -höhe des Pop-Ups (in Zeichen) angegeben werden. Das ist aber nur erforderlich, wenn das Pop-Up sehr groß oder der Speicher sehr klein ist. Die Voreinstellung ist sonst maximal 64 Zeichen Breite und maximal 32 Zeichen Höhe.
■ Pop_Entry (Entry$ , Entry% [, State%])
normalen Eintrag erzeugen
Entry$ enthält den Text des Eintrags, und der Rückgabewert Entry% ist das Handle, mit dem später auf den Eintrag zugegriffen wird. Entry$ sollte keine Anfangs- und Endleerzeichen enthalten, sie werden automatisch in der richtigen Länge erzeugt. Optional kann ein Object State% übergeben werden (am besten durch die Gemdefs). In Text-Pop-Ups sind allerdings nur Normal%=0, Checked%=4, Diasbled%=8 sinnvoll. Ohne Angabe von State% wird Normal%=0 eingestellt.
■ Pop_Line
Es wird eine graue Trennlinie (?--------") als Eintrag erzeugt.
■ End_Pop (Pop_Mem%L)
Pop-Up-Definiton beenden und damit Pop-Up-Objektbaum im Speicher anlegen. Die Objekte werden in der Größe aufeinander abgestimmt und mittels RSRC_OBFIX an die aktuelle Auflösung angepaßt. Die Adresse des Objektbaumes erhält man in Pop_Mem%L zurück. Der so angefertigte Objektbaum kann genau wie jeder mit einem RCS erstellte Objektbaum benutzt werden.
■ Clear_Pop (Pop_Mem%L)
Objektbaum eines Pop-Up-Menüs löschen. Der Speicher, den der Baum belegt hatte, wird wieder freigegeben. Dieser Aufruf ist nur bei knappem Speicher erforderlich -OMIKRON.BASIC gibt beim Programmende sowieso alle Speicherbereiche wieder frei.