#Titel Programmieren / gadtools.library & Pascal
#Logo gadget24:Pinsel/AG.Prog
#Font topaz 8
#C10


Ein kleiner Pascal-Kurs fürs Gadget...
#C31
#Y-10
                                        Programmieren von Gadgets mit der
                                         gadtools.library (entnommen aus
                                         meinem Pascal-Workshop)

#C21

    Gadgets werden mit den Funktionen                 und
#C10
#Y-10
                                      CreateContext()     CreateGadgetA()
#C21
    erzeugt.


    Bevor überhaupt ein Gadget kreiert wird, muß erst mal für GadTools intern
    ein Speicherbereich alloziert werden. Dies geschieht mit der Funktion
                     Ihr übergibt man als Parameter den Pointer auf einen
#C10
#Y-10
    CreateContext().
#C21
    NIL-Pointer. Als Rückgabewert erhält man ein p_Gadget.


    Beispiel:
#Seitenende
    |------------------------- snipp ------------------------|
#C10
    VAR gl : p_Gadget;

    ...
    gl := NIL;
    gl := CreateContext(^gl);
    IF gl = NIL THEN Error("Konnte keinen Speicher allozieren!");
    ...
#C21
    |------------------------- snipp ------------------------|


    Dieser Rückgabewert ist der Anfang der verketteten Gadget-
    Liste.


    Jetzt haben wir unseren Kontext erzeugt und wollen nun unser erstes
    Gadget kreieren, ein normales Gadget. Dafür brauchen wir die
    Struktur NewGadget, die wie folgt aussieht:
#Seitenende
#C10
    TYPE NewGadget = RECORD
      ng_LeftEdge   : Integer;
      ng_TopEdge    : Integer;
      ng_Width      : Integer;
      ng_Height     : Integer;
      ng_GadgetText : Str;
      ng_TextAttr   : p_TextAttr;
      ng_GadgetID   : Word;
      ng_Flags      : Long;
      ng_VisualInfo : Ptr;
      ng_UserData   : Ptr;
    END;
#C21

    Die Felder sollten alle selbst erklärend sein. ng_VisualInfo ist
    für uns sehr wichtig. GadTools braucht die VisualInfo, um die
    Gadgets kreieren zu können. Diese VisualInfo bekommen wir mit
    Hilfe der Funktion                 . Als ersten Parameter
#C10
#Y-10
                       GetVisualInfoA()
#C21
    übergeben wir ihr den Zeiger auf einen Screen (entweder den
    der Workbench oder unseres eigenen Screens oder eines
    Public-Screens). Als zweiten Parameter geben wir NIL an.

    Holen wir uns also schnell die VisualInfo unseres Workbench-
    Screens:

    |------------------------- snipp ------------------------|
#C10
    ...
    VAR
      ps        : p_Screen;
      vi        : PTR;
    BEGIN
      ps := LockPubSceen("Workbench");
      IF ps = NIL THEN Error("Konnte Workbenchscreen nicht locken!");
      vi := GetVisualInfoA(ps,NIL);
      UnLockPubScreen(NIL,ps);
      IF vi = NIL THEN Error("Konnte keine VisualInfo bekommen!");
      ...
    END.
#C21
    |------------------------- snipp ------------------------|
                    lockt einen Public-Screen. Je nachdem, welchen
#C10
#Y-10
    LockPubScreen()
#C21
    Screen-Namen (!) man angegeben hat, wird derjenige Public-
    Screen gelockt. Gibt man NIL an, so wird der Default-Public-
    Screen gelockt.

    Der Screen muß natürlich wieder freigegeben werden, das er-
    ledigt die Prozedur                . Der erste Parameter
#C10
#Y-10
                        UnLockPubScreen
#C21
    kann den Namen des Screens angeben, der zweite die Screen-
    Adresse.


    ACHTUNG! Immer nur einen von beiden Parametern angeben!


    So. Jetzt haben wir unsere VisualInfo und gehen nun daran,
    unseren NewGadget-Record auszufüllen:
#Seitenende
    |------------------------- snipp ------------------------|
#C10
    ...
    VAR ng : NewGadget;
        tattr : TextAttr;
    ...
    tattr := TextAttr("topaz.font",8,0,0);
    ng := NewGadget(10,10,100,13,
                    "Huhu!",^tattr,
                    1,PLACETEXT_IN,
                    vi,NIL);
    ...
#C21
    |------------------------- snipp ------------------------|


    Das war wohl etwas viel, nicht? ;)


    Gehen wir mal Schritt für Schritt durch, was wir gerade-
    eben gemacht haben:
#Seitenende
#C12
    1. tattr := TextAttr ...
#C21

       Hier haben wir eine TextAttr-Struktur ausgefüllt. Wir
       wollen den topaz.font in der Größe 8 Punkte haben.

#C12
    2. ng := NewGadget ...
#C21

       Die ersten 4 Felder geben die Koordinaten an, wo sich
       das Gadget befinden soll.

       Die nächsten beiden Felder sind der Gadget-Text und
       dann unsere TextAttr-Struktur, denn irgendwoher muß
       ja GadTools wissen, in welcher Schrift unser Text
       gezeichnet werden soll!

       Das nächste ist die GadgetID, kennen wir ja noch von
       der OS1.x-Programmierung der Gadgets.

       Das nächste Feld ist interessant: Hier geben wir, je
       nach Gadget-Typ (ja, es gibt mehr Gadget-Typen als
       nur ein simples Button-Gadget!:) Flags in. In unserem
       Beispiel PLACETEXT_IN, was heißen soll, daß unser
       Text im Gadget (zentriert) plaziert werden soll.
       Es gibt noch PLACETEXT_LEFT, PLACETEXT_RIGHT,
       PLACETEXT_ABOVE und PLACETEXT_BELOW (links, rechts,
       oben und unten).

       Die letzten beiden Felder sind unsere VisualInfo und
       UserDaten, die wir getrost auf NIL setzen!


    Nun haben wir unseren Record ausgefüllt und wollen unser
    Gadget kreieren, und zwar mit

#C10
    FUNCTION  CreateGadgetA(D0:Long; A0:p_Gadget; A1:p_NewGadget;
                                                  A2:p_TagItem): p_Gadget;
#C21

    Der erste Parameter gibt die Art des Gadgets an (in unserem Fall
    ein BUTTON_KIND, der zweite das Vorgänger-Gadget (wenn wir
    unser erstes Gadget kreieren, geben wir hier unser "gl" an),
    der dritte unser Record, und der vierte ein Zeiger auf eine
    TagItem-Liste, die das Gadget noch mit Flags erweitern!

    Für die versch. Gadget-Typen gibt es auch unterschiedliche Flags. Ich
    werde diese Flags hier nicht groß erläutern, Sie können sie in
    geeigneter Literatur (z.B. HotHelp der Firma Maxon Computer GmbH oder
    den RKRM's) nachlesen.

    Für alle Gadgettypen gibt es ein Flag:

    GT_Underscore: Mit diesem Tag gibt man an, welches Zeichen für die
    "GadTools-Unterstreichung" verantwortlich ist. Im Allgemeinen wird
    man hier bei ti_Data ein LONG("_"); angeben!

    Beispiel: Als Gadget-Text haben wir "_Hallo" und in der Tag-Liste
#C10
    t[1] := TagItem(GT_Underscore, LONG("_"));
#C21
    Dann wird, wenn unser Gadget auf dem Bildschirm erscheint, der
    Buchstabe H unterstrichen!

    Insgesamt gibt es also sehr viele verschiedene Arten von Gadgets.
    Kreieren wir also nun unser Button-Gadget:

    |------------------------- snipp ------------------------|
#C10
    ...
    bgad := CreateGadgetA(BUTTON_KIND,gl,^ng,NIL);
    IF bgad = NIL THEN { Fehler };
#C21
    |------------------------- snipp ------------------------|

    Wir könnten nun noch mehr Gadgets kreieren. Um die Gadgets an
    unser Window anzuhängen, empfiehlt sich der Tag WA_Gadgets:

    |------------------------- snipp ------------------------|
#C10
    t[1] := TagItem(WA_Gadgets, LONG(gl));
    t[2] := TagItem(WA_Width, ...
    ...
#C21
    |------------------------- snipp ------------------------|
    Dann werden nämlich gleich nach dem Öffnen des Fensters unsere
    Gadgets dargestellt!

    Nun werden wir unsere Gadgets kreieren, das Fenster öffnen,
    einige Sekunden warten, und es wieder schließen. Danach müssen
    wir noch den belegten Speicherplatz, den wir beim Kreieren
    der Gadgets alloziert haben, freigeben:

    |------------------------- snipp ------------------------|
#C10
    ...
    CloseWindow(wp);
    @{B}FreeGadgets(gl);@{UB}
    ...
#C21
    |------------------------- snipp ------------------------|

    Mit               wird unser gesamter allozierter Speicher-
#Y-10
#C10
        FreeGadgets()
#C21
    platz freigegeben.

    Nun also das gesamte Programm:
#C10
PROGRAM CreateGads;

{ Beispiel-Programm für den OS2Workshop

  ©1995 by Björn Schotte, PUBLIC DOMAIN
}

USES Intuition, Exec;

{$incl "gadtools.lib",
       "graphics/text.h"}

VAR
  wp                                    : p_Window;
  vi                                    : PTR;
  gl, bgad                              : p_Gadget;
  ng                                    : NewGadget;
  t                                     : ARRAY[1..7] OF TagItem;
  tattr                                 : TextAttr;
  ps                                    : p_Screen;
  xoff,yoff                             : INTEGER;
  msg                                   : p_IntuiMessage;
  class                                 : LONG;
  done                                  : BOOLEAN;

{ VisualInfo von der Workbench bekommen }
PROCEDURE GetVi;
BEGIN
  ps := LockPubScreen("Workbench");
  IF ps = NIL THEN Error("Konnte Workbenchscreen nicht locken!");
  vi := GetVisualInfoA(ps, NIL);
  UnLockPubScreen(NIL, ps);
  { Damit das Gadget *im* Fenster plaziert wird }
  xoff := ps^.WBorLeft;
  yoff := ps^.WBorTop + ps^.Font^.ta_YSize + 1;
  IF vi = NIL THEN Error("Konnte keine VisualInfo bekommen!");
END;

BEGIN
  OpenLib(GadToolsBase, "gadtools.library", 37);
  GetVi;
  tattr := TextAttr("topaz.font",8,0,0); { topaz.font definieren }
  { Kontext anfordern }
  gl := NIL;
  gl := CreateContext(^gl);
  IF gl = NIL THEN Error("Konnte keinen Kontext allozieren!");

  { Gadget-Record ausfüllen }
  ng := NewGadget(xoff+1,yoff+1,
                  100,14,
                  "_Hallo!",^tattr,
                  1,PLACETEXT_IN,
                  vi,NIL);

  { Underscore definieren }
  t[1] := TagItem(GT_Underscore, LONG("_"));
  t[2].ti_Tag := TAG_DONE;
  { Gadget kreieren. Wenn es fehl schlägt, Fehlermeldung ausgeben. }
  bgad := CreateGadgetA(BUTTON_KIND,gl,^ng,^t);
  IF bgad = NIL THEN
  BEGIN
    FreeVisualInfo(vi);
    Error("Kein Speicher mehr frei!");
  END;

  t[1] := TagItem(WA_InnerWidth, 300); { Breite des Fensters ohne (!) Rahmen }
  t[2] := TagItem(WA_InnerHeight, 70); { Analog die Höhe }
  t[3] := TagItem(WA_Gadgets, LONG(gl)); { Pointer auf unseren Kontext }
  t[4].ti_Tag := WA_Title;
  t[4].ti_Data := "Gadgets";
  { Unsere Window-Flags }
  t[5] := TagItem(WA_Flags, WFLG_NOCAREREFRESH OR WFLG_SMART_REFRESH OR
                            WFLG_ACTIVATE OR WFLG_DEPTHGADGET OR
                            WFLG_CLOSEGADGET OR WFLG_DRAGBAR);
  t[6] := TagItem(WA_Idcmp, IDCMP_CLOSEWINDOW);
  t[7].ti_Tag := TAG_DONE;
  wp := OpenWindowTagList(NIL, ^t);
  IF wp <> NIL THEN
  BEGIN
    done := FALSE;
    REPEAT
      msg := p_IntuiMessage(WaitPort(wp^.UserPort));
      { Wenn GadTools-Gadgets/-Menüs etc. abgefragt werden, dann
        immer (!) GT_GetIMsg() und GT_ReplyIMsg() verwenden!!     }
      msg := GT_GetIMsg(wp^.UserPort);
      WHILE msg <> NIL DO
      BEGIN
        class := msg^.Class;
        GT_ReplyIMsg(msg);
        IF class=IDCMP_CLOSEWINDOW THEN done := TRUE;
        msg := GT_GetIMsg(wp^.UserPort);
      END;
    UNTIL done;
    CloseWindow(wp);
  END ELSE Writeln("Konnte Fenster nicht öffnen!");
  { Allozierte Resourcen wieder freigeben }
  FreeGadgets(gl);
  FreeVisualInfo(vi);
  CloseLib(GadToolsBase);
END.

#C21
Das war's...
#Y-10
#C31
             ©1996 by Björn Schotte <bjoern@baer.franken.de>.
