]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
Fix to excule OnPaint from WXPM
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose: wxClientDC class
f0a56ab0 4// Author: David Webster
0e320a79 5// Modified by:
f0a56ab0 6// Created: 09/21/99
0e320a79 7// RCS-ID: $Id$
f0a56ab0 8// Copyright: (c) David Webster
23e4b7d8 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
0e320a79 22
23e4b7d8
DW
23#include "wx/string.h"
24#include "wx/log.h"
25#include "wx/window.h"
0e320a79 26
ce44c50e 27#include "wx/os2/private.h"
0e320a79 28
23e4b7d8 29#include "wx/dcclient.h"
0e320a79 30
23e4b7d8
DW
31// ----------------------------------------------------------------------------
32// array/list types
33// ----------------------------------------------------------------------------
0e320a79 34
23e4b7d8 35struct WXDLLEXPORT wxPaintDCInfo
0e320a79 36{
e99762c0
DW
37 wxPaintDCInfo( wxWindow* pWin
38 ,wxDC* pDC
39 )
23e4b7d8 40 {
e99762c0
DW
41 m_hWnd = pWin->GetHWND();
42 m_hDC = pDC->GetHDC();
43 m_nCount = 1;
23e4b7d8 44 }
0e320a79 45
e99762c0
DW
46 WXHWND m_hWnd; // window for this DC
47 WXHDC m_hDC; // the DC handle
48 size_t m_nCount; // usage count
49}; // end of wxPaintDCInfot
0e320a79 50
23e4b7d8 51#include "wx/arrimpl.cpp"
1408104d 52
23e4b7d8 53WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 54
23e4b7d8
DW
55// ----------------------------------------------------------------------------
56// macros
57// ----------------------------------------------------------------------------
0e320a79 58
23e4b7d8
DW
59 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
60 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
61 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
0e320a79 62
23e4b7d8
DW
63// ----------------------------------------------------------------------------
64// global variables
65// ----------------------------------------------------------------------------
1408104d 66
ce44c50e 67static RECT g_paintStruct;
1408104d 68
23e4b7d8
DW
69#ifdef __WXDEBUG__
70 // a global variable which we check to verify that wxPaintDC are only
71 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
72 // common programming error among wxWindows programmers and might lead to
73 // very subtle and difficult to debug refresh/repaint bugs.
74 int g_isPainting = 0;
75#endif // __WXDEBUG__
1408104d 76
23e4b7d8
DW
77// ===========================================================================
78// implementation
79// ===========================================================================
1408104d 80
23e4b7d8
DW
81// ----------------------------------------------------------------------------
82// wxWindowDC
83// ----------------------------------------------------------------------------
0e320a79 84
23e4b7d8 85wxWindowDC::wxWindowDC()
0e320a79 86{
26ac77db 87 m_pCanvas = NULL;
23e4b7d8 88}
0e320a79 89
e99762c0
DW
90wxWindowDC::wxWindowDC(
91 wxWindow* pTheCanvas
92)
0e320a79 93{
26ac77db
DW
94 ERRORID vError;
95 wxString sError;
1408104d 96
e99762c0
DW
97 m_pCanvas = pTheCanvas;
98 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
e1a688e4 99
23e4b7d8 100 //
26ac77db
DW
101 // default under PM is that Window and Client DC's are the same
102 // so we offer a separate Presentation Space to use for the
103 // entire window. Otherwise, calling BeginPaint will just create
104 // chached-micro client presentation space
23e4b7d8 105 //
e1a688e4
DW
106 m_hPS = ::GpiCreatePS( vHabmain
107 ,m_hDC
108 ,&m_PageSize
109 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
110 );
26ac77db
DW
111 ::GpiAssociate(m_hPS, NULLHANDLE);
112 ::GpiAssociate(m_hPS, m_hDC);
e1a688e4
DW
113
114 //
26ac77db 115 // Set the wxWindows color table
e1a688e4 116 //
26ac77db
DW
117 if (!::GpiCreateLogColorTable( m_hPS
118 ,0L
119 ,LCOLF_CONSECRGB
120 ,0L
121 ,(LONG)wxTheColourDatabase->m_nSize
122 ,(PLONG)wxTheColourDatabase->m_palTable
123 ))
7e99520b 124 {
26ac77db
DW
125 vError = ::WinGetLastError(vHabmain);
126 sError = wxPMErrorToStr(vError);
127 wxLogError("Unable to set current color table. Error: %s\n", sError);
7e99520b 128 }
5afb9458
DW
129 ::GpiCreateLogColorTable( m_hPS
130 ,0L
131 ,LCOLF_RGB
132 ,0L
133 ,0L
134 ,NULL
135 );
5afb9458
DW
136 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
137 ,&m_vRclPaint
138 );
e1a688e4
DW
139 InitDC();
140} // end of wxWindowDC::wxWindowDC
1408104d 141
e1a688e4 142void wxWindowDC::InitDC()
26ac77db 143{
e1a688e4
DW
144 //
145 // The background mode is only used for text background and is set in
146 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
147 //
148 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
26ac77db 149
e1a688e4
DW
150 //
151 // Default bg colour is pne of the window
152 //
153 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
154} // end of wxWindowDC::InitDC
0e320a79 155
23e4b7d8
DW
156// ----------------------------------------------------------------------------
157// wxClientDC
158// ----------------------------------------------------------------------------
0e320a79 159
23e4b7d8 160wxClientDC::wxClientDC()
0e320a79 161{
26ac77db 162 m_pCanvas = NULL;
23e4b7d8 163}
0e320a79 164
e99762c0
DW
165wxClientDC::wxClientDC(
166 wxWindow* pTheCanvas
167)
0e320a79 168{
7e99520b 169 SIZEL vSizl = { 0,0};
26ac77db
DW
170 ERRORID vError;
171 wxString sError;
0e320a79 172
e99762c0 173 m_pCanvas = pTheCanvas;
1408104d 174
7e99520b
DW
175 //
176 // default under PM is that Window and Client DC's are the same
177 //
e99762c0 178 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
7e99520b
DW
179 m_hPS = ::GpiCreatePS( wxGetInstance()
180 ,m_hDC
f44fdfb0 181 ,&vSizl
7e99520b
DW
182 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
183 );
184
26ac77db
DW
185 // Set the wxWindows color table
186 if (!::GpiCreateLogColorTable( m_hPS
187 ,0L
188 ,LCOLF_CONSECRGB
189 ,0L
190 ,(LONG)wxTheColourDatabase->m_nSize
191 ,(PLONG)wxTheColourDatabase->m_palTable
192 ))
193 {
194 vError = ::WinGetLastError(vHabmain);
195 sError = wxPMErrorToStr(vError);
196 wxLogError("Unable to set current color table. Error: %s\n", sError);
197 }
5afb9458
DW
198 ::GpiCreateLogColorTable( m_hPS
199 ,0L
200 ,LCOLF_RGB
201 ,0L
202 ,0L
203 ,NULL
204 );
7e99520b 205 //
5afb9458
DW
206 // Set the DC/PS rectangle
207 //
208 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
209 ,&m_vRclPaint
210 );
e1a688e4 211 InitDC();
e99762c0 212} // end of wxClientDC::wxClientDC
0e320a79 213
23e4b7d8
DW
214// ----------------------------------------------------------------------------
215// wxPaintDC
216// ----------------------------------------------------------------------------
217
23e4b7d8
DW
218wxArrayDCInfo wxPaintDC::ms_cache;
219
220wxPaintDC::wxPaintDC()
221{
f6bcfd97 222 m_pCanvas = NULL;
23e4b7d8
DW
223 m_hDC = 0;
224}
0e320a79 225
7e99520b
DW
226wxPaintDC::wxPaintDC(
227 wxWindow* pCanvas
228)
0e320a79 229{
f44fdfb0 230 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
1408104d 231
23e4b7d8 232#ifdef __WXDEBUG__
7e99520b 233 if (g_isPainting <= 0)
23e4b7d8 234 {
223d09f6 235 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
23e4b7d8
DW
236 return;
237 }
238#endif // __WXDEBUG__
0e320a79 239
7e99520b 240 m_pCanvas = pCanvas;
1408104d 241
7e99520b
DW
242 //
243 // Do we have a DC for this window in the cache?
244 //
245 wxPaintDCInfo* pInfo = FindInCache();
246
247 if (pInfo)
0e320a79 248 {
e99762c0
DW
249 m_hDC = pInfo->m_hDC;
250 pInfo->m_nCount++;
23e4b7d8
DW
251 }
252 else // not in cache, create a new one
253 {
7e99520b
DW
254 HPS hPS;
255
256 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
257 ,NULLHANDLE
258 ,&g_paintStruct
259 );
260 if(hPS)
261 {
262 m_hOldPS = m_hPS;
263 m_hPS = hPS;
26ac77db
DW
264 ::GpiCreateLogColorTable( m_hPS
265 ,0L
266 ,LCOLF_CONSECRGB
267 ,0L
268 ,(LONG)wxTheColourDatabase->m_nSize
269 ,(PLONG)wxTheColourDatabase->m_palTable
270 );
271 ::GpiCreateLogColorTable( m_hPS
272 ,0L
273 ,LCOLF_RGB
274 ,0L
275 ,0L
276 ,NULL
277 );
8d854fa9
DW
278
279 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
eeff964a
DW
280 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
281 ,&m_vRclPaint
282 );
7e99520b 283 }
e99762c0 284
7e99520b
DW
285 m_bIsPaintTime = TRUE;
286 m_hDC = (WXHDC) -1; // to satisfy those anonizmous efforts
f6bcfd97 287 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
0e320a79 288 }
e1a688e4
DW
289 InitDC();
290} // end of wxPaintDC::wxPaintDC
0e320a79 291
23e4b7d8 292wxPaintDC::~wxPaintDC()
0e320a79 293{
23e4b7d8
DW
294 if ( m_hDC )
295 {
296 SelectOldObjects(m_hDC);
0e320a79 297
e99762c0
DW
298 size_t nIndex;
299 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
0e320a79 300
e99762c0 301 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
0e320a79 302
e99762c0 303 if ( !--pInfo->m_nCount )
23e4b7d8 304 {
ce44c50e 305 ::WinEndPaint(m_hPS);
f44fdfb0 306 m_hPS = m_hOldPS;
7e99520b 307 m_bIsPaintTime = FALSE;
e99762c0 308 ms_cache.Remove(nIndex);
23e4b7d8
DW
309 }
310 //else: cached DC entry is still in use
0e320a79 311
23e4b7d8
DW
312 // prevent the base class dtor from ReleaseDC()ing it again
313 m_hDC = 0;
0e320a79
DW
314 }
315}
316
e99762c0
DW
317wxPaintDCInfo* wxPaintDC::FindInCache(
318 size_t* pIndex
319) const
0e320a79 320{
e99762c0
DW
321 wxPaintDCInfo* pInfo = NULL;
322 size_t nCache = ms_cache.GetCount();
323
324 for (size_t n = 0; n < nCache; n++)
0e320a79 325 {
e99762c0
DW
326 pInfo = &ms_cache[n];
327 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
23e4b7d8 328 {
e99762c0
DW
329 if (pIndex)
330 *pIndex = n;
23e4b7d8
DW
331 break;
332 }
0e320a79 333 }
e99762c0
DW
334 return pInfo;
335} // end of wxPaintDC::FindInCache
0e320a79 336
e1a688e4
DW
337// find the entry for this DC in the cache (keyed by the window)
338WXHDC wxPaintDC::FindDCInCache(
339 wxWindow* pWin
340)
341{
342 wxPaintDCInfo* pInfo = NULL;
343 size_t nCache = ms_cache.GetCount();
344
345 for (size_t n = 0; n < nCache; n++)
346 {
347 pInfo = &ms_cache[n];
348 if (pInfo->m_hWnd == pWin->GetHWND())
349 {
350 return pInfo->m_hDC;
351 }
352 }
353 return 0;
354} // end of wxPaintDC::FindInCache
355