1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxClientDC class
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #include "wx/string.h"
25 #include "wx/window.h"
28 #include "wx/os2/private.h"
30 #include "wx/dcclient.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 struct WXDLLEXPORT wxPaintDCInfo
38 wxPaintDCInfo( wxWindow
* pWin
42 m_hWnd
= pWin
->GetHWND();
43 m_hDC
= pDC
->GetHDC();
47 WXHWND m_hWnd
; // window for this DC
48 WXHDC m_hDC
; // the DC handle
49 size_t m_nCount
; // usage count
50 }; // end of wxPaintDCInfot
52 #include "wx/arrimpl.cpp"
54 WX_DEFINE_OBJARRAY(wxArrayDCInfo
);
56 // ----------------------------------------------------------------------------
58 // ----------------------------------------------------------------------------
60 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
61 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
62 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
64 // ----------------------------------------------------------------------------
66 // ----------------------------------------------------------------------------
68 static RECT g_paintStruct
;
71 // a global variable which we check to verify that wxPaintDC are only
72 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
73 // common programming error among wxWindows programmers and might lead to
74 // very subtle and difficult to debug refresh/repaint bugs.
78 // ===========================================================================
80 // ===========================================================================
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 wxWindowDC::wxWindowDC()
91 wxWindowDC::wxWindowDC(
98 m_pCanvas
= pTheCanvas
;
99 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
102 // default under PM is that Window and Client DC's are the same
103 // so we offer a separate Presentation Space to use for the
104 // entire window. Otherwise, calling BeginPaint will just create
105 // chached-micro client presentation space
107 m_hPS
= ::GpiCreatePS( vHabmain
110 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
112 ::GpiAssociate(m_hPS
, NULLHANDLE
);
113 ::GpiAssociate(m_hPS
, m_hDC
);
116 // Set the wxWindows color table
118 if (!::GpiCreateLogColorTable( m_hPS
122 ,(LONG
)wxTheColourDatabase
->m_nSize
123 ,(PLONG
)wxTheColourDatabase
->m_palTable
126 vError
= ::WinGetLastError(vHabmain
);
127 sError
= wxPMErrorToStr(vError
);
128 wxLogError("Unable to set current color table. Error: %s\n", sError
);
130 ::GpiCreateLogColorTable( m_hPS
137 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
141 } // end of wxWindowDC::wxWindowDC
143 void wxWindowDC::InitDC()
147 vColor
.InitFromName("BLACK");
148 m_pen
.SetColour(vColor
);
150 m_brush
.SetColour(vColor
);
152 // The background mode is only used for text background and is set in
153 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
155 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
158 // Default bg colour is pne of the window
160 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
161 } // end of wxWindowDC::InitDC
163 // ----------------------------------------------------------------------------
165 // ----------------------------------------------------------------------------
167 wxClientDC::wxClientDC()
172 wxClientDC::wxClientDC(
176 SIZEL vSizl
= { 0,0};
180 m_pCanvas
= pTheCanvas
;
183 // default under PM is that Window and Client DC's are the same
185 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
186 m_hPS
= ::GpiCreatePS( wxGetInstance()
189 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
192 // Set the wxWindows color table
193 if (!::GpiCreateLogColorTable( m_hPS
197 ,(LONG
)wxTheColourDatabase
->m_nSize
198 ,(PLONG
)wxTheColourDatabase
->m_palTable
201 vError
= ::WinGetLastError(vHabmain
);
202 sError
= wxPMErrorToStr(vError
);
203 wxLogError("Unable to set current color table. Error: %s\n", sError
);
205 ::GpiCreateLogColorTable( m_hPS
213 // Set the DC/PS rectangle
215 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
219 } // end of wxClientDC::wxClientDC
221 // ----------------------------------------------------------------------------
223 // ----------------------------------------------------------------------------
225 wxArrayDCInfo
wxPaintDC::ms_cache
;
227 wxPaintDC::wxPaintDC()
233 wxPaintDC::wxPaintDC(
237 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
240 if (g_isPainting
<= 0)
242 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
245 #endif // __WXDEBUG__
250 // Do we have a DC for this window in the cache?
252 wxPaintDCInfo
* pInfo
= FindInCache();
256 m_hDC
= pInfo
->m_hDC
;
259 else // not in cache, create a new one
263 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
271 ::GpiCreateLogColorTable( m_hPS
275 ,(LONG
)wxTheColourDatabase
->m_nSize
276 ,(PLONG
)wxTheColourDatabase
->m_palTable
278 ::GpiCreateLogColorTable( m_hPS
286 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
287 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
292 m_bIsPaintTime
= TRUE
;
293 m_hDC
= (WXHDC
) -1; // to satisfy those anonizmous efforts
294 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
297 } // end of wxPaintDC::wxPaintDC
299 wxPaintDC::~wxPaintDC()
303 SelectOldObjects(m_hDC
);
306 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
308 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
310 if ( !--pInfo
->m_nCount
)
312 ::WinEndPaint(m_hPS
);
314 m_bIsPaintTime
= FALSE
;
315 ms_cache
.Remove(nIndex
);
317 //else: cached DC entry is still in use
319 // prevent the base class dtor from ReleaseDC()ing it again
324 wxPaintDCInfo
* wxPaintDC::FindInCache(
328 wxPaintDCInfo
* pInfo
= NULL
;
329 size_t nCache
= ms_cache
.GetCount();
331 for (size_t n
= 0; n
< nCache
; n
++)
333 pInfo
= &ms_cache
[n
];
334 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
342 } // end of wxPaintDC::FindInCache
344 // find the entry for this DC in the cache (keyed by the window)
345 WXHDC
wxPaintDC::FindDCInCache(
349 wxPaintDCInfo
* pInfo
= NULL
;
350 size_t nCache
= ms_cache
.GetCount();
352 for (size_t n
= 0; n
< nCache
; n
++)
354 pInfo
= &ms_cache
[n
];
355 if (pInfo
->m_hWnd
== pWin
->GetHWND())
361 } // end of wxPaintDC::FindInCache