5.0 VisualClass Objekte
^5.1 Die VisualClassDie VisualClass ist die Superclass für alle Visual Objekt Klassen. Visual Objekte werden innerhalb eines View-Objekts dargestellt. Sie dienen der komfortablen Ausgabe von Grafik bzw. Text und können auf Maus- und Tastaturereignisse reagieren. Dieser Abschnitt beschreibt die gemeinsamen Eigenschaften aller VisualClass Objekte. Ausnahmen sind explizit erwähnt.In R-BASIC gibt es die folgenden VisualClass Objekte:
MausunterstützungAlle VisualClass-Objekte unterstützten die Behandlung von Mausereignissen. Dazu werden von VisContent, VisObj und BitmapContent die folgende Instancevariablen und Methoden unterstützt. Die Text-Objekte behandeln die Mausereignisse komplett selbständig.
Die Maus-Actionhandler müssen als MouseAction deklariert sein. Eine detaillierte Beschreibung der Arbeit mit der Maus finden Sie im Handbuch "Spezielle Themen", Kapitel 17. Es ist sehr häufig, dass VisualClass-Objekte mit der Maus umgehen müssen. Sie können auch Text und Grafik innerhalb des Maushandlers auf den Schirm ausgeben. Allerdings speichert das VisContent und das VisObj Objekt diese Ausgaben nicht. Nur das BitmapContent Objekt speichert die Grafikausgaben gleichzeitig in der Bitmap.
TastaturhandlingSie können sich in das Tastaturhandling aller VisClass-Objekte, auch der Text-Objekte, einklinken, indem Sie einen Tastaturhandler schreiben. Dazu werden die folgenden Instancevariablen und Actionhandler unterstützt:
Eine ausführliche Beschreibung, wie man einen Tastaturhandler schreibt und was es dabei zu beachten gilt, finden Sie im Handbuch "Spezielle Themen", Kapitel 14. Focus und TargetAlle VisualClass Objekte interagieren mit der Focus- und Target-Hierarchie. Es ist möglich zu überwachen, ob ein VisualClass-Objekt den Focus oder das Target hat, indem man einen Focus- bzw. Target-Handler schreibt. Dazu werden die folgenden Actionhandler und Systemvariablen unterstützt.Für VisObj-Objekte ist wichtig, dass die Tastatureingaben an das Focus-Objekt gehen. Das Beispiel "VisObj Keyboard Demo" verwendet die Focus-Hierarchie um dem Nutzer ein visuelles Feedback zu geben, welches Objekt als letztes angeklickt wurde.
Die Arbeit mit Focus und Target ist etwas für erfahrene Programmierer und nur in wenigen Fällen notwendig. Die notwendigen Details dazu finden Sie in den Kapiteln 12 (Focus und Target) und 13 (Implementieren von Menüs: Bearbeiten, Textgröße und andere) des Handbuchs "Spezielle Themen". Arbeit mit dem ClipboardAlle VisualClass Objekte können mit der Zwischenablage (Clipboard) kommunizieren. Die Methoden ClpTestCopy, ClpTestPaste, ClpCopy und ClpPaste werden unterstützt. Eine detaillierte Beschreibung dieser Methoden finden Sie im Kapitel "Arbeit mit der Zwischenablage" (Kapitel 5 im Handbuch "Spezielle Themen"). Für BitmapContent-Objekte und die Text-Objekte gibt es dabei keine Einschränkungen, bei VisContent und VisObj-Objekten muss der gepufferte Modus aktiv sein (Instancevariable buffered = TRUE). Außerdem müssen Sie die Methode MarkInvalid aufrufen, nachdem Sie eine Grafik mit ClpPaste eingefügt haben, damit sich der visual Tree neu darstellt.5.2 Das BitmapContent^5.2.1 ÜberblickObjekte der Klasse BitmapContent verwalten eine editierbare Bitmap. Bitmaps sind digitalisierte Bilder. Sie bestehen aus einer rechteckigen Anordnung von einzelnen Bildpunkten (Picture Element: Pixel). Jedem Pixel kann eine eigene Farbe zugeordnet werden. In die Bitmaps der Klasse BitmapContent kann Text oder Grafik geschrieben werden. Das BitmapContent-Objekt legt die zugehörige Bitmap automatisch selbst an, so dass sie sofort benutzt werden kann.Einen kompletten Überblick über die weitern Möglichkeiten von R-BASIC, Grafik auszugeben, finden Sie im Kapitel 2.2. Abstammung:
Da BitmapContent Objekte von der VisualClass abstammen, kommen Sie nicht in den generic Tree des Programms. Stattdessen werden die über die Instance-Variable "Content" eines Views mit dem View verbunden. Das View muss aber in den generic Tree des Programms eingebunden werden.
Arbeit mit dem ClipboardBitmapContent Objekte können mit der Zwischenablage (Clipboard) kommunizieren. Die Methoden (Objektanweisungen) ClpTestCopy, ClpTestPaste, ClpCopy und ClpPaste werden unterstützt. Eine detaillierte Beschreibung dieser Methoden finden Sie im Handbuch "Spezielle Themen", Kapitel 5, "Arbeit mit der Zwischenablage". Für BitmapContent Objekte gelten dabei folgende Besonderheiten:
MausunterstützungEs ist sehr häufig, dass ein BitmapContent-Objekt mit der Maus umgehen muss. Da ein BitmapContent-Objekt in Normalfall keine Children hat muss es die Mausereignisse selbst behandeln. BitmapContent-Objekte erben die Fähigkeiten im Umgang mit der Maus vom der VisualClass. Eine detaillierte Beschreibung der Arbeit mit der Maus finden Sie im Handbuch "Spezielle Themen", Kapitel 17.TastaturhandlingBitmapContent-Objekte erben die Fähigkeiten im Umgang mit der Tastatur vom der VisualClass. Eine ausführliche Beschreibung, wie man einen Tastaturhandler schreibt und was es dabei zu beachten gilt, finden Sie im Handbuch "Spezielle Themen", Kapitel 14.Focus und TargetBitmapContent Objekte erben die Fähigkeiten im Umgang mit der Focus- und der Traget-Hierarchie von der VisualClass. In den Kapiteln 12 und 13 des Handbuchs "Spezielle Themen" finden Sie eine detaillierte Darstellung des Umgangs mit Focus und Target. Spezielle Instance-Variablen:
Methoden:
^5.2.2 Grundlegende FunktionenBeispiel UI-Code:Das View "MyView" enthält ein BitmapContent, das eine 320x256 Pixel große True-Color Bitmap darstellt. Es kommuniziert automatisch mit dem BitmapContent "MyBitmap" um seine Größe auf 320x256 Pixel zu setzen, so dass die ganze Bitmap sichtbar ist. "DefaultScreen" stellt das BitmapContent als "Standard-Ausgabe-Objekt" für Grafik- und Textausgaben ein. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
View MyView
vControl = HVC_NO_LARGER_THAN_CONTENT + \
HVC_NO_SMALLER_THAN_CONTENT
hControl = HVC_NO_LARGER_THAN_CONTENT + \
HVC_NO_SMALLER_THAN_CONTENT
Content = MyBitmap
END Object
BitmapContent MyBitmap
bitmapFormat = 320, 256, 24
DefaultScreen
defaultColor = BLACK, LIGHT_CYAN
END Object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
In vielen Fällen wird der im Code oben verwendete Fall (kein Scrolling der Bitmap, kein Zoom) ausreichend sein. Ein BitmapContent ist jedoch ein vollwertiges Content-Objekt und kann daher z.B. auch in einem scrollbaren View dargestellt werden:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
View MyView
hControl = HVC_SCROLLABLE
vControl = HVC_SCROLLABLE
fixedSize = 200, 150
! Kleiner als das Content
Content = MyBitmap
END Object
BitmapContent MyBitmap
bitmapFormat = 320, 256, 24
DefaultScreen
defaultColor = BLACK, LIGHT_CYAN
END Object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bitmapFormatDie Instance-Variable bitmapFormat speichert die Größe, die Farbtiefe und weitere Eigenschaften der Bitmap. R-BASIC unterstützt die Farbtiefen 1 (schwarz/weiß), 8 (256 Farben) und 24 (True Color, 16 Mio. Farben). Die Farbtiefe 4 (16 Farben) wird von R-BASIC nicht unterstützt. Verwenden Sie stattdessen 8 Bit Farbtiefe. Über den Parameter flags können Sie einstellen, ob die Bitmap transparent sein soll ("maskierte" Bitmap) und/oder eine Palette verwenden soll. Masken und Paletten in den nächsten Abschnitten beschrieben.
Syntax UI-Code: bitmapFormat = x, y, n [, flags ]
x: Breite der Bitmap
y: Höhe der Bitmap
n: Farbtiefe (zulässige Werte: 1, 8, 24)
flags: Transparenz und Palette. Siehe Tabelle unten.
Lesen: <numVar> = <obj>.bitmapFormat (0) ' Breite
<numVar> = <obj>.bitmapFormat (1) ' Höhe
<numVar> = <obj>.bitmapFormat (2) ' Farbtiefe
<numVar> = <obj>.bitmapFormat (3) ' flags
Schreiben: <obj>.bitmapFormat = x, y, n [, flags ]
Beispiel UI-Code: siehe oben Für "flags" sind folgende Werte zugelassen:
Wenn Sie im BASIC-Code die Variable bitmapFormat belegen (schreiben), so wird die Bitmap neu angelegt. Alle vorhandenen Informationen (Grafik, Text..) gehen verloren. Die Bitmap darf dabei weiterhin als Content einen Views gesetzt sein, muss es aber nicht. Beispiele BASIC-Code:Lesen der Werte: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM b, h, f as WORD
b = MyBitmap.bitmapFomat (0) ' Breite
h = MyBitmap.bitmapFomat (1) ' Höhe
f = MyBitmap.bitmapFomat (2) ' Farbtiefe
Print "Bitmapgröße:" b; "x"; h; "Pixel, "; f; "Bit pro Pixel"
! z.B. 320 x 256 Pixel, 24 Bit pro Pixel
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Neu anlegen der Bitmap: 800 x 600 Pixel, 256 Farben | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MyBitmap.bitmapFormat = 800, 600, 8 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Hinweis: Das Bitmapobjekt informiert sein View automatisch über seine neue Größe, so dass das View ggf. seine eigene Größe anpassen kann.
defaultColorDie Instance-Variable defaultColor enthält die Farben, die beim Initialisieren der Bitmap (erstmaliges bzw. Neuanlegen der Bitmap) verwendet werden. Außerdem werden sie verwendet, wenn das Objekt zum "Screen" wird. Das tritt auf, wenn das Objekt die Anweisung DefaultScreen im UI-Code enthält oder wenn es der Systemvariablen Screen direkt zugewiesen wird (vergleiche Kapitel 2.3.1 "Die Screen-Variable").BitmapContent-Objekte ohne die Anweisung defaultColor verwenden die Farben "schwarz auf weiß".
Syntax UI-Code: defaultColor = fg, bg
fg: Vordergrund (foreground)
bg: Hintergrund (background)
fg und bg müssen Indexfarben sein.
RGB-Farben sind nicht zulässig.
Lesen: <numVar> = <obj>.defaultColor (0) ' fg
<numVar> = <obj>.defaultColor (1) ' bg
Schreiben: <obj>.defaultColor = fg, bg
Beim Anlegen der Bitmap löscht R-BASIC die Bitmap in der Hintergrundfarbe bg. Wird das zugehörige BitmapContent-Objekt zum Screen setzt R-BASIC die Farben folgendermaßen:
Hintergrundfarbe: bg
Text-, Linien- und Flächenfarbe: fg
Das ist prinzipiell so, als würde automatisch die Anweisung "COLOR fg, bg" ausgeführt.
DefaultScreenDiese Anweisung im UI-Code bewirkt, dass das entsprechende BitmapContent als "Standard-Ausgabe-Objekt" festgelegt wird. Es wird dazu automatisch in der Systemvariablen Screen gespeichert (vergleiche Kapitel 2.3.1 "Die Screen-Variable"). Alle Grafik- oder Textausgaben gehen damit automatisch auf dieses Objekt.Syntax UI-Code: DefaultScreen Beispiel UI-Code: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BitmapContent MyBitmap bitmapFormat = 320, 256, 24 DefaultScreen END Object | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Hinweis für Profis BitmapContent-Objekte sind auch dann voll nutzbar, wenn sie nicht mit einem View verbunden sind, d.h. sie können zum "Screen" gemacht oder als "DefaultScreen" gesetzt werden. Natürlich werden sie dann nicht auf dem Bildschirm erscheinen. Grafik- und Textausgaben gehen dann "im Hintergrund" in die Bitmap und werden sichtbar, sobald das Objekt an ein View gekoppelt wird (z.B. mit der Zuweisung MyView.Content = MyBitmapContent). Insbesondere ist es möglich zwischen zwei BitmapContent Objekten hin- und herzuschalten. Sie können die eine Bitmap im Hintergrund ändern, während die andere sichtbar ist - und dann die Veränderungen mit der Zuweisung MyView.Content = .. auf "einen Schlag" sichtbar machen. ^5.2.3 Erweitere FunktionensuspendDrawParallel zur Bitmap gehen die Grafikausgaben gleichzeitig auf den Bildschirm. Dort wird aber weder das Vorhandensein einer Maske noch die Information, dass eventuell "nur" die Maske bearbeitet wird, berücksichtigt. Auch eine eventuell geänderte Farbpalette (siehe Kapitel 5.2.5) wird nicht berücksichtigt. Das führt zu einem zeitweisen Widerspruch zwischen Darstellung auf dem Bildschirm und der Grafik in der Bitmap. Deswegen sollten Sie, während Sie in eine maskierte Bitmap schreiben (egal ob Maske oder Bitmapdaten), die parallel dazu verlaufende Ausgabe auf den Monitor deaktivieren. Das Gleiche gilt für das Schreiben in eine Bitmap mit geänderter Farbpalette. Für diesen Zweck gibt es die Instancevariable suspendDraw.
Syntax UI-Code: nicht zulässig
Lesen: <numVar> = <Bitmapobj>.suspendDraw
Schreiben: <Bitmapobj>.suspendDraw = TRUE | FALSE
SuspendDraw = TRUE deaktiviert die die gleichzeitige Ausgabe der Grafikbefehle auf den Bildschirm. Sobald suspendDraw wieder auf FALSE gesetzt wird zeichnet sich die Bitmap neu auf den Schirm, so dass die vorgenommenen Änderungen "auf einen Schlag" sichtbar werden. SuspendDraw ist - unabhängig von der Existenz einer Maske oder einer Palette - ebenfalls nützlich, wenn Sie eine große Anzahl von Grafikbefehlen haben, die entweder zu "komischen" Zwischenresultaten führen oder sehr lange dauern. Das zeitweise Abschalten der Ausgabe auf den Schirm beschleunigt natürlich die Zeichenoperationen. Verliert ein Objekt den "Screen" Status (d.h. belegen Sie die Systemvariable Screen neu), so wird die Suspendierung automatisch aufgehoben.
RedrawDie Methode Redraw bewirkt, dass das Objekt die Bitmap neu auf den Bildschirm zeichnet. Der Aufruf der Methode ist notwendig, wenn Sie einen einzelnen Paletteneintrag geändert haben (Methode SetPaletteEntry, siehe Kapitel 5.2.5.2) oder eine Bitmapzeile manuell verändert haben (Methode PeekLine, siehe Kapitel 5.2.6).
Syntax: <obj>.Redraw [drawBackground]
drawBackground: TRUE | FALSE (Default: FALSE)
Beispiel: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DemoBitmap.Redraw DemoBitmap.Redraw TRUE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DrawBackground = TRUE bewirkt, dass sich das zum Objekt gehörende View neu zeichnet bevor das Objekt die Bitmap neu darstellt. Damit wird der Hintergrund gelöscht. DrawBackground = TRUE ist nur erforderlich, wenn die Bitmap eine Maske (Transparenzebene) hat und Sie mit der Methode PeekLine den von der Maske als durchsichtig markierten Bereich geändert haben.
GetBitmapHandleDie Methode GetBitmapHandle liefert das Handle auf die vom BitmapContent verwaltete Bitmap. Das Handle kann zum Beispiel verwendet werden, um die Bitmap in ein anderes Objekt oder einen GString zu zeichnen. Im Kapitel 2.8.6.4 (Bitmaps und Bitmap Handles) des R-BASIC Programmierhandbuchs finden Sie eine Übersicht über die Möglichkeiten der Arbeit mit Bitmaphandles.
Syntax BASIC Code: <han> = <obj>.GetBitmapHandle
<han>: Variable vom Typ Handle
Alle Änderungen, die an der Bitmap im BitmapContent-Objekt gemacht werden wirken sich auf das Handle aus. Insbesondere wird das Handle ungültig, wenn das Objekt seine Bitmap neu anlegt (z.B. die Größe oder die Farbtiefe ändert oder wenn einer der Methoden NewBitmapFromHandle oder ClpPaste aufgerufen werden). Das folgende Codebeispiel zeigt wie man eine Bitmap in eine BMP-Datei schreibt. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB WritToBMPFile( fileName$ as String ) DIM han as HANDLE han = MyBitmap.GetBitmapHandle WriteBitmapToFile(han, fileName$) End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CopyBitmapDie Methode CopyBitmap fertigt eine Kopie des vom BitmapContent verwalteten Bitmap an und liefert das Handle der Kopie. Das Handle kann verwendet werden, um die kopierte Bitmap mit DrawBitmap() zu zeichnen. Im Kapitel 2.8.6.4 (Bitmaps und Bitmap Handles) des R-BASIC Programmierhandbuchs finden Sie eine Übersicht über die Möglichkeiten der Arbeit mit Bitmaphandles.Die mit CopyBitmap erstellte Kopie muss mit FreeBitmap wieder freigegeben werden.
Syntax BASIC Code: <han> = <obj>.CopyBitmap
<han>: Variable vom Typ Handle
Im Gegensatz zu GetBitmapHandle wirken sich Änderungen der Bitmap des Objekts nicht mehr auf die kopierte Bitmap und deren Handle aus. NewBitmapFromHandleDie Methode NewBitmapFromHandle kopiert eine durch ein Handle referenzierte Bitmap in das Objekt. Die alte vom Objekt gespeicherte Bitmap geht verloren. Das Objekt stellt sich anschließend neu dar. Es informiert auch sein View über die neue Größe der Bitmap.
Syntax BASIC Code: <obj>.NewBitmapFromHandle <han>
<han>: Referenz auf die zu kopierende Bitmap
Das folgende Codebeispiel kopiert eine Bitmap von einem Objekt in ein anderes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB CloneBitmap( ) DIM han as HANDLE han = MyBitmap.GetBitmapHandle MyOtherBitmap.NewBitmapFromHandle han End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^5.2.4 Arbeit mit transparenten Bitmaps5.2.4.1 ÜberblickDer Begriff "transparente Bitmap" oder auch "maskierte Bitmap" beschreibt, dass Teile der Bitmap durchsichtig sind, also den Hintergrund nicht verdecken. Man muss sich das so vorstellen, dass die Bitmap außer der eigentlichen Grafik noch eine schwarz-weiß Bitmap gleicher Größe enthält. Diese heißt "Maske" und bestimmt die Transparenz. Weiße Pixel sind durchsichtig, schwarze nicht.
Um eine transparente Bitmap anzulegen muss das Bit 0 (zugehöriger Wert: 1, Konstante BF_MASK) im Parameter "flags" der Instancevariable bitmapFormat gesetzt sein. Der folgende UI-Code definiert eine transparente 8-Bit Bitmap: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BitmapContent DemoBitmap
bitmapFormat = 300, 100, 8, BF_MASK
DefaultScreen
defaultColor = YELLOW, LIGHT_BLUE
END Object
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Beim Anlegen einer transparenten Bitmap wird die Maske vollständig gefüllt, d.h. die Bitmap ist zunächst nicht durchsichtig.
editMaskNormalerweise gehen Grafik- und Textausgaben direkt in die Bitmap und parallel dazu auf den Bildschirm. Die Maske wird dabei nicht verändert. Um die Maske zu beschreiben müssen Sie die Instancevariable editMask auf TRUE setzen.
Syntax UI-Code: nicht zulässig
Lesen: <numVar> = <Bitmapobj>.editMask
Schreiben: <Bitmapobj>.editMask = TRUE | FALSE
Danach gehen alle Zeichenoperationen in die Maske und die "normalen" Bilddaten bleiben unberührt. suspendDrawParallel zur Bitmap gehen die Grafikausgaben gleichzeitig auf den Bildschirm. Dort wird aber das Vorhandensein einer Maske nicht berücksichtigt. Deswegen sollten Sie, während Sie in eine maskierte Bitmap schreiben (egal ob Maske oder Bitmapdaten) die parallel dazu verlaufende Ausgabe auf den Monitor deaktivieren. Für diesen Zweck gibt es die Instancevariable suspendDraw. SuspendDraw = TRUE deaktiviert die die gleichzeitige Ausgabe der Grafikbefehle auf den Bildschirm. Sobald suspendDraw wieder auf FALSE gesetzt wird zeichnet sich die Bitmap neu auf den Schirm, so dass die vorgenommenen Änderungen "auf einen Schlag" sichtbar werden.Wichtige Hinweise
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Paper BG_TRANSPARENT
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^5.2.4.2 Beschreiben der MaskeDa es sich bei der Maske aus Sicht des Systems um eine schwarz-weiß-Bitmap handelt sollten Sie beim Zeichnen in die Maske (editMask = TRUE) nur die Farben Schwarz (macht den Bereich undurchsichtig) oder Weiß (macht den Bereich durchsichtig) verwenden. Flächen in anderer Farbe (nicht aber Linien und Texte) werden entsprechend der Helligkeit der Farbe gerastet.Alternativ zu den Farben kann man das Feld "mixMode" der globalen Variablen "graphic" mit einem passenden Wert belegen. Mehr dazu im 2. Beispiel. Die folgenden Beispiele verwenden die Kommandos ScreenSaveState (speichern aller Grafikdaten wie Farben, Font, mixMode usw.) und ScreenRestoreState (wiederherstellen der gespeicherten Werte). Außerdem wird die fertige Bitmap ins Clipboard kopiert (DemoBitmap.ClpCopy), von wo aus sie in z.B. GeoWrite für dieses Handbuch verwendet werden kann. Der Befehl CLS wirkt - wie alle anderen Grafikbefehle - entweder auf die Bitmapdaten (editMask = FALSE) oder auf die Maske (editMask = TRUE). Ist editMask = TRUE löscht er die Maske immer (alles durchsichtig), egal welche Farbe Sie eingestellt haben. Beispiel: Zeichenoperationen in die Maske | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub InkDemo()
ScreenSaveState ' Grafikdaten sichern
DemoBitmap.suspendDraw = TRUE ' Bildschirm tot legen
DemoBitmap.editMask = TRUE ' Maske editieren
Cls
Ink BLACK
FillEllipse 0, 0, 150, 100
Ink WHITE
FillRect 50, 25, 100, 75
DemoBitmap.editMask = FALSE ' Maske ist fertig
ScreenRestoreState ' Grafikeinstellungen
' wiederherstellen
FillRect 0, 0, 75, 50, GREEN
FillRect 75, 0, 150, 50, RED
FillRect 0, 50, 150, 100, BLUE
FillRect 75, 50, 150, 100, CYAN
DemoBitmap.suspendDraw = FALSE ' alles neu zeichnen
DemoBitmap.ClpCopy
END Sub
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Anmerkung: Da einige Druckertreiber (z.B. Postscript Color) transparente Bitmaps nicht korrekt drucken, wurden alle transparenten Bitmaps in diesem Handbuch zuvor in GeoDraw vor einen Text gelegt und diese Kombination in eine (druckbare) unmaskierte Bitmap konvertiert.
5.2.4.3 Verwendung des MixMode MM_SETNicht immer kann man sicherstellen, dass nur die Farben Schwarz und Weiß verwendet werden, z.B. wenn man einen GString (siehe R-BASIC Programmierhandbuch, Kapitel 2.8.5) in eine maskierte Bitmap schreiben will oder wenn die auszugebende Grafik in einer SUB steckt, die selbst Farben einstellt: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub PaintHouse() ScreenSaveState graphic.linewidth = 5 Ink LIGHT_BLUE FillRect 10, 50, 100, 80 ' das Haus Ink WHITE FillRect 15, 55, 25, 65 ' ein Fenster FillRect 35, 55, 45, 78 ' die Tür FillRect 55, 55, 65, 65 ' ein Fenster FillRect 75, 55, 85, 65 ' ein Fenster Ink LIGHT_GREEN Line 10, 50, 55, 10 ' das Dach Line 55, 10, 100, 50 Ink LIGHT_RED FillEllipse 90, 5, 110, 25 ' die Sonne ScreenRestoreState END Sub | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dazu belegt man das Feld "mixMode" der globalen Variablen "graphic" mit dem passenden Wert. Für uns sind an dieser Stelle die Modes MM_SET, MM_CLEAR und MM_COPY interessant.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Sub MixModeExample() DIM mmSaved DemoBitmap.suspendDraw = TRUE ' Schirmausgabe abschalten Cls ' Bitmapdaten löschen PaintHouse ' Farbige Grafik zeichnen DemoBitmap.editMask = TRUE ' Maske editieren mmSaved = graphic.mixMode graphic.mixMode = MM_SET Cls ' Maske löschen PaintHouse graphic.mixMode = mmSaved ' MixMode restaurieren DemoBitmap.editMask = FALSE ' Maske fertig DemoBitmap.suspendDraw = FALSE ' Alles neu zeichnen DemoBitmap.ClpCopy END Sub | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Beispiel: Das Resultat vom vorherigen Beispiel soll vollständig einfarbig gefärbt werden. Das ist sehr einfach. Wir löschen die Bitmapdaten ohne die Maske zu verändern.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DemoBitmap.suspendDraw = TRUE Paper GREEN CLS DemoBitmap.suspendDraw = FALSE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^5.2.4.4 Zeichnen einer maskierten Bitmap in eine andereWird eine maskierte Bitmap in eine andere Bitmap gezeichnet so werden die Masken natürlich berücksichtigt. Der folgende Code zeichnet eine Bitmap (aus dem Objekt DemoBitmap2) in den Screen DemoBitmap. Weil das Zielobjekt (DemoBitmap) ebenfalls eine maskierte Bitmap enthält setzen wir während der eigentlichen Zeichenanweisung die Instancevariable suspendDraw auf TRUE. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB DoDrawBitmap() DIM h as Handle DemoBitmap.suspendDraw = TRUE h = DemoBitmap2.GetBitmapHandle DrawBitmap h, 0, 0 DemoBitmap.suspendDraw = FALSE End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Das Ergebnis sieht so aus. Die Maske der Zielbitmap wurde nicht verändert.
Tipp: Wir brauchen in diesem speziellen Fall suspendDraw nicht auf TRUE zu setzen, weil wir den undurchsichtigen Teil der Maske ergänzen und genau diesen Bereich mit Grafik füllen, so dass der Bildschirm automatisch auf dem korrekten Stand ist.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB DoDrawBitmap() DIM h as Handle ' hier nicht erforderlich: DemoBitmap.suspendDraw = TRUE h = DemoBitmap2.GetBitmapHandle Drawbitmap h, 0, 0 DemoBitmap.editMask = TRUE graphic.mixMode = MM_SET DrawBitmap h, 0, 0 graphic.mixMode = MM_COPY DemoBitmap.editMask = FALSE ' hier nicht erforderlich: DemoBitmap.suspendDraw = FALSE End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^5.2.5 Arbeit mit Paletten5.2.5.1 ÜberblickUnter GEOS bzw. R-BASIC werden Bitmaps mit folgenden Farbtiefen unterstützt:
Eine Bitmap mit 24 Bit pro Pixel enthält für jedes Pixel 3 Byte, je eines für die Farben Rot, Grün und Blau. Da jedes Byte die Werte 0 bis 255 annehmen kann ergeben sich etwa 16,8 Millionen mögliche Farben. Wenn eine Bitmap weniger als 3 Byte pro Pixel speichert muss das System entscheiden, welche der über 16 Millionen möglichen Farben dargestellt werden sollen. Das wird über eine sogenannte Farbpalette realisiert. Die Palette ist eine Liste von bis zu 256 Einträgen zu je drei Byte - jeweils eins für Rot, Grün und Blau. Der "Farbwert" des Pixels entspricht dann der Nummer (dem sogenannten Index) des Eintrags in der Liste. Die Zählung beginnt dabei immer mit Null. Zur Verwaltung der Palette sind in R-BASIC die folgenden Strukturen definiert: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STRUCT PaletteEntry rt, gn, bl as BYTE End Struct STRUCT FullPalette item[255] as PaletteEntry END Struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
PaletteEntry enthält einen einzelnen Paletteneintrag, FullPalette enthält die vollständige Palette einer 256-Farb-Bitmap. Erlaubte Werte für den Index sind 0 bis 255. Die Palettendaten werden in der GEOS-Bitmap selbst gespeichert. R-BASIC erlaubt den Zugriff auf die Palette und deren Änderung. Wenn die Bitmap keine eigene Palette hat nutzt das System die GEOS-Standard-Palette. Dann kann R-BASIC die Farben nicht ändern.
Um eine Bitmap mit Palette anzulegen muss im vierten Parameter (flags) der Instancevariablen bitmapFormat das Bit 1 (zugehöriger Wert: 2, Konstante BF_PALETTE) gesetzt sein. Das System belegt dann die Palettendaten der Bitmap mit der Standardpalette. Diese Daten können später von R-BASIC aus geändert werden. Das passiert individuell für jede Bitmap, so dass Sie in einem Programm mehrere Bitmaps mit verschiedenen Paletten gleichzeitig anzeigen können. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
' Parameter flags: Transparenz und Palette
bitmapFormat = 640, 480, 8 ' Keine eigene Palette,
' nutzt Standardpalette
bitmapFormat = 640, 480, 8, BF_PALETTE ' Palette
bitmapFormat = 640, 480, 8, BF_PALETTE + BF_MASK
' Palette + Transparenz
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Die Verwendung einer Palette ist nur bei 8-Bit-Bitmaps sinnvoll. R-BASIC unterstützt zwar den Zugriff auf die Palette einer schwarz/weiß Bitmap, das System ignoriert die Palettendaten aber. Es zeichnet monochrome Bitmaps immer in schwarz/weiß.
^5.2.5.2 Zugriff auf die FarbpaletteGetFullPaletteDie Methode GetFullPalette liest die Palette einer Bitmap aus. Enthält die Palette der Bitmap weniger als 256 Einträge werden die restlichen Einträge mit Null belegt. Enthält die Bitmap keine Palette kommt es zu einem Laufzeitfehler.Syntax: <pal> = <obj>.GetFullPalette <pal>: Variable vom Typ FullPalette SetFullPaletteDie Methode SetFullPalette belegt die Palette einer Bitmap. Das Objekt stellt sich automatisch neu dar. Enthält die Palette der Bitmap weniger als 256 Einträge werden die restlichen Einträge ignoriert. Enthält die Bitmap keine Palette kommt es zu einem Laufzeitfehler.Syntax: <obj>.SetFullPalette <pal> <pal>: Variable oder Ausdruck vom Typ FullPalette GetPaletteEntryDie Methode GetPaletteEntry liest einen einzelnen Paletteneintrag einer Bitmap aus. Enthält die Bitmap keine Palette kommt es zu einem Laufzeitfehler.
Syntax: <entry> = <obj>.GetPaletteEntry (index)
<entry>: Variable vom Typ PaletteEntry
index: Index des auszulesenden Paletteneintrags. Es muss gelten
0 <= index < Anzahl der Paletteneinträge der Bitmap,
ansonsten kommt es zu einem Laufzeitfehler.
SetPaletteEntryDie Methode GetPaletteEntry setzt einen einzelnen Paletteneintrag einer Bitmap aus. Das Objekt stellt sich aber nicht automatisch neu dar. Sie müssen dazu die Methode Redraw aufrufen. Enthält die Bitmap keine Palette kommt es zu einem Laufzeitfehler.
Syntax: <obj>.SetPaletteEntry <entry>, index
<entry>: Variable oder Ausdruck vom Typ PaletteEntry
index: Index des auszulesenden Paletteneintrags. Es muss gelten
0 <= index < Anzahl der Paletteneinträge der Bitmap,
ansonsten kommt es zu einem Laufzeitfehler.
Tipp: GetPaletteEntry und SetPaletteEntry laufen nur geringfügig schneller als SetFullPalette und GetFullPalette. Wenn Sie mehrere Paletteneinträge ändern wollen ist deshalb häufig effektiver, die komplette Palette zu holen, die zu ändern und sie dann komplett neu zu setzen. RedrawDie Methode Redraw (ausführliche Beschreibung siehe vorne) bewirkt, dass das Objekt die Bitmap neu auf den Bildschirm zeichnet. Der Aufruf der Methode ist notwendig, wenn Sie einen einzelnen Paletteneintrag geändert haben (Methode SetPaletteEntry).^5.2.5.3 BeispieleDie Farbkonstanten von R-BASIC basieren auf der GEOS Standardpalette. Zum Beispiel hat BLACK den Wert Null, BLUE den Wert 1 und WHITE den Wert 15. Wenn Sie beispielsweise dem Palettenwert mit dem Index 1 die RGB-Werte der Farbe Weiß zuweisen, werden alle Pixel, die den Index 1 haben, nicht mehr blau, sondern weiß dargestellt. Auf diese Weise kann man die Farben einer Bitmap sehr schnell ändern.Der folgende Code ersetzt den Paletteneintrag für die Farbe Schwarz (Index Null) durch einen Grauwert. Die erste Variante liest und setzt die vollständige Palette. Die Methode SetFullPalette zeichnet die Bitmap automatisch neu. In der zweiten Variante lesen und schreiben wir genau einen Paletteneintrag. Weil SetPaletteEntry die Bitmap nicht neu zeichnet müssen wir die Methode Redraw aufrufen. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB ModifyBlack() DIM pal as FullPalette pal = DemoBitmap.GetFullPalette pal.item(0).rt = 120 pal.item(0).gn = 120 pal.item(0).bl = 120 DemoBitmap.SetFullPalette pal End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB ModifyBlack2() DIM pe as PaletteEntry pe = DemoBitmap.GetPaletteEntry (0) pe.rt = 120 pe.gn = 120 pe.bl = 120 DemoBitmap.SetPaletteEntry pe, 0 DemoBitmap.Redraw End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Der folgende Code senkt alle Farbwerte der Palette auf 80% ab. Dadurch wird das Bild deutlich dunkler. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB MakeDarker()
DIM pal AS FullPalette
DIM n
pal = DemoBitmap.GetFullPalette
FOR n = 0 TO 255
' Rot, Grün und Blauwert verringern
pal.item(n).rt = 0.8 * pal.item(n).rt
pal.item(n).gn = 0.8 * pal.item(n).gn
pal.item(n).bl = 0.8 * pal.item(n).bl
NEXT n
DemoBitmap.SetFullPalette pal
End Sub
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Das folgende Beispiel tauscht die Palettenwerte für die Farben Blau und Weiß. Alles was bisher weiß war erscheint dann blau und umgekehrt. Die erste Variante verwendet die Methoden GetPaletteEntry und SetPaletteEntry. Deswegen ist der Aufruf der Methode Redraw erforderlich. Variante Zwei liest und schreibt die vollständige Palette. Der Aufruf von SetFullPalette stellt die Bitmap automatisch mit den geänderten Farben dar. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB SwitchColors() DIM pe1, pe2 AS PaletteEntry ' originale Palettenwerte holen pe1 = DemoBitmap.GetPaletteEntry(WHITE) pe2 = DemoBitmap.GetPaletteEntry(LIGHT_BLUE) ' Jeweils dem anderen Farbwert zuweisen DemoBitmap.SetPaletteEntry(pe1, LIGHT_BLUE) DemoBitmap.SetPaletteEntry(pe2, WHITE) ' Objekt neu zeichnen. Das passiert nicht automatisch! DemoBitmap.Redraw End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB SwitchColors2() DIM pal as FullPalette DIM pe AS PaletteEntry pal = DemoBitmap.GetFullPalette pe = pal.item(WHITE) pal.item(WHITE) = pal.item(LIGHT_BLUE) pal.item(LIGHT_BLUE) = pe DemoBitmap.SetFullPalette pal End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Betrachten wir nun den folgenden Code. Wenn wir ihn ausführen nachdem wir die SUB SwitchColors aufgerufen haben, sollte eine weiße Line erscheinen, weil dem Index der Farbe Blau (LIGHT_BLUE) jetzt die RGB-Werte der Farbe Weiß zugeordnet sind. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Line 10, 10, 200, 200, LIGHT_BLUE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Wir sehen jedoch eine blaue Linie. Erst wenn wir das Fenster mit der Bitmap auf dem Schirm verschieben (und sich die Bitmap deswegen neu zeichnen muss) wird die Linie weiß. Warum? Jeder Grafikbefehl (auch Textausgaben) gehen nicht nur in die Bitmap, sondern parallel dazu auch direkt auf den Schirm. Bei der Ausgabe auf den Schirm wird die geänderte Palette aber nicht berücksichtigt, sie ist nur der Bitmap bekannt. Deswegen sollten sie während der Ausgabe von Grafik und Text in eine Bitmap mit geänderter Palette die parallele Ausgabe auf den Bildschirm abschalten. Für diesen Zweck gibt es die Instancevariable suspendDraw. Der folgende Code erzeugt sofort gewünschte weiße Linie: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DemoBitmap.suspendDraw = TRUE Line 10, 10, 200, 200, LIGHT_BLUE ' <hier weitere Grafik- und Textausgaben> DemoBitmap.suspendDraw = FALSE | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
DemoBitmap.suspendDraw = TRUE schaltet die parallele Ausgabe der Grafik auf den Schirm ab. Die Bitmap wird unsichtbar im Hintergrund beschrieben. DemoBitmap.suspendDraw = FALSE hebt die Suspendierung auf und zeichnet die Bitmap neu auf den Schirm, so dass alle Änderungen sichtbar werden.
Eine ähnliche Situation tritt auf, wenn wir eine Bitmap in eine andere Bitmap zeichnen, falls die Paletten nicht übereinstimmen. Oder wir zeichnen eine RGB-Grafik (Bitmap oder Grafikbefehl) in die 8-Bit Bitmap. Das System ersetzt dann die nicht in der Palette befindlichen Farben durch "ähnliche" Farben, die in der Palette der Zielbitmap vorhanden sind. Auf dem Schirm erscheinen jedoch die originalen Farben. Auch hier sollten wir suspendDraw einsetzen. Der folgende Code geht davon aus, dass DemoBitmap1 der Screen ist. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SUB CopyBitmap2ToScreen DIM h as Handle DemoBitmap1.suspendDraw = TRUE h = DemoBitmap2.GetBitmapHandle DrawBitmap h, 10, 20 ' Handle, Koordinaten DemoBitmap1.suspendDraw = FALSE End SUB | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
^5.2.6 Direktzugriff auf die BitmapdatenEs ist möglich, auf die einzelnen Pixelzeilen einer Bitmapgrafik direkt zuzugreifen. Dazu kann man mit der Methode PokeLine eine komplette Grafikzeile in den virtuelle RAM schreiben, dort die einzelnen Pixel modifizieren und die Zeile dann mit der Methode PeekLine zurück in die Bitmap kopieren. Insbesondere ist es auf diese Weise möglich, die Maskendaten einer 24-bit Bitmap zu ändern. Man sollte sich jedoch der Tatsache bewusst sein, dass die Manipulation von einigen Tausend Pixeln sehr lange dauern kann.PokeLineDie Methode PokeLine kopiert eine komplette Pixelzeile aus der Bitmap in den virtuellen R-BASIC RAM. Falls die Bitmap eine Maske enthält werden die zur Zeile gehörenden Maskendaten ebenfalls kopiert.
Syntax: <obj>.PokeLine adr, line
adr: Adresse im virtuellen RAM (0 ... 65535)
Es werden so viele Bytes geschrieben wie die Zeile enthält
line: Zeilennummer der in den RAM zu schreibenden Zeile
Erlaubte Werte: 0 .. Höhe - 1
PeekLineDie Methode PeekLine kopiert eine komplette Pixelzeile aus dem virtuellen R-BASIC-RAM in die Bitmap des Objekts. Falls die Bitmap eine Maske enthält werden die zur Zeile gehörenden Maskendaten ebenfalls überschrieben. Die Bitmap stellt sich nicht neu dar, Sie müssen dazu die Methode Redraw aufrufen.
Syntax: <obj>.PeekLine adr, line
adr: Adresse im virtuellen RAM (0 ... 65535)
Es werden so viele Bytes aus dem RAM gelesen,
wie die Zeile fasst.
line: Zeilennummer der zu beschreibenden Bitmap-Zeile
Erlaubte Werte: 0 .. Höhe - 1
Beispiel: Der folgende Code kopiert die die ersten 50 Zeilen einer Bitmap in die Zeilen 100 bis 149. Die Adresse im virtuellen RAM ist egal, deswegen wählen wir Adresse 0. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM n FOR n = 0 TO 49 DemoBitmap.PokeLine 0, n DemoBitmap.PeekLine 0, 100+n NEXT n DemoBitmap.Redraw | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RedrawDie Methode Redraw (ausführliche Beschreibung siehe vorne) bewirkt, dass das Objekt die Bitmap neu auf den Bildschirm zeichnet. Der Aufruf der Methode ist notwendig, wenn Sie eine Bitmapzeile manuell verändert haben (Methode PeekLine). Falls die Bitmap eine Maske (Transparenzebene) hat und Sie mit der Methode PeekLine den von der Maske als durchsichtig markierten Bereich geändert haben müssen Sie Redraw mit dem Parameter TRUE aufrufen, damit der Hintergrund der Bitmap neu dargestellt wird und die geänderte Maske erkennbar wird.Aufbau der Bitmapdaten
Um die Pixelzeilen bearbeiten zu können müssen Sie die Struktur der Bitmapdaten kennen. Wir nehmen zunächst an, dass die Bitmap keine Maske hat. Je nach Farbtiefe wird eine unterschiedliche Anzahl von Bits für ein Pixel benötigt. Daraus ergibt sich die Anzahl der Bytes für eine Pixelzeile.
Grundsätzlich liegen die in der Zeile links liegenden Pixel auf den niedrigen Adressen im virtuellen RAM. Bei monochromen Bitmaps liegt das ganz linke Pixel auf dem höchstwertigen Bit des Bytes. True-Color Bitmaps speichern die Farbwerte in der Reihenfolge Rot-Grün-Blau. Daraus ergeben sich die folgenden Zusammenhänge. In den Bildern bezeichnet "adr" Adresse "adr", die an die Methoden PeekLine bzw. PokeLine übergeben wurde. Monochrome Bitmap:Bit 7 ist das höherwertigste Bit, Bit 0 ist das niederwertigste Bit.
256 Farben Bitmap:
True Color Bitmap:
Aufbau der Bitmapdaten mit MaskeWenn die Bitmap eine Maske hat sind die Maskendaten für jede Zeile direkt vor den Grafikdaten der Zeile angeordnet. Der Aufbau der Maskendaten entspricht dem einer monochromen Bitmap. Ein gesetztes Bit bedeutet, dass die Grafikdaten des Pixels dargestellt werden sollen. Ist das Bit nicht gesetzt (also Null) ist das Pixel transparent. Die Größe der Maskendaten (Anzahl der Bytes) berechnet sich zu:maskLen = INT ( (breite+7) / 8 )Die Methoden PokeLine und PeekLine kopieren jeweils sowohl die Maskendaten als auch die Grafikdaten.
Das folgende Codefragment belegt die Maskendaten einer Bitmap mit dem Bitmuster 00001111 (= 15 dezimal). Dadurch erscheint die Grafik gestreift. Die Farbtiefe der Grafik spielt dabei keine Rolle, da sie die Größe der Maskendaten nicht beeinflusst.
Hinweis: Je nachdem, welche Grafikdaten die Maske vorher verdeckt hat kann das linke oder das rechte Bild entstehen. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM width, height, x, y, masklen
width = DemoBitmap.bitmapformat(0)
height = DemoBitmap.bitmapformat(1)
maskLen = INT ( (width+7)/8)
FOR y = 0 TO height-1
DemoBitmap.PokeLine 0, y
FOR x = 0 TO maskLen - 1
Poke x, 15 ' &B00001111
NEXT x
DemoBitmap.PeekLine 0, y
NEXT y
DemoBitmap.Redraw
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Ein etwas komplexeres BeispielDie Tatsache, dass das Format der Maskendaten identisch mit dem einer monochromen Bitmap ist ermöglich es, auf relativ einfache Weise die Maske einer 24 Bit Bitmap zu bearbeiten. Das System unterstützt das leider nicht.Nehmen wir an, wir haben eine 24 Bit Bitmap der Größe 256 x 192 Pixel, die eine Maske enthält (Objekt DemoBitmap). Die Idee hinter dem folgenden Code ist, eine ebenso große monochrome Bitmap ohne (!) Maske (DemoBitmap2) zu verwenden, diese mit Grafikbefehlen zu bearbeiten und dann die Daten der monochromen Bitmap in die Maske der 24 Bit Bitmap zu kopieren. Dieses Vorgehen setzt voraus, dass beide Bitmaps exakt die gleichen Abmessungen haben. Der folgende Code bearbeitet zunächst die monochromen Bitmap. Weiße Pixel werden später transparent, schwarze Pixel werden undurchsichtig. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Screen = DemoBitmap2 Paper WHITE Cls ' komplett transparent FillEllipse 64, 32, 192, 160, Black FillRect 32, 64, 224, 128, Black | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Nun holen wir uns jede einzelne Pixelzeile der 24 Bit Bitmap in den virtuellen RAM und kopieren die Daten der monochromen Bitmap an die gleiche Stelle. Weil beide Bitmaps die gleiche Größe haben werden damit nur die Maskendaten der 24 Bit Bitmap überschrieben. Dann kopieren wir die geänderte Pixelzeile zurück in die 24 Bit Bitmap. Abschießend rufen wir die Redraw-Methode mit dem Parameter TRUE auf um die Änderungen sichtbar zu machen. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIM x, y, maskLen
maskLen = INT ((256+7)/8)
FOR y = 0 TO 191
DemoBitmap.PokeLine 0, y
DemoBitmap2.PokeLine 0, y
DemoBitmap.PeekLine 0, y
NEXT y
DemoBitmap.Redraw TRUE
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Dieser Code erzeugt aus dem linken das rechte Bild.
Hinweis: Um Speicherplatz zu sparen wurden die Grafiken für dieses Handbuch auf 8 Bit heruntergerechnet und etwas verkleinert.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||