1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxClientDC class 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // =========================================================================== 
  14 // =========================================================================== 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "dcclient.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #include "wx/string.h" 
  33 #include "wx/window.h" 
  35 #include "wx/msw/private.h" 
  37 #include "wx/dcclient.h" 
  39 // ---------------------------------------------------------------------------- 
  41 // ---------------------------------------------------------------------------- 
  43 #if !USE_SHARED_LIBRARY 
  44     IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
) 
  45     IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
) 
  46     IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
) 
  49 // ---------------------------------------------------------------------------- 
  51 // ---------------------------------------------------------------------------- 
  53 static PAINTSTRUCT g_paintStruct
; 
  56     // a global variable which we check to verify that wxPaintDC are only 
  57     // created in resopnse to WM_PAINT message - doing this from elsewhere is a 
  58     // common programming error among wxWindows programmers and might lead to 
  59     // very subtle and difficult to debug refresh/repaint bugs. 
  60     extern bool g_isPainting 
= FALSE
; 
  63 // =========================================================================== 
  65 // =========================================================================== 
  67 // ---------------------------------------------------------------------------- 
  69 // ---------------------------------------------------------------------------- 
  71 wxWindowDC::wxWindowDC() 
  76 wxWindowDC::wxWindowDC(wxWindow 
*the_canvas
) 
  78   m_canvas 
= the_canvas
; 
  79   m_hDC 
= (WXHDC
) ::GetWindowDC(GetWinHwnd(the_canvas
) ); 
  82   SetBackground(wxBrush(m_canvas
->GetBackgroundColour(), wxSOLID
)); 
  85 wxWindowDC::~wxWindowDC() 
  87   if (m_canvas 
&& m_hDC
) 
  89     SelectOldObjects(m_hDC
); 
  91     ::ReleaseDC(GetWinHwnd(m_canvas
), GetHdc()); 
  98 // ---------------------------------------------------------------------------- 
 100 // ---------------------------------------------------------------------------- 
 102 wxClientDC::wxClientDC() 
 107 wxClientDC::wxClientDC(wxWindow 
*the_canvas
) 
 109   m_canvas 
= the_canvas
; 
 110   m_hDC 
= (WXHDC
) ::GetDC(GetWinHwnd(the_canvas
)); 
 112   SetBackground(wxBrush(m_canvas
->GetBackgroundColour(), wxSOLID
)); 
 115 wxClientDC::~wxClientDC() 
 117   if ( m_canvas 
&& GetHdc() ) 
 119     SelectOldObjects(m_hDC
); 
 121     ::ReleaseDC(GetWinHwnd(m_canvas
), GetHdc()); 
 126 // ---------------------------------------------------------------------------- 
 128 // ---------------------------------------------------------------------------- 
 130 // TODO (VZ) I have still some doubts about this hack and I still think that we 
 131 //           should store pairs of (hwnd, hdc) and not just the DC - what if 
 132 //           BeginPaint() was called on other window? It seems to work like 
 133 //           this, but to be sure about it we'd need to store hwnd too... 
 135 WXHDC  
wxPaintDC::ms_PaintHDC 
= 0; 
 136 size_t wxPaintDC::ms_PaintCount 
= 0; // count of ms_PaintHDC usage 
 138 wxPaintDC::wxPaintDC() 
 143 wxPaintDC::wxPaintDC(wxWindow 
*canvas
) 
 145   wxCHECK_RET( canvas
, "NULL canvas in wxPaintDC ctor" ); 
 146   wxCHECK_RET( g_isPainting
, 
 147                _T("wxPaintDC may be created only in EVT_PAINT handler!") ); 
 151   // Don't call Begin/EndPaint if it's already been called: for example, if 
 152   // calling a base class OnPaint. 
 153   if ( ms_PaintCount 
> 0 ) { 
 154     // it means that we've already called BeginPaint and so we must just 
 155     // reuse the same HDC (BeginPaint shouldn't be called more than once) 
 156     wxASSERT( ms_PaintHDC 
); 
 163     m_hDC 
= (WXHDC
)::BeginPaint((HWND
)m_canvas
->GetHWND(), &g_paintStruct
); 
 168   SetBackground(wxBrush(m_canvas
->GetBackgroundColour(), wxSOLID
)); 
 171 wxPaintDC::~wxPaintDC() 
 174     if ( !--ms_PaintCount 
) { 
 175       ::EndPaint((HWND
)m_canvas
->GetHWND(), &g_paintStruct
); 
 177       m_hDC 
= (WXHDC
) NULL
; 
 178       ms_PaintHDC 
= (WXHDC
) NULL
; 
 180     //else: ms_PaintHDC still in use