Tutorial: Double Buffering using GDI BitBlt

qmp

Newcomer
Joined
May 23, 2005
With help from this forum I was able to figure out the double buffer solution using gdi32s BitBlt in C#.net.

GDI+ is well known for its lack of speed in the performance arena.

To solve the "flicker" solution, and add a fast back buffer to my application, i dipped back into gdi32.

What youll want to do is this..

On your form, create a picturebox that will show your live drawing. Lets call it picChart.

Now, what we need to do is create a back buffer for our picChart.
C#:
private Bitmap memBmp;	// Backbuffers bitmap
private IntPtr hMemBmp;	// Handle to our memBmp
private Graphics memDC;	// We draw on this
private IntPtr hMemdc;	// Handle to our memDC
private void picChart_Resize(object sender, EventArgs e)
{
	// If we have already created a dc for mem, lets free it up first
	if (hMemdc.ToInt32() != 0)
	{
		// Clean up
		DeleteObject(hMemBmp);
		DeleteDC(hMemdc);
		memBmp.Dispose();
	}

	// Resize our backbuffer
	memBmp = new Bitmap(picChart.Width, picChart.Height, System.Drawing.Imaging.PixelFormat.Format16bppRgb555 );
	Graphics clientDC = picChart.CreateGraphics();

	IntPtr hdc = clientDC.GetHdc();
	hMemdc = CreateCompatibleDC(hdc);	// hMemdc is the handle to our memDC
	hMemBmp = memBmp.GetHbitmap();
	SelectObject(hMemdc, hMemBmp);
	memDC = Graphics.FromHdc(hMemdc);	// We draw on memDC

	// Clean up
	clientDC.ReleaseHdc(hdc);
	clientDC.Dispose();
}

private void picChart_Paint(object sender, PaintEventArgs e)
{
	// Copy Region from memDC
	IntPtr hdc = e.Graphics.GetHdc();

	BitBlt(hdc, e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height, hMemdc, e.ClipRectangle.X, e.ClipRectangle.Y, 0x00CC0020);

	e.Graphics.ReleaseHdc(hdc);
}

What the above code does is create a backbuffer the same size of our picChart every time the picChart is resized. If we have already created a backbuffer from a previous resize event, we delete the previous backbuffer from memory.

Then in the picChart paint event, we will bitblt the exact region that was invalidated to our main picChart paint area.

Also, in your form/controls dispose() method you will need to add:
C#:
	// If we have already created a dc for mem, lets free it up first
	if (hMemdc.ToInt32() != 0)
	{
		// Clean up
		DeleteObject(hMemBmp);
		DeleteDC(hMemdc);
		memBmp.Dispose();
	}

That will free up your backbuffer if it was created before the form/control disposes.


To draw on your backbuffer, all you have to use is memDC.Drawxxx to draw whatever you like.

It still uses GDI+ drawing techniques but will use the faster gdi32 bitblt to doublebuffer and repaint your form.

Hope this helps.
 
Last edited by a moderator:
Top