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