"Fliegende Dialoge" in GFA-Basic

Dialogboxen haben die unschöne Angewohnheit, immer dort zu erscheinen, wo sie die gerade benötigten Informationen zur Eingabe verdecken. Fliegende Dialoge könnten dieses Problem elegant umgehen, aber leider existieren bislang nur lösungen in ‘C'. Den BASIC-Programmierern blieben somit nur der Biss in den sauren Apfel und der Verzicht auf solche Annehmlichkeiten. Dieses Manko soll mit den im folgenden vorgestellten Routinen beseitigt werden.

Die Fähigkeiten der originalen GEM-Dialogboxen sind, was die Flexibilität ihrer Positionierung am Bildschirm angeht, recht verkümmert. Zumindest erscheint es im ersten Augenblick so. In Urzeiten des Atari ST war die zentrierte Ausgabe am Bildschirm meistens die einzige Darstellungsvariante, die in Programmen zum Ausdruck kam. Allzu oft wurden dabei Informationen, gerade in dem Augenblick, in dem sie benötigt wurden, von der Dialogbox verdeckt. Also ‘ABBRUCH’ im Dialog anwählen (sofern der Programmierer daran gedacht hat) und darunter nachsehen und merken (na, wozu hat man denn im Computerzeitalter einen Notizblock?).

Mit zunehmender Verbreitung der Großbildschirme wurde eine weitere Schwachstelle dieser zentrierten Dialoge evident. Auch wenn der Hauptarbeitsaufwand - beim Hantieren in der Menüleiste - in der linken oberen Ecke lag, mußte man aufgrund der zentrierten Dialogboxen regelmäßig einen Mausmarathon hinlegen, um bei einer Abfrage die gewünschten Knöpfe zu erreichen.

Dialogbox zur Demonstration

Das Problem blieb nicht lange unbeachtet, und schon bald war die Idee zu beweglichen Boxen geschaffen. Diese als C-Bibliothek vorliegenden FLY-DIALs wurden von Julian F. Reschke entworfen und programmiert. Inder Januarausgabe des heurigen Jahres wurde ergänzend auch die ‘MOVE-DIAL’-Bibliothek in der ST-Computer vorgestellt. Mittlerweile gehört es - zumindest in professionellen Programmen -fast schon zum guten 'Programmierton’, sich dieser FLY-DIALs zu bedienen.

Das ursprüngliche Problem blieb letztendlich den Programmierern in GFA-BASIC erhalten, denn sie konnten die C-Routinen nicht nutzen. Aus diesem Grund möchte ich Ihnen eine Abwandlung der AES-Routine FORM_DO vorstellen, die unter anderem ein Verschieben der Dialogboxen zuläßt. Diese Funktion wurde für den Einsatz in GFA-BASIC-Programmen entwickelt. Eine Umsetzung in OMIKRON BASIC dürfte aber keine Probleme bereiten.

Welche Routinen werden zur Verfügung gestellt?

1 )FORM_DO(Baum, Objekt, x-Koordinate,y-Koordinate)
2)FORM_DRAW als Subroutine von FORM_DO Die gesamte Arbeit übernimmt eine GFA-Funktion mit dem Namen FORM_DO(), die in einer erweiterten Parameterliste auch die Dialogboxkoordinaten übernimmt. Die Prozedur Form draw wird nur als Subroutine von FORM DO() eingesetzt.

Das AES bietet Ihnen - um den Verwaltungsaufwand bei Formularen gering zu halten -die fix und fertige Funktion FORM_DO() an. Diese Routine übernimmt, nach Darstellung einer Dialogbox, die vollständige Abarbeitung derselben. Die Originalroutine erfordert die Angabe des Objektbaumes und die Nummer des ersten Objektes, ab dem die Bearbeitung erfolgen soll. Als Funktionsrückgabe erhält man die Nummer des Objektes, über welches das Formular verlassen wurde. Das Verlassen eines Objektes mittels Doppelklick wird durch Setzen des höchsten Bits angezeigt. In diesem Fall muß man, um zur Objektnummer zu gelangen, das Bit ausmaskieren, was durch die GFA-Konstruktion form& = (form& and &HFF) erreicht wird.

Die modifizierte FORM_DO-Funktion unterscheidet sich in zwei Punkten vom Original. Erstens können die x- und y-Koordinaten an die Funktion übergeben werden, um das Formular an den entsprechenden Koordinaten darzustellen. Da diese Variablen als sogenannter ‘Call by reference’ an die Funktion übergeben werden, können Koordinatenveränderungen - die z.B. durch Verschieben des Formulares bewirkt werden - an die aufrufende Prozedur zurückgegeben werden. Sollten sowohl die x-als auch die y-Koordinate Undefiniert sein (entspricht dem Wert Null), wird automatisch eine Zentrierung durchgeführt. Diese können Sie auch jederzeit aktiv durchführen, indem Sie das Bewegungssymbol (MOVER) mit einem Doppelklick anwählen. Danach wird Ihre Dialogbox automatisch zentriert erscheinen.

Wieso läßt sich nun eine Dialogbox plötzlich verschieben? Die Frage wird dann klar, wenn man sich die verschiedenen Status- und Flaggendefinitionen (oder besser Flags) der RSC-Objekte näher ansieht. Was benötigt man zur Realisierung einer Verschieberoutine? Zuerst muß man den Austieg aus der AES-Routine FORM DO schaffen. Dies funktioniert mit Hilfe eines kleinen Tricks. Das Grundobjekt, welches den Boxrahmen darsteilt, hat die Objektnummer Null. Man muß also das nullte Objekt so definieren, daß bei Mausklick darauf die FORM DO-Routine verlassen wird. Zu diesem Zweck gibt es das Objekt-Flag TOUCHEXIT\ welches man am Objekt Null aktivieren muß. In GFA-BASIC sieht das folgendermaßen aus (s. Bild):

tree%= <- Adresse der Dialogbox
objnull=0
touchexit=&H40
OB_FLAGS(tree%,objnull)= OB_FLAGS(tree%,objnull) OR touchexit

Nun wird bei Anklicken des Grundrahmens, sofern kein anderes Objekt darüber liegt, die FORM_DO-Verarbeitung abgebrochen, und man kann in seine selbstdefinierte Verschiebeprozedur verzweigen und nach Erledigung der Bewegung in die Dialogverarbeitung zurückkehren. Um nur das Bewegungszeichen (MOVER) abzufragen, muß man eine Koordinatenüberprüfung, die den zulässigen Bereich einschränkt, durchführen.

Der zweite Unterschied zur Original-AES-Routine liegt darin, daß die modifizierte FORM DO-Funktion auch die Darstellung des Formulares übernimmt. Bei Benutzung der Original-FORM_DO-Routine müssen Sie sich um das Zeichnen und Löschen der Dialogbox am Bildschirm selbst kümmern. Hierzu stellt Ihnen das AES die Prozeduren OBJC_CENTER, OBJC_DRAW und FORM_DIAL zur Verfügung. Die in GFA modifizierte FORM_DO-Routine nimmt Ihnen diese Arbeit ab. Sowohl die Bildschirmdarstellung als auch das Räumen des Bildschirmes werden automatisch erledigt. Wenn Ihnen dieser Komfort aber hinderlich sein sollte, können Sie diese Programmteile nach Belieben aus der Funktion ausgliedern.

Das Wiederherstellen des Hintergrundes erfolgt im Normalfall durch Absetzen einer REDRAW-Meldung an die laufende Applikation, die nun darauf zu reagieren hat. Falls Sie dies nicht tut, entstehen häßliche graue Löcher, die so manche unsauber programmierte Anwendung auszeichnen. Um das Neuzeichnen der Dialogbox zu beschleunigen, wird in diesem Fall der Bildschirmhintergrund gepuffert. In GFA-BASIC bietet sich für diese Tätigkeit eine Variable vom Typ String an. Der Nachteil liegt darin, daß natürlich mehr Speicherplatz verbraten wird, und zweitens, daß diese Lösung auf der neuen Maschine in der TT-Auflösung bei zu großen Boxen nicht mehr ohne weiteres funktioniert, denn Strings dürfen maximal 32786 Byte groß sein, eine Dimension, die bei einer größeren Box in der TT-Auflösung durchaus überschritten werden kann.

Zur Programmdemonstration wird lediglich eine - mit dem Resource-Construktion-Set erstellte - Dialogbox benötigt. Diese muß allerdings ein Objekt beinhalten, welches als EXIT definiert ist. In allen anderen Fällen ist eine Verwendung mit der FORM_DO-Routine ein ‘Warten auf Reset’. Nach dem Programmstart werden Sie über eine Dateiauswahlbox aufgefordert, eine RSC-Datei zu wählen. Der erste Baum (=Treel) dieser Datei wird nun am Bildschirm dargestellt und Sie können die ‘Fliegenden Dialoge’ in GFA-BASIC testen.

Literatur:

[1] Handbuch GFA-BASIC 3.0; GFA Systemtechnik GmbH

[2] Engels G/Görgens M: GFA-BASIC-Version 3.0; GFA Systemtechnik GmbH

[3] Baldauf Mathias: Movedial -Bewegliche Dialogboxen; ST-Computer 1/91, S. 100ff

' * * * * * * * * * * * * * * * * * *
' *
' * FLYING DIAL’s in GFA BASIC V3.0 
' *
' * Autor: W.Kohlmaier 4/1991 
' *
' * (c) 1991 MAXON Computer GmbH 
' *
' * * * * * * * * * * * * * * * * * *
'
' Resourcenamen wählen ....

FILESELECT "\*.RSC","",resource$
'
' Resource laden 
~RSRC_LOAD(resource$)
'
'
baum%=0 ! Adresse von Baum=0 erfragen 
~RSRC_GADDR(0,baum%,adresse%)
'
'
'
' -------- Demonstration einer 'FLY DIAL' Version in GFA BASIC-----
'
wx&=32	! X Koordinate wo Dialogbox erscheinen soll 
wy&=32	! Y Koordinate wo Dialogbox erscheinen soll
'
~@form_do(adresse%,0,wx&,wyfi) ! die neue FORM_DO Routine
'
' Resource Speicher wieder freigeben 
~RSRC_FREE()
'
END
'
' ------- Funktionen und Proceduren
'
'
FUNCTION form_do<tree%,start%,VAR x&,y&)
    '
    LOCAL form&,d&,w&,h& ! lokale Variablen 
    LOCAL rx&,ry&        ! Dummy-Variablen um Verschiebung zu testen 
    LOCAL puffer$        ! rettet Bildschirmausschnitt in Puffer$
    LOCAL wrk_x,wrk_y    ! maximale X-,Y-Bildschirmkoordinaten
    '
    '
    wrk_x=WORK_OUT(0) ! ermittelt über VDI die max. Gerätekoordinaten 
    wrk_y=WORK_OUT(1)
    '
    sicher_rand=64 ! Sicherheitszone vor dem Hinausschieben 
    mover_dim=16 ! Größe des MOVER Zeichen
    '
    ' --- Dialogbox zeichnen --
    '
    ~WIND_UPDATE(3) ! Kontrolle an Dialogbox abgeben
    '
    '
    ' Wenn globale X& + Y& Variable verwendet werden um die 
    Dialogboxkoordinaten 
    ' zu puffern werden diese hier auch verwendet.
    '
    IF x&>0 OR y&>0 ! wenn Übergabekoordinaten <>0 dann x& y& verwenden...
        '
        ~FORM_CENTER(tree%,d&,d&,w&,h&) ! nur w& und h& erfragen 
        OB_X(tree%,0)=x&                ! Dialogbox an x& Wert setzen
        OB_Y(tree%,0)=y&                ! Dialogbox an y&
        '
    ELSE                                ! ... sonst zentrieren
        '
        ~FORM_CENTER(tree%,x&,y&,w&,h&)
        '
    ENDIF
    '
    ' Ausschnitt puffern
    GET MAX(0,x&-4),MAX(0,y&-4),MIN(wrk_x,x&+ w&+4),MIN(wrk_y,y&+h&+4),puffer$
    '
    '
    ' Der Trick wieso alles funktioniert...
    ' Den Basisrahmen der Dialogbox = Objekt
    ' als TOUCHEXIT definieren.
    ' Aus diesem Grund kann die Box
    ' verlassen werden wenn die ’MOVE'-Ecke 
    ' angeklickt wird.
    '
    '
    objnull=0 
    touch_exit=&H40
    OB_FLAGS(tree%,objnull)=OB_FLAGS(tree%,objnull) OR touch_exit ! Objekt 0 der Box als TOUCHEXIT definieren
    '
    '
    ' ~FORM_DIAL(1,0,0,0,0,x&,y&,w&,h&) ! eventuell Dialogauschnitt anmelden
    '
    '
    ' Dialogbox mit 'MOVE'-Eck zeichnen 
    form_draw
    '
    '
    ' Beginn der eigentlichen FORM_DO Routine
    '
    '
    DO
        '
        ' Dies ist der Standard FORM_DO Aufruf des AES
        form&=FORM_DO(tree%,start%)
        '
        '
        ' Schleife verlassen wenn ein Objekt größer als 0 angeklickt wurde...
        ' 'AND &HFF' filtert den Doppelklick heraus
        '
        EXIT IF (form& AND &HFF)<>0 ! ändern
        ' wenn das Objekt =0 gewählt wurde 
        ' dann Verschiebung beginnen
        '
        '
        rx&=x& ! alte x Koordinaten puffern 
        ry&=y& ! - y -
        '
        '
        IF MOUSEX<=mover_dim AND MOUSEY<=mover_dim ! wenn Maus innerhalb des MOVE-Zeichens 
            IF BTST(form&,31)
                ' Wenn Doppelklick dann Dialogbox zentrieren
                '
                ~FORM_CENTER(tree%,x&,y&,w&,h&)
            ELSE
                ' ... sonst Rahmen verschieben
                '
                DEFMOUSE 4 ! Mausform auf flache Hand schalten
                '
                ' Der Wert '22* sperrt die Verschiebung in die Menüleiste 
                ' kann bei Bedarf auf Null gesetzt werden
                '
                ' sicher_rand bestimmt die Größe des minimal sichtbaren Anteiles der 
                ' Dialogbox, bei Verschiebung nach rechts unten.
                '
                ~GRAF_DRAGBOX(OB_W(tree%,0),OB_H(tree%,0),OB_X(tree%,0),OB_Y(tree%,0),4,22,wrk_x+OB_W(tree%,0)-sicher_rand,wrk_y+OB_H(tree%,0)-sicher_rand,x&,y&)
                '
                DEFMOUSE 0 ! Mausform auf Pfeil retour
                '
            ENDIF
        ENDIF
        '
        '
        '
        IF x&<>rx& OR y&<>ry&
            ' wenn tatsächlich eine Verschiebung erfolgte...
            '
            ' alten Ausschnitt restaurieren...
            PUT rx&-4,ry&-4,puffer$
            '
            ' ... und neuen Ausschnitt puffern
            GET MAX(0,x&-4),MAX(0,y&-4),MIN(wrk_x,x&+w&+4),MIN(wrk_y,y&+h&+4),puffer$
            '
            ' neue Dialogkoordinaten festsetzen 
            OB_X(tree%,0)=x& ! Dialogbox an neuen x& Wert setzen 
            OB_Y(tree%,0)=y& ! Dialogbox an neuen y& Wert setzen
            '
            ' Dialogbox mit 'MOVE'-Eck neuzeichnen 
            form_draw
            '
        ENDIF
        '
        '
    LOOP
    '
    OB_STATE(tree%,form& AND &HFF) =
    OB_STATE(tree%,form& AND &HFF) AND &X1111111111111110 
    '---- FORM_DO verlassen -----
    '
    '
    PUT x&-4,y&-4,puffer$ ! Bildschirm restaurieren
    '
    '
    ' ~FORM_DIAL(3,0,0,0,0,x&,y&,w&,h&) ! ev. Redraw Meldung ans System schicken
    '
    '
    ~WIND_UPDATE(2) ! Kontrolle ans AES zurückgeben
    '
    ' gibt die Nummer des Objektes, über welches die Dialogbox verlassen wurde 
    ' als Rückgabewert zurück 
    RETURN form&
    '
    '
ENDFUNC
'
'
PROCEDURE form_draw 
    LOCAL m
    '
    ' Diese Procedure zeichnet die Dialogbox und das 'MOVE' Eck links oben
    '
    '
    ' Grafik Nullpunkt auf linke, obere Ecke der Dialogbox setzen
    '
    CLIP OFFSET OB_X(tree%,0),OB_Y(tree%,0)
    '
    ' Dialogbox zeichnen
    ~OBJC_DRAW(tree%, 0,4,x&-4,y&-4,w&+4,h&+4)
    '
    '
    GRAPHMODE 1 ! Grafikmodus auf überschreiben setzen 
    DEFFILL 1,0 ! weißes Füllmuster wählen
    '
    m=mover_dim
    '
    PBOX 0,0,m,m ! zeichnet den Winkel ins Eck
    DRAW 0,m TO m, 0 
    '
    SUB m, 2
    DRAW 0,m TO m,0 
    '
RETURN

Wolfgang Kohlmaier
Aus: ST-Computer 12 / 1991, Seite 76

Links

Copyright-Bestimmungen: siehe Über diese Seite