|
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
|
|