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"
24 #include "wx/os2/dcclient.h"
27 #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 static RECT g_paintStruct
;
65 #ifdef wxHAS_PAINT_DEBUG
66 // a global variable which we check to verify that wxPaintDC are only
67 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
68 // common programming error among wxWidgets programmers and might lead to
69 // very subtle and difficult to debug refresh/repaint bugs.
71 #endif // wxHAS_PAINT_DEBUG
73 // ===========================================================================
75 // ===========================================================================
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl
, wxPMDCImpl
)
83 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
) :
86 m_PageSize
.cx
= m_PageSize
.cy
= 0;
89 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
, wxWindow
* pTheCanvas
) :
96 m_pCanvas
= pTheCanvas
;
97 DoGetSize(&nWidth
, &nHeight
);
98 m_PageSize
.cx
= nWidth
;
99 m_PageSize
.cy
= nHeight
;
100 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
103 // default under PM is that Window and Client DC's are the same
104 // so we offer a separate Presentation Space to use for the
105 // entire window. Otherwise, calling BeginPaint will just create
106 // chached-micro client presentation space
108 m_hPS
= ::GpiCreatePS( vHabmain
111 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
115 vError
= ::WinGetLastError(vHabmain
);
116 sError
= wxPMErrorToStr(vError
);
117 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError
.c_str());
119 ::GpiAssociate(m_hPS
, NULLHANDLE
);
120 ::GpiAssociate(m_hPS
, m_hDC
);
123 // Set the wxWidgets color table
125 if (!::GpiCreateLogColorTable( m_hPS
129 ,(LONG
)wxTheColourDatabase
->m_nSize
130 ,(PLONG
)wxTheColourDatabase
->m_palTable
133 vError
= ::WinGetLastError(vHabmain
);
134 sError
= wxPMErrorToStr(vError
);
135 wxLogError(_T("Unable to set current color table (3). Error: %s\n"), sError
.c_str());
137 ::GpiCreateLogColorTable( m_hPS
144 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
148 } // end of wxWindowDCImpl::wxWindowDCImpl
150 void wxWindowDCImpl::InitDC()
154 // The background mode is only used for text background and is set in
155 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
157 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
160 // Default bg colour is pne of the window
162 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
164 m_pen
.SetColour(*wxBLACK
);
165 m_brush
.SetColour(*wxWHITE
);
166 // since we are a window dc we need to grab the palette from the window
170 wxFont
* pFont
= new wxFont( 10, wxMODERN
, wxNORMAL
, wxBOLD
);
174 // OS/2 default vertical character alignment needs to match the other OS's
176 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
178 } // end of wxWindowDCImpl::InitDC
180 void wxWindowDCImpl::DoGetSize(
185 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
186 m_pCanvas
->GetSize( pnWidth
189 } // end of wxWindowDCImpl::DoGetSize
191 // ----------------------------------------------------------------------------
193 // ----------------------------------------------------------------------------
195 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl
, wxWindowDCImpl
)
197 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
) :
198 wxWindowDCImpl( owner
)
203 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
, wxWindow
*pTheCanvas
) :
204 wxWindowDCImpl( owner
)
206 SIZEL vSizl
= { 0,0};
210 m_pCanvas
= pTheCanvas
;
213 // default under PM is that Window and Client DC's are the same
216 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
217 printf("Got WindowDC %X for window handle %X\n", m_hDC
, pTheCanvas
);
219 m_hPS
= ::GpiCreatePS( wxGetInstance()
222 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
224 ::GpiAssociate(m_hPS
, NULLHANDLE
);
225 ::GpiAssociate(m_hPS
, m_hDC
);
227 printf("Got m_hPS %X\n", m_hPS
);
228 // Set the wxWidgets color table
229 if (!::GpiCreateLogColorTable( m_hPS
233 ,(LONG
)wxTheColourDatabase
->m_nSize
234 ,(PLONG
)wxTheColourDatabase
->m_palTable
237 vError
= ::WinGetLastError(vHabmain
);
238 sError
= wxPMErrorToStr(vError
);
239 wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError
.c_str());
241 ::GpiCreateLogColorTable( m_hPS
249 // Set the DC/PS rectangle
251 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
255 } // end of wxClientDCImpl::wxClientDCImpl
257 void wxClientDCImpl::InitDC()
259 wxWindowDCImpl::InitDC();
261 // in wxUniv build we must manually do some DC adjustments usually
262 // performed by Windows for us
263 #ifdef __WXUNIVERSAL__
264 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
265 if ( ptOrigin
.x
|| ptOrigin
.y
)
267 // no need to shift DC origin if shift is null
268 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
271 // clip the DC to avoid overwriting the non client area
272 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
273 #endif // __WXUNIVERSAL__
274 } // end of wxClientDCImpl::InitDC
276 wxClientDCImpl::~wxClientDCImpl()
278 } // end of wxClientDCImpl::~wxClientDCImpl
280 void wxClientDCImpl::DoGetSize(
285 wxCHECK_RET( m_pCanvas
, _T("wxWindowDC without a window?") );
286 m_pCanvas
->GetClientSize( pnWidth
289 } // end of wxClientDCImpl::DoGetSize
291 // ----------------------------------------------------------------------------
293 // ----------------------------------------------------------------------------
295 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl
, wxWindowDCImpl
)
297 wxArrayDCInfo
wxPaintDCImpl::ms_cache
;
299 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
) :
300 wxClientDCImpl( owner
)
306 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
, wxWindow
*pCanvas
) :
307 wxClientDCImpl( owner
)
309 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
311 #ifdef wxHAS_PAINT_DEBUG
312 if (g_isPainting
<= 0)
314 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
317 #endif // wxHAS_PAINT_DEBUG
322 // Do we have a DC for this window in the cache?
324 wxPaintDCInfo
* pInfo
= FindInCache();
328 m_hDC
= pInfo
->m_hDC
;
331 else // not in cache, create a new one
335 m_hDC
= ::WinOpenWindowDC(GetWinHwnd(m_pCanvas
));
336 hPS
= ::WinBeginPaint( GetWinHwnd(m_pCanvas
)
342 ::GpiAssociate(hPS
, m_hDC
);
345 ::GpiCreateLogColorTable( m_hPS
349 ,(LONG
)wxTheColourDatabase
->m_nSize
350 ,(PLONG
)wxTheColourDatabase
->m_palTable
352 ::GpiCreateLogColorTable( m_hPS
360 ::WinFillRect(hPS
, &g_paintStruct
, m_pCanvas
->GetBackgroundColour().GetPixel());
361 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
366 m_bIsPaintTime
= true;
367 ms_cache
.Add(new wxPaintDCInfo(m_pCanvas
, this));
370 } // end of wxPaintDCImpl::wxPaintDCImpl
372 wxPaintDCImpl::~wxPaintDCImpl()
376 SelectOldObjects(m_hDC
);
379 wxPaintDCInfo
* pInfo
= FindInCache(&nIndex
);
381 wxCHECK_RET( pInfo
, wxT("existing DC should have a cache entry") );
383 if ( !--pInfo
->m_nCount
)
385 ::WinEndPaint(m_hPS
);
387 m_bIsPaintTime
= false;
388 ms_cache
.RemoveAt(nIndex
);
390 //else: cached DC entry is still in use
392 // prevent the base class dtor from ReleaseDC()ing it again
397 wxPaintDCInfo
* wxPaintDCImpl::FindInCache(
401 wxPaintDCInfo
* pInfo
= NULL
;
402 size_t nCache
= ms_cache
.GetCount();
404 for (size_t n
= 0; n
< nCache
; n
++)
406 pInfo
= &ms_cache
[n
];
407 if (pInfo
->m_hWnd
== m_pCanvas
->GetHWND())
415 } // end of wxPaintDCImpl::FindInCache
417 // find the entry for this DC in the cache (keyed by the window)
418 WXHDC
wxPaintDCImpl::FindDCInCache(
422 wxPaintDCInfo
* pInfo
= NULL
;
423 size_t nCache
= ms_cache
.GetCount();
425 for (size_t n
= 0; n
< nCache
; n
++)
427 pInfo
= &ms_cache
[n
];
428 if (pInfo
->m_hWnd
== pWin
->GetHWND())
434 } // end of wxPaintDCImpl::FindInCache