Throughout Section IV, you'll encounter various functions to change the device context attributes. Normally, Windows creates a new device context with default values when you call GetDC or BeginPaint. All changes you make to the attributes are lost when the device context is released with the ReleaseDC or the EndPaint call. If your program needs to use nondefault device context attributes, you'll have to initialize the device context every time you obtain a device context handle:
WM_PAINT :
hdc = BeginPaint (hwnd, &ps) ;
[initialize device context attributes][paint client area of window]
EndPaint (hwnd, &ps) ;
return 0 ;
Although this approach is generally satisfactory, you might prefer that changes you make to the device context attributes be saved when you release the device context, so they will be in effect the next time you call GetDC or BeginPaint. You can accomplish this by including the CS_OWNDC flag as part of the window class when you register the window class:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ;
Now each window that you create based on this window class will have its own private device context that exists until the window is destroyed. When you use the CS_OWNDC style, you need to initialize the device context attributes only once, perhaps during processing of the WM_CREATE message:
WM_CREATE :
hdc = GetDC (hwnd) ;
[initialize device context attributes]
ReleaseDC (hwnd, hdc) ;
The attributes continue to be valid until you change them.
The CS_OWNDC style affects only the device contexts retrieved from GetDC and BeginPaint and not device contexts obtained from the other functions (such as GetWindowDC). The CS_OWNDC style is not without its cost: Windows requires about 800 bytes to store the device context for each window created with this style. Even if you use CS_OWNDC, you must still release the device context before exiting the window function.
You can also use the CS_CLASSDC style:
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC ;
This causes each window class to have its own device context that is shared by all windows created based on that class—even by windows created in other instances of the same program. Now you can initialize the device context attributes once in WinMain following creation of the first window based on that window class:
if (!hPrevInstance)
{
hdc = GetDC (hwnd) ;
[initialize device context]
ReleaseDC (hwnd, hdc) ;
}
In general, the CS_CLASSDC type of device context is more difficult to use than the CS_OWNDC type, because any changes you make to the device context attributes affect all windows in all instances based on the same window class. This could have some strange effects, particularly if you use a customized mapping mode (a subject coming up shortly) based on the size of the window.
In some cases you might want to change certain device context attributes, do some painting using the changed attributes, and then revert to the original device context. To simplify this process, you save the state of a device context by calling:
nSavedID = SaveDC (hdc) ;
Now you change some attributes. When you want to return to the device context as it existed before the SaveDC call, you use:
RestoreDC (hdc, nSavedID) ;
You can call SaveDC any number of times before calling RestoreDC. If you want to revert to the device context as it existed before the last SaveDC call, you call:
RestoreDC (hdc, -1) ;