Can't use "SaveDC" and "RestoreDC" function in other message handling code?
I am trying to set my preferred device context properties in a message WM_CREATE
and then use it in a message WM_PAINT
. My method is to use the features SaveDC
and RestoreDC
in reports WM_CREATE
, and WM_PAINT
, respectively. But the result doesn't match my need. I really need to show a circle in the center of the client area.
#include <windows.h>
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("HelloWin") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, // window class name
TEXT ("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL) ; // creation parameters
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc ;
PAINTSTRUCT ps ;
RECT rect;
static int nSavedDC;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
SetMapMode(hdc, MM_LOMETRIC);
GetClientRect(hwnd, &rect);
SetViewportOrgEx(hdc, rect.right/2, rect.bottom/2, NULL);
nSavedDC = SaveDC(hdc); //I want to save the current state of device context to be used in WM_PAINT message.
ReleaseDC(hwnd, hdc);
return 0;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
RestoreDC(hdc, nSavedDC); //Restore the the state of device context which is saved in WM_CREATE message.
Ellipse(hdc, -100, 100, 100, -100);
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
source to share
Your code is missing error handling. You need to check all the values ββreturned by every call to the GDI function.
As described on the MSDN page , the purpose of SaveDC
/ RestoreDC
is mainly to restore the state to its original after drawing is complete. And that's exactly what you don't do in message handlers WM_CREATE
and WM_PAINT
. You always leave the DC in a modified state.
How to use SaveDC
/ RestoreDC
to tune the DC state once and then quickly restore it on every draw operation instead of tweaking from scratch every time I think of at least one obstacle: if any other function calls RestoreDC
between DC handlers restoring an item that was not on top of the DC's state stack, then your saved state that was on top of the stack will be destroyed as described.
source to share