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