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 m_pen
.SetColour(*wxBLACK
);
172 m_brush
.SetColour(*wxWHITE
);
174 wxFont
* pFont
= new wxFont( 10, wxMODERN
, wxNORMAL
, wxBOLD
);
178 // OS/2 default vertical character alignment needs to match the other OS's
180 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
182 } // end of wxWindowDC::InitDC
184 void wxWindowDC::DoGetSize(
189 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
190 m_pCanvas
->GetSize( pnWidth
193 } // end of wxWindowDC::DoGetSize
195 // ----------------------------------------------------------------------------
197 // ----------------------------------------------------------------------------
199 wxClientDC::wxClientDC()
204 wxClientDC::wxClientDC(
208 SIZEL vSizl
= { 0,0};
212 m_pCanvas
= pTheCanvas
;
215 // default under PM is that Window and Client DC's are the same
217 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
218 m_hPS
= ::GpiCreatePS( wxGetInstance()
221 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
224 // Set the wxWidgets color table
225 if (!::GpiCreateLogColorTable( m_hPS
229 ,(LONG
)wxTheColourDatabase
->m_nSize
230 ,(PLONG
)wxTheColourDatabase
->m_palTable
233 vError
= ::WinGetLastError(vHabmain
);
234 sError
= wxPMErrorToStr(vError
);
235 wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError
.c_str());
237 ::GpiCreateLogColorTable( m_hPS
245 // Set the DC/PS rectangle
247 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
251 } // end of wxClientDC::wxClientDC
253 void wxClientDC::InitDC()
255 wxWindowDC::InitDC();
257 // in wxUniv build we must manually do some DC adjustments usually
258 // performed by Windows for us
259 #ifdef __WXUNIVERSAL__
260 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
261 if ( ptOrigin
.x
|| ptOrigin
.y
)
263 // no need to shift DC origin if shift is null
264 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
267 // clip the DC to avoid overwriting the non client area
268 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
269 #endif // __WXUNIVERSAL__
270 } // end of wxClientDC::InitDC
272 wxClientDC::~wxClientDC()
274 } // end of wxClientDC::~wxClientDC
276 void wxClientDC::DoGetSize(
281 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
282 m_pCanvas
->GetClientSize( pnWidth
285 } // end of wxClientDC::DoGetSize
287 // ----------------------------------------------------------------------------
289 // ----------------------------------------------------------------------------
291 wxArrayDCInfo
wxPaintDC::ms_cache
;
293 wxPaintDC::wxPaintDC()
299 wxPaintDC::wxPaintDC(
303 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
306 if (g_isPainting
<= 0)
308 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
311 #endif // __WXDEBUG__
316 // Do we have a DC for this window in the cache?
318 wxPaintDCInfo
* pInfo
= FindInCache();
322 m_hDC
= pInfo
->m_hDC
;
325 else // not in cache, create a new one
329 m_hDC
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
));
330 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
336 ::GpiAssociate(hPS
, m_hDC
);
339 ::GpiCreateLogColorTable( m_hPS
343 ,(LONG
)wxTheColourDatabase
->m_nSize
344 ,(PLONG
)wxTheColourDatabase
->m_palTable
346 ::GpiCreateLogColorTable( m_hPS
354 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
355 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
360 m_bIsPaintTime
= true;
361 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
364 } // end of wxPaintDC::wxPaintDC
366 wxPaintDC::~wxPaintDC()
370 SelectOldObjects(m_hDC
);
373 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
375 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
377 if ( !--pInfo
->m_nCount
)
379 ::WinEndPaint(m_hPS
);
381 m_bIsPaintTime
= false;
382 ms_cache
.RemoveAt(nIndex
);
384 //else: cached DC entry is still in use
386 // prevent the base class dtor from ReleaseDC()ing it again
391 wxPaintDCInfo
* wxPaintDC::FindInCache(
395 wxPaintDCInfo
* pInfo
= NULL
;
396 size_t nCache
= ms_cache
.GetCount();
398 for (size_t n
= 0; n
< nCache
; n
++)
400 pInfo
= &ms_cache
[n
];
401 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
409 } // end of wxPaintDC::FindInCache
411 // find the entry for this DC in the cache (keyed by the window)
412 WXHDC
wxPaintDC::FindDCInCache(
416 wxPaintDCInfo
* pInfo
= NULL
;
417 size_t nCache
= ms_cache
.GetCount();
419 for (size_t n
= 0; n
< nCache
; n
++)
421 pInfo
= &ms_cache
[n
];
422 if (pInfo
->m_hWnd
== pWin
->GetHWND())
428 } // end of wxPaintDC::FindInCache