]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dcclient.cpp
Avoid clash with control container event handlers
[wxWidgets.git] / src / os2 / dcclient.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/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/dcclient.h"
24
25#ifndef WX_PRECOMP
26 #include "wx/string.h"
27 #include "wx/log.h"
28 #include "wx/app.h"
29 #include "wx/window.h"
30#endif
31
32#include "wx/os2/private.h"
33
34// ----------------------------------------------------------------------------
35// array/list types
36// ----------------------------------------------------------------------------
37
38struct WXDLLEXPORT wxPaintDCInfo
39{
40 wxPaintDCInfo( wxWindow* pWin
41 ,wxDC* pDC
42 )
43 {
44 m_hWnd = pWin->GetHWND();
45 m_hDC = pDC->GetHDC();
46 m_nCount = 1;
47 }
48
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
53
54#include "wx/arrimpl.cpp"
55
56WX_DEFINE_OBJARRAY(wxArrayDCInfo);
57
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
62 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
63 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
64 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
65
66// ----------------------------------------------------------------------------
67// global variables
68// ----------------------------------------------------------------------------
69
70static RECT g_paintStruct;
71
72#ifdef __WXDEBUG__
73 // a global variable which we check to verify that wxPaintDC are only
74 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
75 // common programming error among wxWidgets programmers and might lead to
76 // very subtle and difficult to debug refresh/repaint bugs.
77 int g_isPainting = 0;
78#endif // __WXDEBUG__
79
80// ===========================================================================
81// implementation
82// ===========================================================================
83
84// ----------------------------------------------------------------------------
85// wxWindowDC
86// ----------------------------------------------------------------------------
87
88wxWindowDC::wxWindowDC()
89{
90 m_pCanvas = NULL;
91 m_PageSize.cx = m_PageSize.cy = 0;
92
93}
94
95wxWindowDC::wxWindowDC(
96 wxWindow* pTheCanvas
97)
98{
99 ERRORID vError;
100 wxString sError;
101 int nWidth, nHeight;
102
103 m_pCanvas = pTheCanvas;
104 DoGetSize(&nWidth, &nHeight);
105 m_PageSize.cx = nWidth;
106 m_PageSize.cy = nHeight;
107 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
108
109 //
110 // default under PM is that Window and Client DC's are the same
111 // so we offer a separate Presentation Space to use for the
112 // entire window. Otherwise, calling BeginPaint will just create
113 // chached-micro client presentation space
114 //
115 m_hPS = ::GpiCreatePS( vHabmain
116 ,m_hDC
117 ,&m_PageSize
118 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
119 );
120 if (!m_hPS)
121 {
122 vError = ::WinGetLastError(vHabmain);
123 sError = wxPMErrorToStr(vError);
124 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError.c_str());
125 }
126 ::GpiAssociate(m_hPS, NULLHANDLE);
127 ::GpiAssociate(m_hPS, m_hDC);
128
129 //
130 // Set the wxWidgets color table
131 //
132 if (!::GpiCreateLogColorTable( m_hPS
133 ,0L
134 ,LCOLF_CONSECRGB
135 ,0L
136 ,(LONG)wxTheColourDatabase->m_nSize
137 ,(PLONG)wxTheColourDatabase->m_palTable
138 ))
139 {
140 vError = ::WinGetLastError(vHabmain);
141 sError = wxPMErrorToStr(vError);
142 wxLogError(_T("Unable to set current color table (3). Error: %s\n"), sError.c_str());
143 }
144 ::GpiCreateLogColorTable( m_hPS
145 ,0L
146 ,LCOLF_RGB
147 ,0L
148 ,0L
149 ,NULL
150 );
151 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
152 ,&m_vRclPaint
153 );
154 InitDC();
155} // end of wxWindowDC::wxWindowDC
156
157void wxWindowDC::InitDC()
158{
159
160 //
161 // The background mode is only used for text background and is set in
162 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
163 //
164 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
165
166 //
167 // Default bg colour is pne of the window
168 //
169 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
170
171 m_pen.SetColour(*wxBLACK);
172 m_brush.SetColour(*wxWHITE);
173 InitializePalette();
174 wxFont* pFont = new wxFont( 10, wxMODERN, wxNORMAL, wxBOLD );
175 SetFont(*pFont);
176 delete pFont;
177 //
178 // OS/2 default vertical character alignment needs to match the other OS's
179 //
180 ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
181
182} // end of wxWindowDC::InitDC
183
184void wxWindowDC::DoGetSize(
185 int* pnWidth
186, int* pnHeight
187) const
188{
189 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
190 m_pCanvas->GetSize( pnWidth
191 ,pnHeight
192 );
193} // end of wxWindowDC::DoGetSize
194
195// ----------------------------------------------------------------------------
196// wxClientDC
197// ----------------------------------------------------------------------------
198
199wxClientDC::wxClientDC()
200{
201 m_pCanvas = NULL;
202}
203
204wxClientDC::wxClientDC(
205 wxWindow* pTheCanvas
206)
207{
208 SIZEL vSizl = { 0,0};
209 ERRORID vError;
210 wxString sError;
211
212 m_pCanvas = pTheCanvas;
213
214 //
215 // default under PM is that Window and Client DC's are the same
216 //
217 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
218 m_hPS = ::GpiCreatePS( wxGetInstance()
219 ,m_hDC
220 ,&vSizl
221 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
222 );
223
224 // Set the wxWidgets color table
225 if (!::GpiCreateLogColorTable( m_hPS
226 ,0L
227 ,LCOLF_CONSECRGB
228 ,0L
229 ,(LONG)wxTheColourDatabase->m_nSize
230 ,(PLONG)wxTheColourDatabase->m_palTable
231 ))
232 {
233 vError = ::WinGetLastError(vHabmain);
234 sError = wxPMErrorToStr(vError);
235 wxLogError(_T("Unable to set current color table (4). Error: %s\n"), sError.c_str());
236 }
237 ::GpiCreateLogColorTable( m_hPS
238 ,0L
239 ,LCOLF_RGB
240 ,0L
241 ,0L
242 ,NULL
243 );
244 //
245 // Set the DC/PS rectangle
246 //
247 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
248 ,&m_vRclPaint
249 );
250 InitDC();
251} // end of wxClientDC::wxClientDC
252
253void wxClientDC::InitDC()
254{
255 wxWindowDC::InitDC();
256
257 // in wxUniv build we must manually do some DC adjustments usually
258 // performed by Windows for us
259#ifdef __WXUNIVERSAL__
260 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
261 if ( ptOrigin.x || ptOrigin.y )
262 {
263 // no need to shift DC origin if shift is null
264 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
265 }
266
267 // clip the DC to avoid overwriting the non client area
268 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
269#endif // __WXUNIVERSAL__
270} // end of wxClientDC::InitDC
271
272wxClientDC::~wxClientDC()
273{
274} // end of wxClientDC::~wxClientDC
275
276void wxClientDC::DoGetSize(
277 int* pnWidth
278, int* pnHeight
279) const
280{
281 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
282 m_pCanvas->GetClientSize( pnWidth
283 ,pnHeight
284 );
285} // end of wxClientDC::DoGetSize
286
287// ----------------------------------------------------------------------------
288// wxPaintDC
289// ----------------------------------------------------------------------------
290
291wxArrayDCInfo wxPaintDC::ms_cache;
292
293wxPaintDC::wxPaintDC()
294{
295 m_pCanvas = NULL;
296 m_hDC = 0;
297}
298
299wxPaintDC::wxPaintDC(
300 wxWindow* pCanvas
301)
302{
303 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
304
305#ifdef __WXDEBUG__
306 if (g_isPainting <= 0)
307 {
308 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
309 return;
310 }
311#endif // __WXDEBUG__
312
313 m_pCanvas = pCanvas;
314
315 //
316 // Do we have a DC for this window in the cache?
317 //
318 wxPaintDCInfo* pInfo = FindInCache();
319
320 if (pInfo)
321 {
322 m_hDC = pInfo->m_hDC;
323 pInfo->m_nCount++;
324 }
325 else // not in cache, create a new one
326 {
327 HPS hPS;
328
329 m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
330 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
331 ,NULLHANDLE
332 ,&g_paintStruct
333 );
334 if(hPS)
335 {
336 ::GpiAssociate(hPS, m_hDC);
337 m_hOldPS = m_hPS;
338 m_hPS = hPS;
339 ::GpiCreateLogColorTable( m_hPS
340 ,0L
341 ,LCOLF_CONSECRGB
342 ,0L
343 ,(LONG)wxTheColourDatabase->m_nSize
344 ,(PLONG)wxTheColourDatabase->m_palTable
345 );
346 ::GpiCreateLogColorTable( m_hPS
347 ,0L
348 ,LCOLF_RGB
349 ,0L
350 ,0L
351 ,NULL
352 );
353
354 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
355 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
356 ,&m_vRclPaint
357 );
358 }
359
360 m_bIsPaintTime = true;
361 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
362 }
363 InitDC();
364} // end of wxPaintDC::wxPaintDC
365
366wxPaintDC::~wxPaintDC()
367{
368 if ( m_hDC )
369 {
370 SelectOldObjects(m_hDC);
371
372 size_t nIndex;
373 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
374
375 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
376
377 if ( !--pInfo->m_nCount )
378 {
379 ::WinEndPaint(m_hPS);
380 m_hPS = m_hOldPS;
381 m_bIsPaintTime = false;
382 ms_cache.RemoveAt(nIndex);
383 }
384 //else: cached DC entry is still in use
385
386 // prevent the base class dtor from ReleaseDC()ing it again
387 m_hDC = 0;
388 }
389}
390
391wxPaintDCInfo* wxPaintDC::FindInCache(
392 size_t* pIndex
393) const
394{
395 wxPaintDCInfo* pInfo = NULL;
396 size_t nCache = ms_cache.GetCount();
397
398 for (size_t n = 0; n < nCache; n++)
399 {
400 pInfo = &ms_cache[n];
401 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
402 {
403 if (pIndex)
404 *pIndex = n;
405 break;
406 }
407 }
408 return pInfo;
409} // end of wxPaintDC::FindInCache
410
411// find the entry for this DC in the cache (keyed by the window)
412WXHDC wxPaintDC::FindDCInCache(
413 wxWindow* pWin
414)
415{
416 wxPaintDCInfo* pInfo = NULL;
417 size_t nCache = ms_cache.GetCount();
418
419 for (size_t n = 0; n < nCache; n++)
420 {
421 pInfo = &ms_cache[n];
422 if (pInfo->m_hWnd == pWin->GetHWND())
423 {
424 return pInfo->m_hDC;
425 }
426 }
427 return 0;
428} // end of wxPaintDC::FindInCache