Double buffering with a back buffer in VC++

A common problem when drawing with GDI in VC++ is that the screen might flicker when you’re doing a lot of drawing. This problem can be overcome by drawing on a so called back buffer. The back buffer is then drawn at once.

I’ve created a Win32 project in VC++ to demonstrate this. The first example draws a rectangle on the screen without using a back buffer. This illustrates the flickering. The second example draws the rectangle on the back buffer and displays it on the screen.

Drawing a rectangle without using a back buffer

A brush has been created within the WndProc function for drawing the rectangle.

HBRUSH hRectangleBrush = CreateSolidBrush(RGB(0,0,0));

The WM_PAINT case statement has been modified to draw the rectangle.

	case WM_PAINT:
		// Get the device context
		hdc = BeginPaint(hWnd, &ps);

		// Select the rectangle brush
		SelectObject(hdc,hRectangleBrush);

		// Draw the rectangle
		Rectangle(hdc,0,0,20,20);

		// Repaint the screen
		InvalidateRect(hWnd,NULL,true);

		EndPaint(hWnd, &ps);
		break;

 

The picture below illustrates the rectangle being drawn when you run the program.

Rectangle

Flickering should occur and this is unwanted if you would like to have smooth graphics.

Drawing a rectangle using a back buffer

The following global variables are defined.

RECT rect; // Struct for the window width and height
HDC hdc; // Device context
HDC hdcBackBuffer; // Back buffer device context
HBRUSH hRectangleBrush = CreateSolidBrush(RGB(0,0,0)); // Rectangle brush
int width, height; // Window width and height
HBITMAP hBitmap; // Bitmap

WndProc additionally contains a WM_CREATE case statement and WM_PAINT has been modified.

		case WM_CREATE:
			// Get the width and height of the window
			GetClientRect(hWnd,&rect);
			width = rect.right;
			height = rect.bottom;

			// Create the back buffer
			hdcBackBuffer = CreateCompatibleDC(NULL);

			// Get the device context
			hdc = GetDC(hWnd);

			// Create a bitmap
			hBitmap = CreateCompatibleBitmap(hdc, width, height);

			// Select the bitmap
			SelectObject(hdcBackBuffer, hBitmap);

			ReleaseDC(hWnd, hdc);
		break;
	case WM_PAINT:
		// Get the device context
		hdc = BeginPaint(hWnd, &ps);

		BitBlt(hdcBackBuffer,0,0,width,height, NULL, NULL, NULL, WHITENESS);

		// Select the rectangle brush
		SelectObject(hdcBackBuffer,hRectangleBrush);

		// Draw the rectangle on the back buffer
		Rectangle(hdcBackBuffer,0,0,20,20);

		// Display the back buffer
		BitBlt(hdc, 0, 0, width, height, hdcBackBuffer, 0, 0, SRCCOPY);

		// Repaint the screen
		InvalidateRect(hWnd,NULL,false);

		EndPaint(hWnd, &ps);
		break;

Drawing should now be done on the back buffer and the back buffer should in turn be displayed on the screen as a bitmap. Moving the rectangle at a certain interval should also demonstrate that there is no flickering.

You may download the VS 2010 project from here.

This entry was posted in C++ and tagged , , , , , , , , , , , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Why ask?