DC updates and an associated .Def file update
[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
27 #include "wx/os2/private.h"
28
29 #include "wx/dcclient.h"
30
31 // ----------------------------------------------------------------------------
32 // array/list types
33 // ----------------------------------------------------------------------------
34
35 struct WXDLLEXPORT wxPaintDCInfo
36 {
37 wxPaintDCInfo( wxWindow* pWin
38 ,wxDC* pDC
39 )
40 {
41 m_hWnd = pWin->GetHWND();
42 m_hDC = pDC->GetHDC();
43 m_nCount = 1;
44 }
45
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
50
51 #include "wx/arrimpl.cpp"
52
53 WX_DEFINE_OBJARRAY(wxArrayDCInfo);
54
55 // ----------------------------------------------------------------------------
56 // macros
57 // ----------------------------------------------------------------------------
58
59 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
60 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
61 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
62
63 // ----------------------------------------------------------------------------
64 // global variables
65 // ----------------------------------------------------------------------------
66
67 static RECT g_paintStruct;
68
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__
76
77 // ===========================================================================
78 // implementation
79 // ===========================================================================
80
81 // ----------------------------------------------------------------------------
82 // wxWindowDC
83 // ----------------------------------------------------------------------------
84
85 wxWindowDC::wxWindowDC()
86 {
87 m_pCanvas = NULL;
88 }
89
90 wxWindowDC::wxWindowDC(
91 wxWindow* pTheCanvas
92 )
93 {
94 ERRORID vError;
95 wxString sError;
96
97 m_pCanvas = pTheCanvas;
98 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
99
100 //
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
105 //
106 m_hPS = ::GpiCreatePS( vHabmain
107 ,m_hDC
108 ,&m_PageSize
109 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
110 );
111 ::GpiAssociate(m_hPS, NULLHANDLE);
112 ::GpiAssociate(m_hPS, m_hDC);
113
114 //
115 // Set the wxWindows color table
116 //
117 if (!::GpiCreateLogColorTable( m_hPS
118 ,0L
119 ,LCOLF_CONSECRGB
120 ,0L
121 ,(LONG)wxTheColourDatabase->m_nSize
122 ,(PLONG)wxTheColourDatabase->m_palTable
123 ))
124 {
125 vError = ::WinGetLastError(vHabmain);
126 sError = wxPMErrorToStr(vError);
127 wxLogError("Unable to set current color table. Error: %s\n", sError);
128 }
129 ::GpiCreateLogColorTable( m_hPS
130 ,0L
131 ,LCOLF_RGB
132 ,0L
133 ,0L
134 ,NULL
135 );
136 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
137 ,&m_vRclPaint
138 );
139 InitDC();
140 } // end of wxWindowDC::wxWindowDC
141
142 void wxWindowDC::InitDC()
143 {
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);
149
150 //
151 // Default bg colour is pne of the window
152 //
153 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
154 } // end of wxWindowDC::InitDC
155
156 // ----------------------------------------------------------------------------
157 // wxClientDC
158 // ----------------------------------------------------------------------------
159
160 wxClientDC::wxClientDC()
161 {
162 m_pCanvas = NULL;
163 }
164
165 wxClientDC::wxClientDC(
166 wxWindow* pTheCanvas
167 )
168 {
169 SIZEL vSizl = { 0,0};
170 ERRORID vError;
171 wxString sError;
172
173 m_pCanvas = pTheCanvas;
174
175 //
176 // default under PM is that Window and Client DC's are the same
177 //
178 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
179 m_hPS = ::GpiCreatePS( wxGetInstance()
180 ,m_hDC
181 ,&vSizl
182 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
183 );
184
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 }
198 ::GpiCreateLogColorTable( m_hPS
199 ,0L
200 ,LCOLF_RGB
201 ,0L
202 ,0L
203 ,NULL
204 );
205 //
206 // Set the DC/PS rectangle
207 //
208 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
209 ,&m_vRclPaint
210 );
211 InitDC();
212 } // end of wxClientDC::wxClientDC
213
214 // ----------------------------------------------------------------------------
215 // wxPaintDC
216 // ----------------------------------------------------------------------------
217
218 wxArrayDCInfo wxPaintDC::ms_cache;
219
220 wxPaintDC::wxPaintDC()
221 {
222 m_pCanvas = NULL;
223 m_hDC = 0;
224 }
225
226 wxPaintDC::wxPaintDC(
227 wxWindow* pCanvas
228 )
229 {
230 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
231
232 #ifdef __WXDEBUG__
233 if (g_isPainting <= 0)
234 {
235 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
236 return;
237 }
238 #endif // __WXDEBUG__
239
240 m_pCanvas = pCanvas;
241
242 //
243 // Do we have a DC for this window in the cache?
244 //
245 wxPaintDCInfo* pInfo = FindInCache();
246
247 if (pInfo)
248 {
249 m_hDC = pInfo->m_hDC;
250 pInfo->m_nCount++;
251 }
252 else // not in cache, create a new one
253 {
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;
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 );
278
279 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
280 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
281 ,&m_vRclPaint
282 );
283 }
284
285 m_bIsPaintTime = TRUE;
286 m_hDC = (WXHDC) -1; // to satisfy those anonizmous efforts
287 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
288 }
289 InitDC();
290 } // end of wxPaintDC::wxPaintDC
291
292 wxPaintDC::~wxPaintDC()
293 {
294 if ( m_hDC )
295 {
296 SelectOldObjects(m_hDC);
297
298 size_t nIndex;
299 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
300
301 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
302
303 if ( !--pInfo->m_nCount )
304 {
305 ::WinEndPaint(m_hPS);
306 m_hPS = m_hOldPS;
307 m_bIsPaintTime = FALSE;
308 ms_cache.Remove(nIndex);
309 }
310 //else: cached DC entry is still in use
311
312 // prevent the base class dtor from ReleaseDC()ing it again
313 m_hDC = 0;
314 }
315 }
316
317 wxPaintDCInfo* wxPaintDC::FindInCache(
318 size_t* pIndex
319 ) const
320 {
321 wxPaintDCInfo* pInfo = NULL;
322 size_t nCache = ms_cache.GetCount();
323
324 for (size_t n = 0; n < nCache; n++)
325 {
326 pInfo = &ms_cache[n];
327 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
328 {
329 if (pIndex)
330 *pIndex = n;
331 break;
332 }
333 }
334 return pInfo;
335 } // end of wxPaintDC::FindInCache
336
337 // find the entry for this DC in the cache (keyed by the window)
338 WXHDC 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