Scrollende Animationen erstellen
Einleitung
Microsoft Visual Basic bietet keine einfachen Möglichkeiten, Text und Grafik zu scrollen, um damit eine einfache Animation zu erstellen. Diese Form von Animationen ist interessant für folgende Zwecke:
In Informationsdialogen werden vertikale Scroller verwendet, um Danksagungen anzuzeigen. Es werden z. B. die Namen der Programmierer geordnet in Sparten angezeigt, die am Projekt mitgewirkt haben. Bereits hier scheitert die Label-Methode, da in einem Label der gesamte Text die gleiche Farbe, Schrift, Ausrichtung und Zeichenformatierung besitzt.
Darstellen von Information, die größer ist, als die zur Verfügung stehende Darstellungsfläche. Eine Kombination mit grafischen Inhalten ist denkbar.
Scrollende Animationen sind oft Bestandteil moderner Multimediaoberflächen.
Es wäre möglich, ein Label-Steuerelement mit transparentem Hintergrund, das den zu scrollenden Text enthält, mit einem Timer über eine Hintergrundgrafik zu bewegen, allerdings tritt bei dieser Methode ein unschönes Flackern des Label-Steuerelements auf. Derselbe Effekt ist auch bei der Verwendung des Image-Steuerelement zu bemerken, das eine transparente Grafik enthalten kann. Daher muß man eine Lösung über das Windows-API suchen.
Ein einfaches Beispiel
Eine gute Möglichkeit bieten die Funktionen aus der GDI-Schnittstelle des Systems. Diese API-Funktionen sind unter 32-Bit-Windows in der gdi32.dll
implementiert, seit Windows 98 bzw. Windows 2000 stellt das System auch die msimg32.dll
zur Verfügung, die als Ergänzung zur gdi32.dll
gedacht ist. So war es beispielsweise mit herkömmlichen GDI-API-Funktionen nur schwer möglich, transparente Grafiken auf einen Gerätekontext zu blitten. Dazu wird von der msimg32.dll
die Funktion TransparentBlt
zur Verfügung gestellt; zudem finden sich in dieser DLL z. B. auch Funktionen zum Zeichnen von Farbverläufen und zum Überblenden zweier Gerätekontexte.
Wie oben beschrieben, wäre es möglich, die TransparentBlt
API-Funktion aus der msimg32.dll
zu verwenden, um den transparenten Text in einer Grafik über den Hintergrund zu blitten. Das Problem dabei ist, daß diese Funktion nur auf neueren Betriebssystemversionen vorhanden ist und daher separater Code für frühere Versionen geschrieben werden müßte (inklusive eines Versionsüberprüfungen). Das Mitausliefern der msimg32.dll
ist aus lizenzrechtlichen Gründen problematisch.
Die Prozedur TransBlt
Aus oben genannten Gründen wollen wir eine eigene Prozedur entwickeln, die eine Grafik transparent über eine andere legen kann. Die Implementierung der Prozedur TransBlt
stützt sich auf die API-Funktion BitBlt
aus der gdi32.dll
. Diese Prozedur maskiert die Vordergrundbitmap in einem Speichergerätekontext (ein Gerätekontext, der nicht angezeigt wird, sondern nur im Arbeitsspeicher angelegt wird, um eine Bitmap zu speichern bzw. Grafikoperationen auf diesen Gerätekontext anzuwenden). Wenn Grafikoperationen auf einen Speichergerätekontext angewendet werden, sind diese etwas schneller als wenn sie auf einen sichtbaren Gerätekontext angewendet werden würden) und erstellt dann eine transparente Bitmap, die anschließend über den Ziel-Gerätekontext geblittet wird.
Die folgende Abbildung zeigt das fertige Programm, wobei der Text als Grafik gespeichert ist und mit der Prozedur TransBlt
über den „Sternenhimmel“ gezeichnet wird:
Damit diese Funktion (wie auch die anderen GDI-Funktionen) funktioniert, muß die ScaleMode
-Eigenschaft von Quell- und Zielobjekt auf vbPixels
eingestellt und die AutoRedraw
-Eigenschaft auf True
gesetzt werden. Folgendes Listing zeigt den Prozedurkopf von TransBlt
. Wie an den Parametern erkennbar ist, unterscheidet sich diese Prozedur von der API-Funktion TransparentBlt
nur dadurch, daß die Breite und Höhe auf dem Quell-Gerätekontext nicht angegeben werden muß. Da es sich um eine Sub
-Prozedur handelt, wird auch kein Wert zurückgegeben, der über den Erfolg des Funktionsaufrufs Aufschluß gibt:
Auf langsamen Rechnern ist die Verwendung eines Timer-Steuerement als Zeitgeber nicht nötig, da die TransBlt
-Prozedur das System kurzzeitig „blockiert“ und dadurch die Anzeige verzögert. Außerdem wird bei jedem Schleifendurchlauf DoEvents
aufgerufen, damit die Ereignisse des Formulars weiterhin abgearbeitet werden. Auf moderneren Rechnern ist es jedoch unumgänglich, das Neuzeichnen alle Millisekunden durchzuführen, da sonst die Geschwindigkeit der Animation zu schnell sein kann. Nachstehendes Listing zeigt die Deklaration der API-Funktion TransparentBlt
:
Der Algorithmus
Im hier beschriebenen Beispiel wird ein Text mit Grafikelementen transparent von oben nach unten über eine Hintergrundgrafik bewegt. Die Hintergrundgrafik stellt einen Sternenhimmel dar, beim „Text“ handelt es sich um Informationen zu einer Anwendung. Der Text ist als Bitmap abgelegt, damit auch Grafikelemente angezeigt werden können:
Bevor der transparente Vordergrund geblittet wird, wird der Inhalt der Ziel-PictureBox geleert und ein neuer Hintergrund geblittet. Dies ist einerseits notwendig, um die bereits vorhandene Anzeige zu löschen, andererseits wird in diesem Beispiel alle 40 Schleifendurchläufe (d. h., wenn die Vertikalposition auf der Quellbitmap um 40 Pixel nach unten verschoben wurde) das Hintergrundbild gewechselt, wodurch die Sterne am Himmel „flackern“. Obige Grafik stellt den verwendeten Algorithmus dar, bei dessen Ablauf zwischen folgenden 3 Fällen unterschieden werden kann:
- Fall 1:
In diesem Fall wird der Teil der Grafik von der Vertikalposition 0 bis 0 plus die Höhe des Zielbereichs transparent auf den Gerätekontext der Ziel-PictureBox geblittet.
- Fall 2:
Die Vertikalposition wird entlang des blauen Pfeils bei jedem Schleifendurchlauf inkrementiert, wodurch der aktuell geblittete Bereich auf der Quellbitmap nach unten wandert.
- Fall 3:
Wird die Vertikalposition plus der Höhe des Zielbereichs größer als die Höhe des Quellbereichs, so muß zuerst der Bereich von der aktuellen Vertikalposition mit der Höhe, die sich aus der Gesamthöhe der Quellbitmap minus die aktuelle Vertikalposition ergibt geblittet werden und anschließend der Bereich von der Vertikalposition 0 bis mit der Höhe (aktuelle Position plus Höhe des Zielbereichs minus die Gesamthöhe der Quellbitmap) auf dem Zielobjekt an der Vertikalposition, die der Höhe des Bereichs, der zuerst geblittet wurde, entspricht.
Eine andere Sichtweise ist die Folgende: Die Grafik, die über den Hintergrund bewegt wird, ist ein Band, das sich dauernd in eine Richtung bewegt. Der Betrachter sieht dann nur einen Ausschnitt aus diesem Band. Die nächste Abbildung zeigt das Sichtfenster des Benutzers sowie das Band, das hier aus Gründen des leichteren Nachvollziehens auf Rollen geführt wird:
Durch diesen Algorithmus wird nach dem Abspielen der gesamten Quellbitmap erneut die Quellbitmap abgespielt, was einem schleifenartigen Durchlauf gleicht. Dies ist in der vorigen Abbildung dargestellt. Folgende Grafiken zeigen das Anzeigeresultat zu den in der Skizze beschriebenen Zuständen, die Grafik am Seitenanfang zeigt ein Beispiel für Fall 1:
Die obenstehende Abbildung zeigt ein Beispiel für den Fall, daß ein zusammenhängender Ausschnitt aus der Vordergrundbitmap zu sehen ist. Bei der nächsten Abbildung handelt es sich um ein Beispiel für Fall 3, da sowohl ein Stück vom oberen als auch dem unteren Ende der Vordergrundbitmap angezeigt werden:
Um die Animation horizontal ablaufen zu lassen, müssen eine entsprechende Grafik erstellt und im Algorithmus - und -Koordinaten vertauscht werden.
Schlußwort
Das vorgestellte Beispiel entstand auf mehrere Anfragen, die an mich herangetragen wurden und ist prinzipiell an Programmiereinsteiger gerichtet. Um eine Grafik transparent über eine andere zu legen, müssen nicht unbedingt API-Funktionen verwendet werden, sondern dies kann auch über einige Umwege mit der Methode PaintPicture
getan werden. Ferner sollte bedacht werden, daß sich ein gutes Programm nicht durch grafische Spielereien auszeichnet, sondern durch eine praktische Benutzerführung und möglichst breiter Unterstützung durch verschiedene Systeme. Selbst wenn mittlerweile die meisten Computerbenutzer über Hardware, die mehr als 256 Farben darstellen kann, verfügen, sollten auch jene Benutzer bedacht werden, bei denen dies nicht der Fall ist.
Downloads
- Beispielprojekt (
CreditsScroller.zip
) Projekt im Visual-Basic-6.0-Format.