Einbindung von 'userdefined objects' in GFA-BASIC 3.x (c)1992 by Gregor Duchalski Mit den hier vorliegenden Routinen k”nnen Sie endlich auch GFA-BASIC-Programme mit zeitgem„žen Dialogboxen versehen: -Flydial-Ecke, damit verbunden natrlich frei verschiebbare Dialoge im SOLID-Modus -Unterstrichene Dialogtitel -Ankreuz-Buttons -Runde Buttons -Ge„nderte Menuestriche, sog. 'nicelines' -Tastaturbedienbare Buttons mit unterstr. Buchstaben Die Routinen funktionieren in allen ST/TT-Aufl”sungen! Die Realisation der Objekte orientiert sich dabei eng an den Flydials von Julian Reschke, dem die Ehre gebhrt, hier einen weitreichenden Standard geschaffen zu haben. Mein Dank geht an Michael Seyfried fr die Relozier-Routine und an Dirk Koenen, der einige ntzlich Flydial-Routinen beigesteuert hat. Das ist die erste ”ffentliche Version der neuen Flydials. Sicher werden noch Verbesserungen folgen. Soll z.B. der Speicherbedarf verringert werden, alles in einem INLINE untergebracht werden usw. Wenn Sie also weitere Vorschl„ge haben, immer her damit! Die Routinen sind Freeware, die Weitergabe ist erwnscht. Allerdings sollten die Funktionen nur komplett weitergegeben werden. Sollten Sie die Routinen in eige- nen Programmen verwenden, so sollte der Ursprung erw„hnt werden. Meine Adresse : Gregor Duchalski, Baueracker 15a, 4690 Herne 1 oder per eMail: GREGOR DUCHALSKI @ DO im Mausnetz -------------------------------------------------------------------------------- Folgende Dateien sollten Sie besitzen... -------------------------------------------------------------------------------- FORM_DO.TXT Dieser Text FORM_DO.LST Beispiel-Listing FORM_DO.RSC Beispiel-Resource FORM_DO.DFN RSC-Definitionsfile INTERFACE.IMG Beispiel fr die INTERFACE-Einbindung *SOURCEN.C In diesem Ordner finden Sie die Ausgaberoutinen im C-Quell- code und die compilierten INLINES D_BUTTON.C Unterstr. Buttons/Strings D_BUTTON.INL D_FLYDIAL.C Flydial D_FLYDIAL.INL D_KREUZ.C Ankreuz-Button D_KREUZ.INL D_KREIS.C Runder Radiobutton D_KREIS.INL D_LINIE.C Unterstrichener Text D_LINIE.INL D_NICELINE.C Anderer Menuestrich D_NICELINE.INL MOVEDIAL.C Bewegt die Dialogbox MOVEDIAL.INL RELOCATE.C Relozier-Routine RELOCATE.INL ERMITTEL.LST Ermittelt die ben”tigte INLINE-Gr”že Das Beispiel-Listing liegt aus Kompatibilit„tsgrnden im ASCII-Format vor. Daher mssen Sie zu Beginn zun„chst die INLINES einladen. Die C-Routinen ben”tigen Sie nur, wenn Sie Ver„nderungen an den Ausgabefunktionen vornehmen wollen. Dieser Text stellt keine umfassende Einfhrung in die userdefined objects dar, ein gewisses Vorwissen sollten Sie also mitbringen. Literaturvorschl„ge: ST-COMPUTER 2/91, S. 100, Button-Designer, Hans-Jrgen Riechstein ST-MAGAZIN 4/91, S. 78, Objekte u. Resourcen, Dietmar Rabich ATARI PROFIBUCH, 10 Auflage, S. 778, Frei definierte Objekttypen -------------------------------------------------------------------------------- So benutzen Sie die Routinen... -------------------------------------------------------------------------------- Objekte festlegen Im RCS mssen wir festlegen, wie das Objekt sp„ter aussehen soll. Dazu verwen- den wir die unbenutzten Bits von OB_FLAGS(), im einzelnen: Bit 9 -> Menue-Niceline Bit 10 -> Flydial Bit 11 -> Ankreuz-Button Bit 12 -> Runder Button Bit 13 -> Unterstr. Dialogtitel Bit 14 -> Unterstr. Button/String Sie ben”tigen allerdings ein RCS, indem Sie diese Werte setzen k”nnen. INTERFA- CE bietet sich da an. Sie k”nnen die Resource von INTERFACE entsprechend anpas- sen, die Belegung k”nnen Sie dem Bild INTRFACE.IMG entnehmen. Verfgen Sie ber kein so komfortables RCS, so mssen die Objekte aus der Bei- spiel-Resource jeweils in Ihre eigenen Resourcen kopieren. Welchen Typ das Objekt zun„chst im RCS hat, ist egal. In unserem Fall nahmen wir ein BOXCHAR-Objekt, da es nicht viel Speicher ben”tigt. Tastenbedienung Um ein Objekt mit der Tastatur bedienen zu k”nnen, muž ihm der SCAN-Code der gewnschten Taste mitgegeben werden. Dazu verwenden wir das unbenutzte, obere Byte von OB_TYPE(), auch 'extended OB_TYPE' genannt. Den Buchstaben, der un- terstrichen werden soll, markieren wir mit dem Zeichen '['. Ein Beispiel: Der Button 'Abbruch' soll ber die Taste 'A' angesprochen werden. Dazu tragen wir zun„chst im RCS als Text '[Abbruch' ein. Das 'A' den SCAN-Code 30 hat, tra- gen wir '30' als extended OB_TYPE ein. Damit unsere Routine berhaupt weiž, daž es sich um ein spezielles Objekt han- delt, setzen wir das 14.Bit von OB_STATE. Es ist geplant, die Auswertung direkt ber das '['-Symbol laufen zu lassen. -------------------------------------------------------------------------------- Hier sollten Sie nur weiterlesen, wenn Sie die Ausgaberoutinen ver„ndern wollen und ber die n”tgen C-Kenntnisse verfgen... -------------------------------------------------------------------------------- Ver„ndern der Ausgaberoutinen Wenn Ihnen die Ausgaberoutinen nicht zusagen, so k”nnen Sie diese natrlich auch ver„ndern: In der Projektdatei mssen Sie 'PCSTART.O' weglassen. In den Linker-Einstel- lungen sollten Sie fr die STACK- und HEAP-Gr”že '0' eintragen. Sonst wrde der Code unn”tig verl„ngert werden, da zus„tzlich ein Stackbereich von mind. 4096 Bytes eingerichtet werden wrde. In den Compiler-Optionen habe ich nur 'default char is unsigned' gesetzt, andere Einstellungen sind aber m”glich. Die compilierte Routine „hnelt einer Programmdatei. D.h. Sie hat einen 28 Bytes langen Header, in dem z.B. die Gr”že des TEXT, DATA und BSS-Segmentes abgelegt sind. Sie muž im BASIC zun„chst reloziert werden, bevor wir sie verwenden k”n- nen. Stellt sich ein Problem: Beim zweiten Start des Programmes im Interpreter wrde es Probleme geben, da die Routine im INLINE ja dann bereits reloziert ist. Also laden wir die Routine in einen INLINE und kopieren sie bei jedem Programmlauf. Die Kopie relozieren wir dann. Der INLINE der Kopie ist um eini- ges gr”žer als der INLINE, der die compilierte Routine enth„lt. Denn er enth„lt zus„tzlich das BSS-Segment. Wie grož muž der zweite INLINE sein? Ganz einfach: 28 Bytes fr den Programmheader +Gr”že des TEXT-Segmentes +Gr”že des DATA-Segmentes +Gr”že des BSS-Segmentes Dazu finden Sie das Programm ERMITTEL.LST im SOURCEN-Ordner. Damit laden Sie einfach die C-compilierte Ausgaberoutine. Ausgegeben wird dann die Gr”že des ben”tigten INLINES. Nach soviel Theorie ein Beispiel: Wir compilieren in C eine Ausgaberoutine. Das erzeugte File 'D_BUTTON.INL' ist 313 Bytes lang. Also sieht der 1. INLINE im Programm so aus: INLINE a%,313 Hier laden wir die Routine ein. Mit dem ERMITTEL.LST-Programm ermitteln wir fr den zweiten INLINE eine Gr”že von 2156 Bytes. Somit haben wir den 2. INLINE: INLINE draw_linie% Beim Programmstart kopieren wir den Original-INLINE (313 Bytes) in den gr”žeren INLINE (2156 Bytes): BMOVE a%,draw_button%,313 Damit sind die Routinen bereit zum Eintragen in die Objektstruktur. Nach dem Laden des RSC-Files durchsuchen wir die Dialogb„ume nach UOs. Das geschieht mit der Funktion 'rsc_walk_tree'. In einem ersten Schritt tragen wir alle gefundenen UOs in den String a$ ein: a$=a$+MKI$(tree&)+MKI$(obj&)+CHR$(art) In l% z„hlen wir dabei mit, wieviel Speicher wir sp„ter anfordern mssen. Dann machen wir das Objekt zu einem UO, indem wir OB_TYPE() des Objektes auf G_USERDEF (=24) setzen. Im zweiten Schritt gehen wir den String durch, erzeugen einen USERBLK fr jedes Objekt und weisen diese OB_SPEC() zu. Eine USERBLK-Struktur umfažt 8 Bytes umfažt und hat folgenden Aufbau: long *ub_code /* Zeiger auf die Objektausgabe-Funktion */ long ub_parm; /* freier Parameter */ Nun tragen wir also den Zeiger auf die Ausgaberoutine ein: {userblk%}=draw_linie% Als freien Parameter bergeben wir das Bildschirmhandle V~H, da wir es fr alle Zeichenfunktionen in der Ausgaberoutine ben”tigen: {userblk%+4}=V~H Bei einem BUTTON-Objekt ist allerdings etwas mehr Aufwand erforderlich, da hier mehr Parameter (Text, Zeichenh”he usw.) ben”tigt werden. Zuerst tragen wir wie gehabt die Zeichenroutine ein: {userblk%}=draw_button% Als optionalen Paramter bergeben wir allerdings die Adresse einer weiteren Struktur: {userblk%+4}=userblk%+8 Diese Struktur befindet sich direkt hinter dem USERBLK, sie ist 10 Bytes lang und hat folgenden Aufbau: WORD u_handle; /* Bildschirmhandle V~H */ LONG *u_text; /* Adresse des Textes */ BYTE u_wchar; /* Breite eines Zeichens */ BYTE u_hchar; /* H”he eines Zeichens */ WORD u_pos; /* Pos. d. unterstr. Buchst. */ Ein normales UO ben”tigt also eine 8 Bytes lange Struktur, ein Button 8+10, also 18 Bytes. Alles klar? Breite und H”he eines Zeichens ermitteln wir am Programmbeginn mit GRAF_HANDLE. Nun lesen wir den Buttontext aus und suchen das '[' Zeichen in ihm, das ja an- gibt, welcher Buchstabe unterstrichen werden soll. Auch diese Position tragen wir in die erweiterte Struktur ein. Wir entfernen das '[' aus dem String und schreiben ihn zurck: b$=CHAR{OB_SPEC(rsc_adr%(tree&),obj&)} pos&=INSTR(b$,"[") ! ...Pos. des unterstr. Buchst. ermitteln IF pos& b$=LEFT$(b$,PRED(pos&))+MID$(b$,SUCC(pos&)) CHAR{OB_SPEC(rsc_adr%(tree&),obj&)}=b$ ENDIF {userblk%+4}=userblk%+8 ! ...in USERBLK Zeiger eintragen INT{userblk%+8}=V~H ! WORD u_handle; /* Bildschirmhandle V~H ' ! BYTE *u_text; /* Adresse des Textes {userblk%+10}=OB_SPEC(rsc_adr%(tree&),obj&) BYTE{userblk%+14}=wchar& ! BYTE u_wchar; /* Breite eines Zeichens BYTE{userblk%+15}=hchar& ! BYTE u_hchar; /* H”he eines Zeichens INT{userblk%+16}=pos& ! WORD u_pos; /* Pos. d. unterstr. Buchst. Jetzt wird vielleicht auch deutlich, warum wir die Resource in zwei Schritten durchsuchen mssen: Um feste Adressen fr die USERBLKs zu erhalten, mssen wir den gesamten Speicherbereich mit MALLOC allozieren. Das k”nnen wir aber nicht, bevor wir nicht wissen, wieviel Speicher wir brauchen... Damit ist die Einbindung der userdefined object abgeschlossen. -------------------------------------------------------------------------------- Herne 1, 06.08.92