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) ;
}

      

+3


source to share


1 answer


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.

+1


source







All Articles