Getting the Handle to the Device Context

Windows provides several methods for obtaining a device context handle. If you obtain a device context handle while processing a message, you should release it (or delete it) before exiting the window function. After you release the handle, it is no longer valid.

The most common method for obtaining and then releasing a device context handle involves using the BeginPaint and EndPaint calls when processing the WM_PAINT message:

hdc = BeginPaint (hwnd, &ps) ;

[other program lines]

EndPaint (hwnd, &ps) ;

The variable ps is a structure of type PAINTSTRUCT. The hdc field of this structure is the handle to the device context that BeginPaint returns. The PAINTSTRUCT structure also contains a RECT (rectangle) structure named rcPaint that contains a clipping rectangle indicating the invalid region of the window's client area. With the device context handle obtained from BeginPaint, you can draw only within this rectangle. The EndPaint call validates this region.

Windows programs can also obtain a handle to a device context during processing of messages other than WM_PAINT:

hdc = GetDC (hwnd) ;

[other program lines]

ReleaseDC (hwnd, hdc) ;

This device context applies to the client area of the window whose handle is hwnd. The primary difference between the use of these calls and of the BeginPaint and EndPaint combination is that you can draw on your entire client area with the handle returned from GetDC. However, ReleaseDC doesn't validate any possibly invalid regions of the client area.

A Windows program can also obtain a handle to a device context that applies to the entire window and not only to the window's client area:

hdc = GetWindowDC (hwnd) ;

[other program lines]

ReleaseDC (hwnd, hdc) ;

This device context includes the window caption bar, menu, scroll bars, and frame in addition to the client area. The GetWindowDC function is rarely used. If you want to experiment with it, you should trap WM_NCPAINT (”nonclient paint“) messages, which prevent Windows from drawing on the nonclient area of the window.

The BeginPaint, GetDC, and GetWindowDC calls obtain a device context associated with a particular window. You can also obtain a device context for the entire display by calling CreateDC:

hdc = CreateDC (lpszDriver, lpszDevice, lpszOutput, lpData) ;

[other program lines]

DeleteDC (hdc) ;

In the BLOWUP1 program in Chapter 4 we used this function to obtain a device context handle that allowed us to write outside our window's client area:

hdc = CreateDC ("DISPLAY", NULL, NULL, NULL) ;

Writing outside your windows is generally impolite, but it's convenient for some unusual applications. (Although this fact is undocumented, you can also retrieve a device context for the entire screen by calling GetDC with a NULL parameter.)

In Chapter 15 we'll use the CreateDC function to obtain a handle to a printer device context:

hdcPrinter = CreateDC ("IBMGRX", "IBM Graphics", "LPT1:", NULL) ;

Of course, we won't include the names of specific printers in our programs. Programs can instead obtain this information from WIN.INI.

Sometimes you need only to obtain some information about a device context and not to do any drawing. In these cases, you can obtain a handle to an ”information context“ using CreateIC. The parameters are the same as for the CreateDC function:

hdcInfo = CreateIC (lpszDriver, lpszDevice, lpszOutput, lpData) ;

[other program lines]

DeleteDC (hdcInfo) ;

You can't write to the device using this information context handle. We'll use this function in the DEVCAPS1 program shown later in this chapter to obtain an information context for the display and the printer.

In the GRAFMENU program in Chapter 9, we obtained a memory device context to manipulate some bitmaps. A memory device context is always created to be compatible with an existing device context:

hdcMem = CreateCompatibleDC (hdc) ;

[other program lines]

DeleteDC (hdcMem) ;

When you first obtain a memory device context, the display surface that it represents contains exactly 1 pixel. We'll work more with memory device contexts in Chapter 13.

In Chapter 13 we'll also work with ”metafiles.“ A metafile is a collection of GDI calls encoded in binary form. You can create a metafile by obtaining a metafile device context:

hdcMeta = CreateMetaFile (lpszFilename) ;

[other program lines]

hmf = CloseMetaFile (hdcMeta) ;

During the time that the metafile device context is valid, any GDI calls you make using hdcMeta become part of the metafile. When you call CloseMetaFile, the device context handle becomes invalid. The function returns a handle to the metafile (hmf).