Sie befinden sich auf der NewGUI Tutorialpage

Start
Über NewGui
Featureübersicht
Changesübersicht
Installation
Download
Demos
Anwendungen
Tutorials
-Windows
-Hintergrundbild
-Gadgets & GuiLoop
-1 Gadget 2 Gui's
-Transparenz
Sourcecodes
Links
Kontakt

Unser Hostingpartner

Alle Tutorials sind in PreASS kompiliert. Aufgrund der starken Ähnlichkeit zu C hier eine kleine Übersicht der Unterschiede.

Dieses kleine Tutorial zeigt das "Ausleihen" von Gadgets zwischen zwei oder mehr Tasks. Ob zwei oder zehn ist vom Prinzip her völlig egal.

Das Beispiel zunächst einmal in Bildern:
Zunächst der Ausgangspunkt, zwei Programme, wie man an der Shell sehen kann:
Das rechte Programm fordert beim Druck auf Transfer Gadget das Slidergadget an. Es muß kein Slidergadget sein, es gehen alle Gadgettypen. Man kann nun über den Slider das Nummerngadget steuern. In einer realen Anwendung wäre dies z.B. die Lautstärkeregelung oder gleich eine ganze Gruppen von Kontrollgadgets, der Fantasie sind da keine Grenzen gesetzt.
Nachdem das Gadget vom eigentlichen Besitzer zurückgefordert wurde, kann es normal weiter benutzt werden. Ergo, es kann völlig egal sein, in welcher Gui ein Gadget ist, wenn man das Ganze entsprechend auslegt! Liegt also beim Programmierer ob das Programm noch funktioniert oder nicht. Wenn Programm 2 das Gadget hat und beendet wird, wird auch das Gadget korrekt freigegeben. Das Programm 1 kann sich dann auch gefahrlos beenden. Allerdings bekommt es sein Gadget nicht wieder. Programm 2 müßte also das Gadget zurücktransferieren wenn es beendet wird, um genau sowas zu verhindern.
Der schlimmste Fall ist, das das Originalprogramm, aus dem die Gadgets geliehen wurden, geschlossen wird, und es die Gadgets nicht mitbekommen. Dann könnte der Rechner crashen, weil die Hooks ins Leere springen. Das kann man aber nun wieder durch geschicktes Abfragen ob noch alle Gadgets da sind, abfangen. Auch könnten die leihenden Guis die original Gui locken, so daß diese erst geschlossen werden kann, wenn kein Client mehr einen Lock hat. Viel ist möglich, wenn man es richtig macht.
Das ist hier natürlich ein Demoprogramm, da kann man das kontrollieren. In der realen Welt, kann ein Programm , einem anderen Programm das Gadget übergeben, ohne das das Zielprogramm das merkt. Das Quellprogramm muß lediglich an das GuiObject kommen. Möchte ein Programmierer dies in seine Applikation aufnehmen, dann wäre eine Pipeline mit interagierenden GUI Objekten ratsam , oder wie hier die Messageversion.

Wie ist das nun gemacht worden?

Start:
    OH=Output()
    MyPort=PortUp("NGTask1")
    move.l myport,replyport  ; Ich gebs zu, ich hab nen bisschen geschludert ;)

    Gui=Open_Window(150,100,320,256,"NewGui Task #1",0,0,0)
    if gui#0
     {
       if (Deep=PlaceDeep(Gui,0,0,"bild1.deep"))#0
        {

Nun wird erstmal der Font gesetzt. Wenn der Font nicht gefunden wird, kommt der Systemfont zum Tragen.

          Wrp=.l4(Gui)
          #Xen=>Topazattr.Name
            15=>Topazattr.Size

          Topazfont=OpenDiskfont(&Topazattr)
          If Topazfont#0 
           {
             WRP=.l4(Gui)
             SetFont(WRP,Topazfont)
           }

          UpdateGui(Gui,>PicTags:NG_BACKGROUND_IMAGE,*deep|TAG_done,null)

Jetzt werden die Gadgets definiert, bitte mitzählen, denn im anderen Programm gibts eins weniger ;)

             
          CreateGadgetGeneric(Gui,005,005,310,020,
                              "Transfer Demo #1",0,0,0,
                              "generic/bevelbox.library",0)
          CreateGadgetGeneric(Gui,055,230,200,020,
                              "Transfer Gadget",0,0,0,
                              "generic/button.library",0)

Hier nun die Verkettung. Die Adresse des Gadgets wird hier gespeichert um Sie direkt dem Slider übergeben zu können:

          result=CreateGadgetGeneric(Gui,100,100,100,025,
                                     "Slidervalue",0,0,0,
                                     "generic/number.library",
                                     >NumberGadget1:NG_TEXT_POS,NG_TOP|
                                                    NG_VALUE,50|
                                                    NG_NB_LISTEN,0|
                                                    NG_INVERSE,1|
                                                    tag_done,null)

          result=CreateGadgetGeneric(Gui,100,150,200,015,
                                     "Slider",0,0,0,
                                     "generic/slider.library",
                                     >SliderGadget1:NG_TEXT_POS,NG_LEFT|
                                                    NG_VALUE,50|
                                                    NG_SLIDER_LISTEN,0|
                                                    NG_SLIDER_MIN,0|
                                                    NG_SLIDER_MAX,100|
                                                    NG_SLIDER_STEP,1|
                                                    NG_NOTICE,*result|
                                                    NG_INVERSE,1|
                                                    tag_done,null)
          gadget==0
           class==0
           
          while class##IDCMP_Closewindow 
           { 

Da kleiner Trick um die Sache mit den Signalen zusparen, schliesslich ist das nurn kleines Demo, wir schalten die GUI einfach in den NONE-Blocking-Modus um. So verhalten sich WaitGuiEvent()s wie GetGuiEvent(Die Funktion gibts allerdings nicht).

             delay(5)
             (Gadget,Class)=WaitGuiEvent(Gui,>noneblocking:NG_NOBLOCKING,1|
                                                           TAG_done,null)
          

Nun holen wir vom MessagePort ggf eine Nachricht ab, wenn jemand das Gadget anfordert. Achtung: Das hier ist absolut gegen die Regel, man mißbraucht das Nameszeigerfeld nicht!

Sobald das klar ist, daß man a) das Gadget hat ( gone=0 ) und b) die Gui wo es hin soll, nicht Null ist, transferiere das Gadget aus Deiner Gui in die Fremde Gui. Bei dieser Kommunikationsmethode, ist völlig offen wer das anfragt, es könnten mehr als 2 Programme an dem Spiel beteiligt sein ! ( Der "Empfänger" gibt ja die ZielGui mit an. )

Damit die Veränderung angezeigt wird, rufen wir WorkGui() auf. ( hab mir schon notiert, daß man WorkGui() auch in TransferGadget() aufrufen sollte. )

             msg=getMsg(MyPort)
             if msg#0 
              {   
                name=.l10(msg)
                if name#0 and gone=0
                 { 
                   Transfergadget(Gui,4,Name)
                   gone==1
                   WorkGui(Gui,0)
                 }
                ReplyMsg(msg)
              }

Nun der Requestteil, also wenn GadgetNr 2 , das ist das Buttongadget, gedrückt wurde und das Gadget nicht in der aktuellen Gui ist, dann schau ob das andere Programm da ist und fordere das Gadget an.

             if Class=#IDCMP_MOUSEBUTTONS and gadget=2 and getGadgetStatus(Gui,Gadget)=0 and gone=1 
              {
                if (msgPort=findPort("NGTask2"))#0
                 {
                   move.l gui,Newgui
                   PutMsg(MsgPort,#Message)
                   WaitPort(Myport)
                   GetMsg(MyPort)
                   gone==0
                   WorkGui(Gui,0)
                 }
              }
           }
          {* Flush *}                  ; Protection of A6 LibraryBase
          freeDeep(deep)
        }

Nun noch der Schutz gegen das Beenden des Originalprogramms und die Crashvermeidung. Wenn das Programm beendet wird, fordert es sich das Gadget einfach wieder an, wenn das noch geht und nötig ist!

       if (msgPort=findPort("NGTask2"))#0 and gone=1
        {
          move.l gui,Newgui
          PutMsg(MsgPort,#Message)
          WaitPort(Myport)
          GetMsg(MyPort)
        }
       If Topazfont#0 
        {
          CloseFont(Topazfont)
        }
       Close_Window(Gui)
     }
    PortDown(MyPort)
    {* Return *}

Nun noch Programm 2. Es ist das gleiche Schema, nur fehlen hier die beiden Gadgets für Slider und Numbergadget! Da das so ist, ist GONE=1 zusetzen.

Start:
    OH=Output()
    MyPort=PortUp("NGTask2")
    move.l myport,replyport

    Gui=Open_Window(150,100,320,256,"NewGui Task #2",0,0,0)
    gone==1
    if gui#0
     {
       if (Deep=PlaceDeep(Gui,0,0,"bild2.deep"))#0
        {
          Wrp=.l4(Gui)
          #Xen=>Topazattr.Name
          15=>Topazattr.Size
      
          Topazfont=OpenDiskfont(&Topazattr)
          If Topazfont#0 
           {
             WRP=.l4(Gui)
             SetFont(WRP,Topazfont)
           }

          UpdateGui(Gui,>PicTags:NG_BACKGROUND_IMAGE,*deep|TAG_done,null)
          CreateGadgetGeneric(Gui,005,005,310,020,
                              "Transfer Demo #2",0,0,0,
                              "generic/bevelbox.library",0)
          CreateGadgetGeneric(Gui,055,230,200,020,
                              "Transfer Gadget",0,0,0,
                              "generic/button.library",0)

          gadget==0
           class==0
           
          while class##IDCMP_Closewindow 
           { 
             delay(5)
             (Gadget,Class)=WaitGuiEvent(Gui,>noneblocking:NG_NOBLOCKING,1|
                                                           TAG_done,null)
          
             msg=getMsg(MyPort)
             if msg#0 
              { 
                name=.l10(msg)
                if name#0 and gone=0
                 { 
                   Transfergadget(Gui,3,Name)
                   gone==1
                   WorkGui(Gui,0)
                 }
                ReplyMsg(msg)
              }

             if Class=#IDCMP_MOUSEBUTTONS and gadget=2 and getGadgetStatus(Gui,Gadget)=0 and gone=1 
              {
                if (msgPort=findPort("NGTask1"))#0
                 {
                   move.l gui,Newgui
                   PutMsg(MsgPort,#Message)
                   WaitPort(Myport)
                   GetMsg(MyPort)
                   gone==0
                   WorkGui(Gui,0)
                 }
              }
           }
          {* Flush *}                  ; Protection of A6 LibraryBase
          freeDeep(deep)
        }
       If Topazfont#0 
        {
          CloseFont(Topazfont)
        }
       Close_Window(Gui)
     }
    PortDown(MyPort)
    {* Return *}

even  
Message:
    dc.l 0,0
    dc.b %10000
    dc.b 0
NewGui:
    dc.l 0
ReplyPort:
    dc.l MyPort
    dc.w 0
even