1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/dcclient.cpp
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/dcclient.h"
26 #include "wx/string.h"
29 #include "wx/window.h"
32 #include "wx/os2/private.h"
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 struct WXDLLEXPORT wxPaintDCInfo
40 wxPaintDCInfo( wxWindow
* pWin
44 m_hWnd
= pWin
->GetHWND();
45 m_hDC
= pDC
->GetHDC();
49 WXHWND m_hWnd
; // window for this DC
50 WXHDC m_hDC
; // the DC handle
51 size_t m_nCount
; // usage count
52 }; // end of wxPaintDCInfot
54 #include "wx/arrimpl.cpp"
56 WX_DEFINE_OBJARRAY(wxArrayDCInfo
);
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
63 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
64 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 static RECT g_paintStruct
;
73 // a global variable which we check to verify that wxPaintDC are only
74 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
75 // common programming error among wxWidgets programmers and might lead to
76 // very subtle and difficult to debug refresh/repaint bugs.
80 // ===========================================================================
82 // ===========================================================================
84 // ----------------------------------------------------------------------------
86 // ----------------------------------------------------------------------------
88 wxWindowDC::wxWindowDC()
91 m_PageSize
.cx
= m_PageSize
.cy
= 0;
95 wxWindowDC::wxWindowDC(
103 m_pCanvas
= pTheCanvas
;
104 DoGetSize(&nWidth
, &nHeight
);
105 m_PageSize
.cx
= nWidth
;
106 m_PageSize
.cy
= nHeight
;
107 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
110 // default under PM is that Window and Client DC's are the same
111 // so we offer a separate Presentation Space to use for the
112 // entire window. Otherwise, calling BeginPaint will just create
113 // chached-micro client presentation space
115 m_hPS
= ::GpiCreatePS( vHabmain
118 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
122 vError
= ::WinGetLastError(vHabmain
);
123 sError
= wxPMErrorToStr(vError
);
124 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError
.c_str());
126 ::GpiAssociate(m_hPS
, NULLHANDLE
);
127 ::GpiAssociate(m_hPS
, m_hDC
);
130 // Set the wxWidgets color table
132 if (!::GpiCreateLogColorTable( m_hPS
136 ,(LONG
)wxTheColourDatabase
->m_nSize
137 ,(PLONG
)wxTheColourDatabase
->m_palTable
140 vError
= ::WinGetLastError(vHabmain
);
141 sError
= wxPMErrorToStr(vError
);
142 wxLogError(_T("Unable to set current color table (3). Error: %s\n"), sError
.c_str());
144 ::GpiCreateLogColorTable( m_hPS
151 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
155 } // end of wxWindowDC::wxWindowDC
157 void wxWindowDC::InitDC()
161 // The background mode is only used for text background and is set in
162 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
164 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
167 // Default bg colour is pne of the window
169 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
171 wxColour
vColor( wxT("BLACK") );
172 m_pen
.SetColour(vColor
);
174 vColor
.Set( wxT("WHITE") );
175 m_brush
.SetColour(vColor
);
177 wxFont
* pFont
= new wxFont( 10
185 // OS/2 default vertical character alignment needs to match the other OS's
187 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
189 } // end of wxWindowDC::InitDC
191 void wxWindowDC::DoGetSize(
196 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
197 m_pCanvas
->GetSize( pnWidth
200 } // end of wxWindowDC::DoGetSize
202 // ----------------------------------------------------------------------------
204 // ----------------------------------------------------------------------------
206 wxClientDC::wxClientDC()
211 wxClientDC::wxClientDC(
215 SIZEL vSizl
= { 0,0};
219 m_pCanvas
= pTheCanvas
;
222 // default under PM is that Window and Client DC's are the same
224 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
225 m_hPS
= ::GpiCreatePS( wxGetInstance()
228 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
231 // Set the wxWidgets color table
232 if (!::GpiCreateLogColorTable( m_hPS
236 ,(LONG
)wxTheColourDatabase
->m_nSize
237 ,(PLONG
)wxTheColourDatabase
->m_palTable
240 vError
= ::WinGetLastError(vHabmain
);
241 sError
= wxPMErrorToStr(vError
);
242 wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError
.c_str());
244 ::GpiCreateLogColorTable( m_hPS
252 // Set the DC/PS rectangle
254 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
258 } // end of wxClientDC::wxClientDC
260 void wxClientDC::InitDC()
262 wxWindowDC::InitDC();
264 // in wxUniv build we must manually do some DC adjustments usually
265 // performed by Windows for us
266 #ifdef __WXUNIVERSAL__
267 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
268 if ( ptOrigin
.x
|| ptOrigin
.y
)
270 // no need to shift DC origin if shift is null
271 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
274 // clip the DC to avoid overwriting the non client area
275 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
276 #endif // __WXUNIVERSAL__
277 } // end of wxClientDC::InitDC
279 wxClientDC::~wxClientDC()
281 } // end of wxClientDC::~wxClientDC
283 void wxClientDC::DoGetSize(
288 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
289 m_pCanvas
->GetClientSize( pnWidth
292 } // end of wxClientDC::DoGetSize
294 // ----------------------------------------------------------------------------
296 // ----------------------------------------------------------------------------
298 wxArrayDCInfo
wxPaintDC::ms_cache
;
300 wxPaintDC::wxPaintDC()
306 wxPaintDC::wxPaintDC(
310 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
313 if (g_isPainting
<= 0)
315 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
318 #endif // __WXDEBUG__
323 // Do we have a DC for this window in the cache?
325 wxPaintDCInfo
* pInfo
= FindInCache();
329 m_hDC
= pInfo
->m_hDC
;
332 else // not in cache, create a new one
336 m_hDC
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
));
337 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
343 ::GpiAssociate(hPS
, m_hDC
);
346 ::GpiCreateLogColorTable( m_hPS
350 ,(LONG
)wxTheColourDatabase
->m_nSize
351 ,(PLONG
)wxTheColourDatabase
->m_palTable
353 ::GpiCreateLogColorTable( m_hPS
361 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
362 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
367 m_bIsPaintTime
= true;
368 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
371 } // end of wxPaintDC::wxPaintDC
373 wxPaintDC::~wxPaintDC()
377 SelectOldObjects(m_hDC
);
380 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
382 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
384 if ( !--pInfo
->m_nCount
)
386 ::WinEndPaint(m_hPS
);
388 m_bIsPaintTime
= false;
389 ms_cache
.RemoveAt(nIndex
);
391 //else: cached DC entry is still in use
393 // prevent the base class dtor from ReleaseDC()ing it again
398 wxPaintDCInfo
* wxPaintDC::FindInCache(
402 wxPaintDCInfo
* pInfo
= NULL
;
403 size_t nCache
= ms_cache
.GetCount();
405 for (size_t n
= 0; n
< nCache
; n
++)
407 pInfo
= &ms_cache
[n
];
408 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
416 } // end of wxPaintDC::FindInCache
418 // find the entry for this DC in the cache (keyed by the window)
419 WXHDC
wxPaintDC::FindDCInCache(
423 wxPaintDCInfo
* pInfo
= NULL
;
424 size_t nCache
= ms_cache
.GetCount();
426 for (size_t n
= 0; n
< nCache
; n
++)
428 pInfo
= &ms_cache
[n
];
429 if (pInfo
->m_hWnd
== pWin
->GetHWND())
435 } // end of wxPaintDC::FindInCache