1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: David Webster
7 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #include "wx/dcclient.h"
23 #include "wx/os2/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 static RECT g_paintStruct
;
64 #ifdef wxHAS_PAINT_DEBUG
65 // a global variable which we check to verify that wxPaintDC are only
66 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
67 // common programming error among wxWidgets programmers and might lead to
68 // very subtle and difficult to debug refresh/repaint bugs.
70 #endif // wxHAS_PAINT_DEBUG
72 // ===========================================================================
74 // ===========================================================================
76 // ----------------------------------------------------------------------------
78 // ----------------------------------------------------------------------------
80 IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl
, wxPMDCImpl
)
82 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
) :
85 m_PageSize
.cx
= m_PageSize
.cy
= 0;
88 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
, wxWindow
* pTheCanvas
) :
95 m_pCanvas
= pTheCanvas
;
96 DoGetSize(&nWidth
, &nHeight
);
97 m_PageSize
.cx
= nWidth
;
98 m_PageSize
.cy
= nHeight
;
99 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
) );
102 // default under PM is that Window and Client DC's are the same
103 // so we offer a separate Presentation Space to use for the
104 // entire window. Otherwise, calling BeginPaint will just create
105 // chached-micro client presentation space
107 m_hPS
= ::GpiCreatePS( vHabmain
110 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
114 vError
= ::WinGetLastError(vHabmain
);
115 sError
= wxPMErrorToStr(vError
);
116 wxLogError(wxT("Unable to create presentation space. Error: %s\n"), sError
.c_str());
118 ::GpiAssociate(m_hPS
, NULLHANDLE
);
119 ::GpiAssociate(m_hPS
, m_hDC
);
122 // Set the wxWidgets color table
124 if (!::GpiCreateLogColorTable( m_hPS
128 ,(LONG
)wxTheColourDatabase
->m_nSize
129 ,(PLONG
)wxTheColourDatabase
->m_palTable
132 vError
= ::WinGetLastError(vHabmain
);
133 sError
= wxPMErrorToStr(vError
);
134 wxLogError(wxT("Unable to set current color table (3). Error: %s\n"), sError
.c_str());
136 ::GpiCreateLogColorTable( m_hPS
143 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
147 } // end of wxWindowDCImpl::wxWindowDCImpl
149 void wxWindowDCImpl::InitDC()
153 // The background mode is only used for text background and is set in
154 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
156 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE
);
159 // Default bg colour is pne of the window
161 SetBackground(wxBrush(m_pCanvas
->GetBackgroundColour(), wxSOLID
));
163 m_pen
.SetColour(*wxBLACK
);
164 m_brush
.SetColour(*wxWHITE
);
165 // since we are a window dc we need to grab the palette from the window
169 wxFont
* pFont
= new wxFont( 10, wxMODERN
, wxNORMAL
, wxBOLD
);
173 // OS/2 default vertical character alignment needs to match the other OS's
175 ::GpiSetTextAlignment((HPS
)GetHPS(), TA_NORMAL_HORIZ
, TA_BOTTOM
);
177 } // end of wxWindowDCImpl::InitDC
179 void wxWindowDCImpl::DoGetSize(
184 wxCHECK_RET( m_pCanvas
, wxT("wxWindowDC without a window?") );
185 m_pCanvas
->GetSize( pnWidth
188 } // end of wxWindowDCImpl::DoGetSize
190 // ----------------------------------------------------------------------------
192 // ----------------------------------------------------------------------------
194 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl
, wxWindowDCImpl
)
196 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
) :
197 wxWindowDCImpl( owner
)
202 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
, wxWindow
*pTheCanvas
) :
203 wxWindowDCImpl( owner
)
205 SIZEL vSizl
= { 0,0};
209 m_pCanvas
= pTheCanvas
;
212 // default under PM is that Window and Client DC's are the same
215 m_hDC
= (WXHDC
) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas
));
216 printf("Got WindowDC %X for window handle %X\n", m_hDC
, pTheCanvas
);
218 m_hPS
= ::GpiCreatePS( wxGetInstance()
221 ,PU_PELS
| GPIF_LONG
| GPIA_ASSOC
223 ::GpiAssociate(m_hPS
, NULLHANDLE
);
224 ::GpiAssociate(m_hPS
, m_hDC
);
226 printf("Got m_hPS %X\n", m_hPS
);
227 // Set the wxWidgets color table
228 if (!::GpiCreateLogColorTable( m_hPS
232 ,(LONG
)wxTheColourDatabase
->m_nSize
233 ,(PLONG
)wxTheColourDatabase
->m_palTable
236 vError
= ::WinGetLastError(vHabmain
);
237 sError
= wxPMErrorToStr(vError
);
238 wxLogError(wxT("Unable to set current color table (4). Error: %s\n"), sError
.c_str());
240 ::GpiCreateLogColorTable( m_hPS
248 // Set the DC/PS rectangle
250 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas
)
254 } // end of wxClientDCImpl::wxClientDCImpl
256 void wxClientDCImpl::InitDC()
258 wxWindowDCImpl::InitDC();
260 // in wxUniv build we must manually do some DC adjustments usually
261 // performed by Windows for us
262 #ifdef __WXUNIVERSAL__
263 wxPoint ptOrigin
= m_pCanvas
->GetClientAreaOrigin();
264 if ( ptOrigin
.x
|| ptOrigin
.y
)
266 // no need to shift DC origin if shift is null
267 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
270 // clip the DC to avoid overwriting the non client area
271 SetClippingRegion(wxPoint(0, 0), m_pCanvas
->GetClientSize());
272 #endif // __WXUNIVERSAL__
273 } // end of wxClientDCImpl::InitDC
275 wxClientDCImpl::~wxClientDCImpl()
277 } // end of wxClientDCImpl::~wxClientDCImpl
279 void wxClientDCImpl::DoGetSize(
284 wxCHECK_RET( m_pCanvas
, wxT("wxWindowDC without a window?") );
285 m_pCanvas
->GetClientSize( pnWidth
288 } // end of wxClientDCImpl::DoGetSize
290 // ----------------------------------------------------------------------------
292 // ----------------------------------------------------------------------------
294 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl
, wxWindowDCImpl
)
296 wxArrayDCInfo
wxPaintDCImpl::ms_cache
;
298 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
) :
299 wxClientDCImpl( owner
)
305 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
, wxWindow
*pCanvas
) :
306 wxClientDCImpl( owner
)
308 wxCHECK_RET(pCanvas
, wxT("NULL canvas in wxPaintDC ctor"));
310 #ifdef wxHAS_PAINT_DEBUG
311 if (g_isPainting
<= 0)
313 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
316 #endif // wxHAS_PAINT_DEBUG
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 wxPaintDCImpl::wxPaintDCImpl
371 wxPaintDCImpl::~wxPaintDCImpl()
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
* wxPaintDCImpl::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 wxPaintDCImpl::FindInCache
416 // find the entry for this DC in the cache (keyed by the window)
417 WXHDC
wxPaintDCImpl::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 wxPaintDCImpl::FindInCache