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 wxWidgets programmers and might lead to
74 // very subtle and difficult to debug refresh/repaint bugs.
78 // ===========================================================================
80 // ===========================================================================
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 wxWindowDC::wxWindowDC()
89 m_PageSize
.cx
= m_PageSize
.cy
= 0;
93 wxWindowDC::wxWindowDC(
101 m_pCanvas
= pTheCanvas
;
102 DoGetSize(&nWidth
, &nHeight
);
103 m_PageSize
.cx
= nWidth
;
104 m_PageSize
.cy
= nHeight
;
105 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
108 // default under PM is that Window and Client DC's are the same
109 // so we offer a separate Presentation Space to use for the
110 // entire window. Otherwise, calling BeginPaint will just create
111 // chached-micro client presentation space
113 m_hPS
= ::GpiCreatePS( vHabmain
116 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
120 vError
= ::WinGetLastError(vHabmain
);
121 sError
= wxPMErrorToStr(vError
);
122 wxLogError("Unable to create presentation space. Error: %s\n", sError
.c_str());
124 ::GpiAssociate(m_hPS
, NULLHANDLE
);
125 ::GpiAssociate(m_hPS
, m_hDC
);
128 // Set the wxWidgets color table
130 if (!::GpiCreateLogColorTable( m_hPS
134 ,(LONG
)wxTheColourDatabase
->m_nSize
135 ,(PLONG
)wxTheColourDatabase
->m_palTable
138 vError
= ::WinGetLastError(vHabmain
);
139 sError
= wxPMErrorToStr(vError
);
140 wxLogError("Unable to set current color table. Error: %s\n", sError
.c_str());
142 ::GpiCreateLogColorTable( m_hPS
149 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
153 } // end of wxWindowDC::wxWindowDC
155 void wxWindowDC::InitDC()
159 // The background mode is only used for text background and is set in
160 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
162 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
165 // Default bg colour is pne of the window
167 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
169 wxColour
vColor( wxT("BLACK") );
170 m_pen
.SetColour(vColor
);
172 vColor
.Set( wxT("WHITE") );
173 m_brush
.SetColour(vColor
);
175 wxFont
* pFont
= new wxFont( 12
183 // OS/2 default vertical character allignment needs to match the other OS's
185 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
187 } // end of wxWindowDC::InitDC
189 void wxWindowDC::DoGetSize(
194 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
195 m_pCanvas
->GetSize( pnWidth
198 } // end of wxWindowDC::DoGetSize
200 // ----------------------------------------------------------------------------
202 // ----------------------------------------------------------------------------
204 wxClientDC::wxClientDC()
209 wxClientDC::wxClientDC(
213 SIZEL vSizl
= { 0,0};
217 m_pCanvas
= pTheCanvas
;
220 // default under PM is that Window and Client DC's are the same
222 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
223 m_hPS
= ::GpiCreatePS( wxGetInstance()
226 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
229 // Set the wxWidgets color table
230 if (!::GpiCreateLogColorTable( m_hPS
234 ,(LONG
)wxTheColourDatabase
->m_nSize
235 ,(PLONG
)wxTheColourDatabase
->m_palTable
238 vError
= ::WinGetLastError(vHabmain
);
239 sError
= wxPMErrorToStr(vError
);
240 wxLogError("Unable to set current color table. Error: %s\n", sError
.c_str());
242 ::GpiCreateLogColorTable( m_hPS
250 // Set the DC/PS rectangle
252 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
256 } // end of wxClientDC::wxClientDC
258 void wxClientDC::InitDC()
260 wxWindowDC::InitDC();
262 // in wxUniv build we must manually do some DC adjustments usually
263 // performed by Windows for us
264 #ifdef __WXUNIVERSAL__
265 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
266 if ( ptOrigin
.x
|| ptOrigin
.y
)
268 // no need to shift DC origin if shift is null
269 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
272 // clip the DC to avoid overwriting the non client area
273 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
274 #endif // __WXUNIVERSAL__
275 } // end of wxClientDC::InitDC
277 wxClientDC::~wxClientDC()
279 } // end of wxClientDC::~wxClientDC
281 void wxClientDC::DoGetSize(
286 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
287 m_pCanvas
->GetClientSize( pnWidth
290 } // end of wxClientDC::DoGetSize
292 // ----------------------------------------------------------------------------
294 // ----------------------------------------------------------------------------
296 wxArrayDCInfo
wxPaintDC::ms_cache
;
298 wxPaintDC::wxPaintDC()
304 wxPaintDC::wxPaintDC(
308 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
311 if (g_isPainting
<= 0)
313 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
316 #endif // __WXDEBUG__
321 // Do we have a DC for this window in the cache?
323 wxPaintDCInfo
* pInfo
= FindInCache();
327 m_hDC
= pInfo
->m_hDC
;
330 else // not in cache, create a new one
334 m_hDC
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
));
335 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
341 ::GpiAssociate(hPS
, m_hDC
);
344 ::GpiCreateLogColorTable( m_hPS
348 ,(LONG
)wxTheColourDatabase
->m_nSize
349 ,(PLONG
)wxTheColourDatabase
->m_palTable
351 ::GpiCreateLogColorTable( m_hPS
359 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
360 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
365 m_bIsPaintTime
= TRUE
;
366 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
369 } // end of wxPaintDC::wxPaintDC
371 wxPaintDC::~wxPaintDC()
375 SelectOldObjects(m_hDC
);
378 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
380 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
382 if ( !--pInfo
->m_nCount
)
384 ::WinEndPaint(m_hPS
);
386 m_bIsPaintTime
= FALSE
;
387 ms_cache
.RemoveAt(nIndex
);
389 //else: cached DC entry is still in use
391 // prevent the base class dtor from ReleaseDC()ing it again
396 wxPaintDCInfo
* wxPaintDC::FindInCache(
400 wxPaintDCInfo
* pInfo
= NULL
;
401 size_t nCache
= ms_cache
.GetCount();
403 for (size_t n
= 0; n
< nCache
; n
++)
405 pInfo
= &ms_cache
[n
];
406 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
414 } // end of wxPaintDC::FindInCache
416 // find the entry for this DC in the cache (keyed by the window)
417 WXHDC
wxPaintDC::FindDCInCache(
421 wxPaintDCInfo
* pInfo
= NULL
;
422 size_t nCache
= ms_cache
.GetCount();
424 for (size_t n
= 0; n
< nCache
; n
++)
426 pInfo
= &ms_cache
[n
];
427 if (pInfo
->m_hWnd
== pWin
->GetHWND())
433 } // end of wxPaintDC::FindInCache