1.2 Windows drawing routines: GDI

We will talk about GDI in this section. GDI is the short-form for Graphics Device Interface. All drawings in Windows, including output to screen or printer, are carried out by GDI. In order to perform a drawing operation, you need to acquire a device context. A device context is a Windows data structure containing information about the drawing attributes of a device such as a display or a printer. In this section, I will concentrate on screen drawing.

There are two ways to acquire device context for the display screen. The first one is through BeginPaint()/EndPaint(). The second one is through GetDC()/ReleaseDC().

BeginPaint()/EndPaint() is normally used in processing WM_PAINT message. Please read the following code:

LRESULT CALLBACK WindowProc(
	HWND a_hwnd,		// handle to window
	UINT a_uMsg,		// message identifier
	WPARAM a_wParam,	// first message parameter
	LPARAM a_lParam)	// second message parameter
{
	switch (a_uMsg)
	{
	case WM_PAINT:
		{
			PAINTSTRUCT ps;
			HDC hDC;

			hDC = BeginPaint(a_hwnd, &ps);
			// .. do all drawing here
			EndPaint(a_hwnd, hDC);
		}
		return 0;
	default:
		return DefWindowProc(a_hwnd, a_uMsg, a_wParam, a_lParam);
	}
}

Beside the device context, BeginPaint() filled up a PAINTSTRUCT too. PAINTSTRUCT contains the information for the update region. An update region is set by InvalidateRect() or InvalidateRgn() functions and by some window actions which affected the clinet area. The device context is clipped to exclude any drawing outside the update region. The mechanism provided here is to minimize unnecessary drawing operations since most of the changes are only happened in portion of the client area. Each BeginPaint() must be followed by EndPaint() to release the allocated device context when the drawing operations are finished. EndPaint() will reset the update region of the window automatically. WM_PAINT message is automatically generated if the update region is not NULL. WM_PAINT get a very low priority. Other messages may be processed eariler even those messages are queued up later than when the WM_PAINT message was generated.

GetDC() will return the device context of the client area. The device context is clipped to the whole client area. Each GetDC() must be followed by a corresponding call of ReleaseDC(). GetDC() is normally used if you want the drawing operations are carried out immediately. GetDC()/ReleaseDC() do not touch the update region at all.

Talk about so many about the device context. Let's talk about how to carry out the actual drawing now.

Each DC contains several GDI objects. The objects includes:

When you acquired a DC from either BeginPaint() or GetDC(), there are already one of each kind of the objects in the device context. You can use the supplied objects to do your drawing operations. Or, you can create your object and then call SelectObject() to replace the one in the device context with the one you created. SelectObject() return the handle of the object selected out of the device context. You must store the handle which is come with the acquired DC. Therefore, before you return the allocated DC, you must select the original objects back to the DC. If the created objects are no longer used and they are not selected into any DC, you should call DeleteObject() to get rid of them. Windows only have a limited number of handles for GDI objects and device context. If you did not free them up, Windows will run out of handles and cannot create any more. As a result, the whole system will become very unstable.

I don't want to bother to describe every single functions of how to use the GDI objects. Please download sample2.zip and experiment with it. You can click on '1' to '4' keys to try this demo. Please set the display mode to high color or true color. Otherwise, the bitmap demo will not work. I will tell you the reason in the next section.


Professional Games/Multimedia Programming
Copyright John Wong, 1998
Last revised on Jun 14, 1998

Please send any comments on this web site to [email protected]