[Anmerkung: Thomas hat uns den Kurs zur Verfügung gestellt, ich habe inhaltlich kaum etwas geändert. Ansonsten stehen meine Kommentare in eckigen Klammern, wobei ich nur Vermutungen anstellen kann, was Blitz-Basic angeht. Red.CC]
Im letzten Kursteil hatten wir ja bereits das Blitten von einer Bitmap in ein Window. Dieses soll heute erklärt werden und den praktischen Nutzen zeigen. Außerdem bekommen wir es zum ersten mal mit User-Gadgets und den IDCMP-Flags zu tun.
Der kleine Ausflug zum Schluß ins Reich der Peeks und Pokes ist die Vorbereitung auf Teil 5.
Und nun gehts los:
Macht es Sinn, die Bitmap in ein Fenster zu legen, wenn es doch möglich ist von BB2 aus in ein Fenster zu blitten und zu zeichnen? Warum dann also noch die Bitmap?
Stellen wir uns folgende Situation vor:
Das Programm zeichnet eine Grafik, die eine sehr lange Rechenzeit hat und der Benutzer soll dessen Fenstergröße selber bestimmen können. Desweiteren soll der Benutzer mit Hilfe der Proportional-Gadgets jede Stelle der Grafik sehen können, egal wie groß das Fenster ist.
Es würde somit beim Scrollen durch das Fenster eine immense Rechenzeit aufgewendet werden. Aus diesem Grund zeichnen wir das alles mit den schnellen BB2 Befehlen auf eine Bitmap und Kopieren dann diese in unser Fenster.
Hier das Beispiel:
- Window mit Proportional Gadgets und einer Bitmap
WBStartup
NEWTYPE.screeninfo
id.l
width.l
height.l
_depth.w
overscan.w
autoscroll.w
bmapwidth.l
bmapheight.l
End NEWTYPE
NEWTYPE.WS
_screen.l
End NEWTYPE
NEWTYPE.pt
x.w
y.w
End NEWTYPE
Dim p.pt(20)
WBenchToFront_
WbToScreen 0
FindScreen 0
; Die Gadgets
PropGadget 0,-3,-8,$18000+4+8+64,1,-20,8
PropGadget 0,-14,10,$11000+2+16+128,2,12,-20
; Ende Der Gadgets
*sc.screeninfo=ASLScreenRequest(31)
If *sc
Dim scrtags.TagItem(8)
col.w=-1
scrtags(0)\ti_Tag=#SA_Left,0
scrtags(1)\ti_Tag=#SA_Top,0
scrtags(2)\ti_Tag=#SA_Width,*sc\width
scrtags(3)\ti_Tag=#SA_Height,*sc\height
scrtags(4)\ti_Tag=#SA_Depth,*sc\_depth
scrtags(5)\ti_Tag=#SA_Overscan,*sc\overscan
scrtags(6)\ti_Tag=#SA_AutoScroll,*sc\autoscroll
scrtags(7)\ti_Tag=#SA_DisplayID,*sc\id
scrtags(8)\ti_Tag=#SA_Pens,&col
ScreenTags 0,"BB2-Kurs von Thomas Krippner",&scrtags(0)
Use Screen 0
*Scr.WS=Addr Screen (0)
FH.w=Peek.w(Peek.l(*Scr\_screen+40)+4)
0,0,FH+3,Peek.w(*Scr\_screen+12),Peek.w(*Scr\_screen+14)-(FH+3), $1|$2|$1000|$400|$8,"Grafik Beispiel",1,2,0
Wi0=ActiveWindow
BitMap 1,Peek.w(*Scr\_screen+12),Peek.w(*Scr\_screen+14),2
Use BitMap 1
For q = 0 To 19
p(q)\x=(InnerWidth/2)+Sin(2*q*Pi/20)*((InnerWidth/2)-1)
p(q)\y=(InnerHeight/2)+Cos(2*q*Pi/20)*((InnerHeight/2)-1)
Next q
For q = 0 To 18
For w = q+1 To 19
Line p(q)\x,p(q)\y,p(w)\x,p(w)\y,1
Next w
Next q
x=0:y=0
Gosub GGGroesse
BitMaptoWindow 1,0,0,0,0,0,WindowWidth,WindowHeight
Repeat
FlushEvents
ev.l=WaitEvent
If Wi0 = ActiveWindow
If ev=$2
WCls
x=HPropPot(0,1)
y=VPropPot(0,2)
Gosub GGGroesse
ev=$20
End If
If ev = $20
x=HPropPot(0,1)*Peek.w(*Scr\_screen+12)
y=VPropPot(0,2)*Peek.w(*Scr\_screen+14)
x=QLimit (HPropPot(0,1)*(Peek.w(*Scr\_screen+12)-InnerWidth),0,(Peek.w(*Scr\_screen+12)-InnerWidth))
y=QLimit (VPropPot(0,2)*(Peek.w(*Scr\_screen+14)-InnerWidth),0,(Peek.w(*Scr\_screen+14)-InnerHeight))
BitMaptoWindow 1,0,x,y,0,0,InnerWidth,InnerHeight
End If
End If
Until ev = $200
End If
End
.GGGroesse
SetHProp 0,1,x,WindowWidth/Peek.w(*Scr\_screen+12)
SetVProp 0,2,y,WindowHeight/Peek.w(*Scr\_screen+14)
Redraw 0,1
Redraw 0,2
Return
[Als Datei in Bin zu finden.]
Unter Gadgets erzeugen wir zwei Proportional-Gadgets, die wir in den Fensterrand integrieren. Für die Flags der Gadgets ist wie immer das BB2-Handbuch zuständig !!!
Im Bereich des Windows haben wir eine 0 angehängt, um die Gadgetliste 0 an unser Window zu übertragen (GTL). Nachdem wir unseren Screen geöffnet haben, öffnen wir eine Bitmap mit der Nummer 1 und den Ausmaßen unseres Screens.
Dieses erklären wir mit Use Bitmap 1 zum Ein- und Ausgabegerät. Dann wird die Grafik berechnet und in die Bitmap gezeichnet. Jetzt springt das Programm nach GGGroesse. Die Größe des Gadget-Body wird nun bestimmt.
SetHprop GadgetListe,Identität,Anfang,Größe
Gadgetliste und Identität sind klar 0,1 im ersten Fall.
Am Anfang soll das Gadget ganz links bzw. ganz oben stehen, dies sind die Positionen 0 (x=0 und y =0).
Jetzt der schwere Teil: Die Werte des Gadgets liegen zwischen 0 und 1, daß heißt, er gibt keine Pixel aus, sondern einen Wert zwischen 0 und 1 der proportional die Lage des Bodys wiedergibt.
Ein Beispiel: 0.5 wäre immer die Mitte des Windows, egal ob das Window 10 Pixel hoch ist oder 1000 Pixel.
Also müssen wir unseren Body auch dementsprechend setzten. Die Größe des Windows geteilt durch die Größe der Grafik gibt uns einen Wert mit dem die Intuition-Library arbeiten kann.
Ein Beispiel: Das Window ist 100 Pixel und die Grafik 200 Pixel hoch, Body-Größe damit 0.5, d h. der Körper des Gadgets nimmt die Hälfte des Windows ein. Klingt kompliziert, ist es aber nicht, hier hilft nur Praxis und Ausprobieren.
Das Programm zeichnet die Propgadgets nach dem Berechnen mit Redraw neu und springt wieder zum Ausgangspunkt.
Mit dem Befehl BitMaptoWindow wird der Inhalt der Bitmap auf das Window übertragen.
BitMaptoWindow BitMap,Window,StartScreenX,StartScreenY,ZielWindowX,ZielWindowY,Breite,Höhe StartScreenX (Bitmap) Anfangsvertikalepunkt der Übertragung StartScreenY (Bitmap) Anfangshorizontalpunkt der Übertragung ZielWindowX (Window) Endpunkt von StartScreenX ZielWindowY (Window) Endpunkt von StartScreenY Breite und Höhe Zu übertragende Größe in Pixel
Jetzt sehen wir erst die Grafik auf unserem Window. Dafür wird sie nicht erst aufgebaut, sondern ist sofort da.
Und schon sind wir in der Repeat-Schleife.
Wenn der Anwender das Window verkleinert, liefert ev.l=$2. In den Variablen x und y wird die momentane Position der Gadget-Bodys eingetragen. Da Intution das Window automatisch vergrößert und damit auch unsere Gadgets, die wir ja in den Fensterrand eingetragen haben, müssen wir uns jetzt um die korrekte Größe der Bodys kümmern. Durch das Springen nach GGGroesse werden unsere Gadget-Bodys neu berechnet und gezeichnet. Die Position der Bodys ist jetzt nicht Null, sondern die vom User eingestellte Position.
Die Variable ev setzen wir nun auf $20, so als ob der User die Gadgets betätigt hätte. In dieser Schleife wird die Position der Bodys wieder in x und y geschrieben. Diesmal aber mit der Größe der Grafik multipliziert und somit erhalten wir die Position der Grafik wieder.
Beispiel: Die Grafik ist 200 Pixel hoch, der Body steht auf 0.5, also der Hälfte des Windows, Resultat ist 100 Pixel (die Hälfte der Grafik).
In QLimit stellen wir noch fest, ob der Wert in x oder y größer ist, als die Grafik breit oder hoch, das würde nämlich zu Fehldarstellungen führen. Sollte dies aber der Fall sein, wird einfach die größte mögliche Position an x oder y gegeben. Zum besseren Verständnis löschen Sie einfach diese Funktionen in dem Beispiel und bewegen den Body.
Das ist schon alles.
Ein Schönheitsfehler bleibt. Wenn der Body mit der Maus genommen wird geht die Grafik nicht mit, das werden wir jetzt ändern!
If ev = $20
Repeat
x=HPropPot(0,1)*Peek.w(*Scr\_screen+12)
y=VPropPot(0,2)*Peek.w(*Scr\_screen+14)
x=QLimit (HPropPot(0,1)*(Peek.w(*Scr\_screen+12)-InnerWidth),0,(Peek.w(*Scr\_screen+12)-InnerWidth))
y=QLimit (VPropPot(0,2)*(Peek.w(*Scr\_screen+14)-InnerWidth),0,(Peek.w(*Scr\_screen+14)-InnerHeight))
BitMaptoWindow 1,0,x,y,0,0,InnerWidth,InnerHeight
Until Joyb(0) = 0
End If
[Als Datei in Bin zu finden.]
Durch Ergänzung der $20 Schleife mit einem einfachen "Warten auf Maustaste loslassen" Joyb(0)=0 berechnet das Programm jede Position der Bodys bis der Benutzer die Maustaste losläßt.
Aber Achtung: Wenn der Benutzer die Maus mit Hilfe der Tastatur bewegt, stellt das das Programm nicht fest!
Wir müssen also die Maus abfragen und nicht nur den Port 0 des Amigas. Das geschieht über Intuition bzw. über die IDCMP-Flags (die wir unserem Window mitgeben). Diese Flags bestimmen, ob wir eine Meldung von Intuition bekommen oder nicht. Geben Sie einfach mal am Anfang des Programms "DefaultIDCMP $8" ein. Sie sehen, daß das Programm nun nicht mehr reagiert, also müssen Sie es abbrechen und mit der Esc-Taste beenden.
Der Grund ist, daß WaitEvent jetzt von Intuition nur noch die gedrückte Maustaste empfängt. Daß WaitEvent beim Start Informationen von Intuition erhält, ohne IDCMP-Flags gesetzt zu haben, liegt daran, daß BB2 beim Start die wichtigsten IDCMP-Flags setzt. Den $10 setzt BB2 nicht standardmäßig und deshalb ergänzen wir unser Programm nach dem ";ENDE DER GADGETS" um folgende Zeile:
AddIDCMP $10
Bedeutung: Addiere zu den bestehenden IDCMP-Flags das Mauszeiger- Bewegungsflag hinzu. Alle Flags stehen im BB2-Handbuch bei Windows beschrieben.
Nun Schreiben wir noch in unsere $20 Schleife statt "Until Joyb(0)" einfach "Until WaitEvent <> $10" und das Programm bleibt solange in der Schleife, wie die Maus bewegt wird.
Es gibt noch eine Variante eine Bitmap auf ein Window zu bringen, in diesem Fall wird aber das Fenster fest an die Bitmap gebunden.
- SuperBitmap und Windows
WBStartup
NEWTYPE.screeninfo
id.l
width.l
height.l
_depth.w
overscan.w
autoscroll.w
bmapwidth.l
bmapheight.l
End NEWTYPE
NEWTYPE.WS
_screen.l
End NEWTYPE
NEWTYPE.pt
x.w
y.w
End NEWTYPE
Dim p.pt(20)
WBenchToFront_
WbToScreen 0
FindScreen 0
; Die Gadgets
PropGadget 0,-3,-8,$18000+4+8+64,1,-20,8
PropGadget 0,-14,10,$11000+2+16+128,2,12,-20
; Ende Der Gadgets
*sc.screeninfo=ASLScreenRequest(31)
AddIDCMP $10
If *sc
Dim scrtags.TagItem(8)
col.w=-1
scrtags(0)\ti_Tag=#SA_Left,0
scrtags(1)\ti_Tag=#SA_Top,0
scrtags(2)\ti_Tag=#SA_Width,*sc\width
scrtags(3)\ti_Tag=#SA_Height,*sc\height
scrtags(4)\ti_Tag=#SA_Depth,*sc\_depth
scrtags(5)\ti_Tag=#SA_Overscan,*sc\overscan
scrtags(6)\ti_Tag=#SA_AutoScroll,*sc\autoscroll
scrtags(7)\ti_Tag=#SA_DisplayID,*sc\id
scrtags(8)\ti_Tag=#SA_Pens,&col
ScreenTags 0,"BB2-Kurs von Thomas Krippner",&scrtags(0)
Use Screen 0
*Scr.WS=Addr Screen (0)
FH.w=Peek.w(Peek.l(*Scr\_screen+40)+4)
BitMap 1,Peek.w(*Scr\_screen+12),Peek.w(*Scr\_screen+14),2
Use BitMap 1
For q = 0 To 19
p(q)\x=(Peek.w(*Scr\_screen+12)/2)+Sin(2*q*Pi/20)*((Peek.w(*Scr\_screen+12) /2)-1)
p(q)\y=(Peek.w(*Scr\_screen+14)/2)+Cos(2*q*Pi/20)*((Peek.w(*Scr\_screen+14) /2)-1)
Next q
For q = 0 To 18
For w = q+1 To 19
Line p(q)\x,p(q)\y,p(w)\x,p(w)\y,1
Next w
Next q
Window 0,0,FH+3,Peek.w(*Scr\_screen+12),Peek.w(*Scr\_screen+14)-(FH+3),$1489,"Grafik Beispiel",1,2,0,1
Wi0=ActiveWindow
x=0:y=0
Gosub GGGroesse
PositionSuperBitMap 0,0
Repeat
FlushEvents
ev.l=WaitEvent
If Wi0 = ActiveWindow
If ev=$2
x=HPropPot(0,1)
y=VPropPot(0,2)
Gosub GGGroesse
PutSuperBitMap ; Neu Zeichnen des Windows
End If
If ev = $20
Repeat
x=HPropPot(0,1)*Peek.w(*Scr\_screen+12)
y=VPropPot(0,2)*Peek.w(*Scr\_screen+14)
x=QLimit(HPropPot(0,1)*(Peek.w(*Scr\_screen+12)-InnerWidth),0,(Peek.w(*Scr\_screen+12) -InnerWidth))
y=Qlimit(VPropPot(0,2)*(Peek.w(*Scr\_screen+14)-InnerWidth),0,(Peek.w(*Scr\_screen+14) -InnerHeight))
PositionSuperBitMap x,y
Until WaitEvent <> $10
End If
End If
Until ev = $200
End If
End
.GGGroesse
SetHProp 0,1,x,WindowWidth/Peek.w(*Scr\_screen+12)
SetVProp 0,2,y,WindowHeight/Peek.w(*Scr\_screen+14)
Redraw 0,1
Redraw 0,2
Return
[Als Datei in Bin zu finden.]
Hierbei gilt es zu beachten, daß das Window um den Parameter 1 erweitert wurde. Dies ist die Angabe der Bitmap, es bewirkt außerdem, daß die Flags den Wert $80 enthalten.
Ich habe hier mit Absicht einmal die Werte addiert, um zu demonstrieren, daß dieses auch geht. Die Bitmap muß vor dem Window erstellt werden und das ist meiner Meinung nach der große Nachteil, denn Änderungen werden nur ungern geduldet. Die Parameter zum Befehl PositionSuperBitmap ist die linke oberste Ecke der Grafik, die auf das Window geblittet werden soll.
Es ist eigentlich egal, ob Sie mit Superbitmap oder mit BitmaptoWindow arbeiten. Die Geschwindigkeit ist der Vorteil der Superbitmap und die Flexibilität der Vorteil des BitmapToWindow-Befehls. Auch hier gilt wieder: Experimentieren ist das Beste, was Sie machen können.
Das war es fürs Erste mit dem Thema, mehr davon in Teil 5.
[Soweit 4. Teil. Nummero 5 folgt in AmZeiger-Ausgabe 8.]
![]() |
Inhaltsverzeichnis | ![]() |
| ©`98 Der AmZeiger | ||