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"
30 #include "wx/window.h"
33 #include "wx/os2/private.h"
35 // ----------------------------------------------------------------------------
37 // ----------------------------------------------------------------------------
39 struct WXDLLEXPORT wxPaintDCInfo
41 wxPaintDCInfo( wxWindow
* pWin
45 m_hWnd
= pWin
->GetHWND();
46 m_hDC
= pDC
->GetHDC();
50 WXHWND m_hWnd
; // window for this DC
51 WXHDC m_hDC
; // the DC handle
52 size_t m_nCount
; // usage count
53 }; // end of wxPaintDCInfot
55 #include "wx/arrimpl.cpp"
57 WX_DEFINE_OBJARRAY(wxArrayDCInfo
);
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC
, wxDC
)
64 IMPLEMENT_DYNAMIC_CLASS(wxClientDC
, wxWindowDC
)
65 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC
, wxWindowDC
)
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static RECT g_paintStruct
;
74 // a global variable which we check to verify that wxPaintDC are only
75 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
76 // common programming error among wxWidgets programmers and might lead to
77 // very subtle and difficult to debug refresh/repaint bugs.
81 // ===========================================================================
83 // ===========================================================================
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 wxWindowDC::wxWindowDC()
92 m_PageSize
.cx
= m_PageSize
.cy
= 0;
96 wxWindowDC::wxWindowDC(
104 m_pCanvas
= pTheCanvas
;
105 DoGetSize(&nWidth
, &nHeight
);
106 m_PageSize
.cx
= nWidth
;
107 m_PageSize
.cy
= nHeight
;
108 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
111 // default under PM is that Window and Client DC's are the same
112 // so we offer a separate Presentation Space to use for the
113 // entire window. Otherwise, calling BeginPaint will just create
114 // chached-micro client presentation space
116 m_hPS
= ::GpiCreatePS( vHabmain
119 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
123 vError
= ::WinGetLastError(vHabmain
);
124 sError
= wxPMErrorToStr(vError
);
125 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError
.c_str());
127 ::GpiAssociate(m_hPS
, NULLHANDLE
);
128 ::GpiAssociate(m_hPS
, m_hDC
);
131 // Set the wxWidgets color table
133 if (!::GpiCreateLogColorTable( m_hPS
137 ,(LONG
)wxTheColourDatabase
->m_nSize
138 ,(PLONG
)wxTheColourDatabase
->m_palTable
141 vError
= ::WinGetLastError(vHabmain
);
142 sError
= wxPMErrorToStr(vError
);
143 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError
.c_str());
145 ::GpiCreateLogColorTable( m_hPS
152 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
156 } // end of wxWindowDC::wxWindowDC
158 void wxWindowDC::InitDC()
162 // The background mode is only used for text background and is set in
163 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
165 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
168 // Default bg colour is pne of the window
170 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
172 wxColour
vColor( wxT("BLACK") );
173 m_pen
.SetColour(vColor
);
175 vColor
.Set( wxT("WHITE") );
176 m_brush
.SetColour(vColor
);
178 wxFont
* pFont
= new wxFont( 10
186 // OS/2 default vertical character alignment needs to match the other OS's
188 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
190 } // end of wxWindowDC::InitDC
192 void wxWindowDC::DoGetSize(
197 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
198 m_pCanvas
->GetSize( pnWidth
201 } // end of wxWindowDC::DoGetSize
203 // ----------------------------------------------------------------------------
205 // ----------------------------------------------------------------------------
207 wxClientDC::wxClientDC()
212 wxClientDC::wxClientDC(
216 SIZEL vSizl
= { 0,0};
220 m_pCanvas
= pTheCanvas
;
223 // default under PM is that Window and Client DC's are the same
225 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
226 m_hPS
= ::GpiCreatePS( wxGetInstance()
229 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
232 // Set the wxWidgets color table
233 if (!::GpiCreateLogColorTable( m_hPS
237 ,(LONG
)wxTheColourDatabase
->m_nSize
238 ,(PLONG
)wxTheColourDatabase
->m_palTable
241 vError
= ::WinGetLastError(vHabmain
);
242 sError
= wxPMErrorToStr(vError
);
243 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError
.c_str());
245 ::GpiCreateLogColorTable( m_hPS
253 // Set the DC/PS rectangle
255 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
259 } // end of wxClientDC::wxClientDC
261 void wxClientDC::InitDC()
263 wxWindowDC::InitDC();
265 // in wxUniv build we must manually do some DC adjustments usually
266 // performed by Windows for us
267 #ifdef __WXUNIVERSAL__
268 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
269 if ( ptOrigin
.x
|| ptOrigin
.y
)
271 // no need to shift DC origin if shift is null
272 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
275 // clip the DC to avoid overwriting the non client area
276 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
277 #endif // __WXUNIVERSAL__
278 } // end of wxClientDC::InitDC
280 wxClientDC::~wxClientDC()
282 } // end of wxClientDC::~wxClientDC
284 void wxClientDC::DoGetSize(
289 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
290 m_pCanvas
->GetClientSize( pnWidth
293 } // end of wxClientDC::DoGetSize
295 // ----------------------------------------------------------------------------
297 // ----------------------------------------------------------------------------
299 wxArrayDCInfo
wxPaintDC::ms_cache
;
301 wxPaintDC::wxPaintDC()
307 wxPaintDC::wxPaintDC(
311 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
314 if (g_isPainting
<= 0)
316 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
319 #endif // __WXDEBUG__
324 // Do we have a DC for this window in the cache?
326 wxPaintDCInfo
* pInfo
= FindInCache();
330 m_hDC
= pInfo
->m_hDC
;
333 else // not in cache, create a new one
337 m_hDC
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
));
338 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
344 ::GpiAssociate(hPS
, m_hDC
);
347 ::GpiCreateLogColorTable( m_hPS
351 ,(LONG
)wxTheColourDatabase
->m_nSize
352 ,(PLONG
)wxTheColourDatabase
->m_palTable
354 ::GpiCreateLogColorTable( m_hPS
362 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
363 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
368 m_bIsPaintTime
= true;
369 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
372 } // end of wxPaintDC::wxPaintDC
374 wxPaintDC::~wxPaintDC()
378 SelectOldObjects(m_hDC
);
381 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
383 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
385 if ( !--pInfo
->m_nCount
)
387 ::WinEndPaint(m_hPS
);
389 m_bIsPaintTime
= false;
390 ms_cache
.RemoveAt(nIndex
);
392 //else: cached DC entry is still in use
394 // prevent the base class dtor from ReleaseDC()ing it again
399 wxPaintDCInfo
* wxPaintDC::FindInCache(
403 wxPaintDCInfo
* pInfo
= NULL
;
404 size_t nCache
= ms_cache
.GetCount();
406 for (size_t n
= 0; n
< nCache
; n
++)
408 pInfo
= &ms_cache
[n
];
409 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
417 } // end of wxPaintDC::FindInCache
419 // find the entry for this DC in the cache (keyed by the window)
420 WXHDC
wxPaintDC::FindDCInCache(
424 wxPaintDCInfo
* pInfo
= NULL
;
425 size_t nCache
= ms_cache
.GetCount();
427 for (size_t n
= 0; n
< nCache
; n
++)
429 pInfo
= &ms_cache
[n
];
430 if (pInfo
->m_hWnd
== pWin
->GetHWND())
436 } // end of wxPaintDC::FindInCache