Bitmaps auf Bitmaps zeichnen (Stichwort Double Buffering)
-
Ich hab ein kleines Programm, das mir zwei Bilder auf ein Fenster zeichnet:
class MainForm : Form { private Bitmap Background = new Bitmap("Background.bmp"); private Bitmap Foreground = new Bitmap("Foreground.bmp"); public MainForm() { Paint += new PaintEventHandler(MainForm_Paint); } private void MainForm_Paint(object sender, PaintEventArgs e) { Graphics graphics = CreateGraphics(); graphics.DrawImage(Background, 0, 0); graphics.DrawImage(Foreground, 0, 0); } }
Und wie wir ja alle wissen: Wenn auf dem Fenster noch ein paar mehr Bilder wären oder wenn sich das Vordergrundbild bewegen und ich das Fenster deshalb zyklisch aktualisieren würde, würde das ganze flackern. Deshalb wollte ich gerne ein Zwischenbild (Back Buffer) erstellen, auf das erstmal alle anderen Bilder raufgemalt werden. Und nur dieses Zwischenbild wird am Ende auf dem Fenster ausgegeben. Ungefähr so:
class MainForm : Form { private Bitmap BackBuffer = new Bitmap(200, 200); private Bitmap Background = new Bitmap("Background.bmp"); private Bitmap Foreground = new Bitmap("Foreground.bmp"); public MainForm() { Paint += new PaintEventHandler(MainForm_Paint); } private void MainForm_Paint(object sender, PaintEventArgs e) { BackBuffer.DrawImage(Background, 0, 0); BackBuffer.DrawImage(Foreground, 0, 0); Graphics graphics = CreateGraphics(); graphics.DrawImage(BackBuffer, 0, 0); } }
Nun wird nur noch ein einzelnes Bild auf das Fenster gezeichnet und tadaaa: Kein Flackern mehr. Das Problem dabei: Die Bitmap-Klasse besitzt keine Funktion DrawImage. Was muss ich also tun, um eine Bitmap auf eine andere zu zeichnen?
-
wirf mal bitte einen Blick auf die statischen Methoden der Klasse Graphics - da wirst Du fündig
-
Danke, ich hab's hingekriegt:
using (Graphics backBufferGraphics = Graphics.FromImage(BackBuffer)) { backBufferGraphics.DrawImage(Background, 0, 0); backBufferGraphics.DrawImage(Foreground, 0, 0); } e.Graphics.DrawImage(BackBuffer, 0, 0);
Noch eine zusätzliche Frage: Sollte man die Bitmap-Variablen manuell disposen? Ich hab mal irgendwas gehört, dass diese Grafikressourcen nur begrenzt zur Verfügung stehen oder so. Allerdings weiß ich nicht, ob sich das auch auf die normalen Bitmap-Variablen oder nur auf Graphics-Objekte bezieht. In der WinAPI konnte man ja zum Beispiel nahezu beliebig viele HBITMAPs haben, aber man sollte die HDCs sparsam, möglichst lokal, einsetzen. Wie ist das hier in .NET? Die Graphics-Objekte werden ja sowieso nur lokal erstellt und die kann ich mit using benutzen, da werden sie automatisch disposet. Aber muss ich bei den Bitmaps nach dem Benutzen auch Dispose() aufrufen oder ist es da unkritisch, irgendwann den Garbage Collector drüberlaufen zu lassen?