]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dcclient.cpp
compile fix for BC++
[wxWidgets.git] / src / os2 / dcclient.cpp
... / ...
CommitLineData
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#ifdef __GNUG__
21 #pragma implementation "dcclient.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#include "wx/string.h"
32#include "wx/log.h"
33#include "wx/window.h"
34
35#include "wx/os2/private.h"
36
37#include "wx/dcclient.h"
38
39// ----------------------------------------------------------------------------
40// array/list types
41// ----------------------------------------------------------------------------
42
43struct WXDLLEXPORT wxPaintDCInfo
44{
45 wxPaintDCInfo(wxWindow *win, wxDC *dc)
46 {
47 hwnd = win->GetHWND();
48 hdc = dc->GetHDC();
49 count = 1;
50 }
51
52 WXHWND hwnd; // window for this DC
53 WXHDC hdc; // the DC handle
54 size_t count; // usage count
55};
56
57#include "wx/arrimpl.cpp"
58
59WX_DEFINE_OBJARRAY(wxArrayDCInfo);
60
61// ----------------------------------------------------------------------------
62// macros
63// ----------------------------------------------------------------------------
64
65#if !USE_SHARED_LIBRARY
66 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
67 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
68 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
69#endif
70
71// ----------------------------------------------------------------------------
72// global variables
73// ----------------------------------------------------------------------------
74
75static RECT g_paintStruct;
76
77#ifdef __WXDEBUG__
78 // a global variable which we check to verify that wxPaintDC are only
79 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
80 // common programming error among wxWindows programmers and might lead to
81 // very subtle and difficult to debug refresh/repaint bugs.
82 int g_isPainting = 0;
83#endif // __WXDEBUG__
84
85// ===========================================================================
86// implementation
87// ===========================================================================
88
89// ----------------------------------------------------------------------------
90// wxWindowDC
91// ----------------------------------------------------------------------------
92
93wxWindowDC::wxWindowDC()
94{
95 m_canvas = NULL;
96}
97
98wxWindowDC::wxWindowDC(wxWindow *the_canvas)
99{
100 m_canvas = the_canvas;
101 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas) );
102 m_hDCCount++;
103 //
104 // default under PM is that Window and Client DC's are the same
105 // so we offer a separate Presentation Space to use for the
106 // entire window. Otherwise, calling BeginPaint will just create
107 // chached-micro client presentation space
108 //
109 m_hPS = GpiCreatePS( m_hab
110 ,m_hDC
111 ,&m_PageSize
112 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
113 );
114 ::GpiAssociate(m_hPS, NULLHANDLE);
115 ::GpiAssociate(m_hPS, m_hDC);
116 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
117}
118
119wxWindowDC::~wxWindowDC()
120{
121 if (m_canvas && m_hDC)
122 {
123 SelectOldObjects(m_hDC);
124
125 //
126 // In PM one does not explicitly close or release an open WindowDC
127 // They automatically close with the window, unless explicitly detached
128 // but we need to destroy our PS
129 //
130 ::GpiAssociate(m_hPS, NULLHANDLE);
131 ::GpiDestroyPS(m_hPS);
132 m_hPS = NULLHANDLE;
133 m_hDC = NULLHANDLE;
134 }
135
136 m_hDCCount--;
137}
138
139// ----------------------------------------------------------------------------
140// wxClientDC
141// ----------------------------------------------------------------------------
142
143wxClientDC::wxClientDC()
144{
145 m_canvas = NULL;
146}
147
148wxClientDC::wxClientDC(wxWindow *the_canvas)
149{
150 m_canvas = the_canvas;
151
152 //
153 // default under PM is that Window and Client DC's are the same
154 //
155 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas));
156
157 //
158 // Default mode is BM_LEAVEALONE so we make no call Set the mix
159 //
160 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
161}
162
163wxClientDC::~wxClientDC()
164{
165 if ( m_canvas && GetHdc() )
166 {
167 SelectOldObjects(m_hDC);
168
169 // We don't explicitly release Device contexts in PM and
170 // the cached micro PS is already gone
171
172 m_hDC = 0;
173 }
174}
175
176// ----------------------------------------------------------------------------
177// wxPaintDC
178// ----------------------------------------------------------------------------
179
180// VZ: initial implementation (by JACS) only remembered the last wxPaintDC
181// created and tried to reuse - this was supposed to take care of a
182// situation when a derived class OnPaint() calls base class OnPaint()
183// because in this case ::BeginPaint() shouldn't be called second time.
184//
185// I'm not sure how useful this is, however we must remember the HWND
186// associated with the last HDC as well - otherwise we may (and will!) try
187// to reuse the HDC for another HWND which is a nice recipe for disaster.
188//
189// So we store a list of windows for which we already have the DC and not
190// just one single hDC. This seems to work, but I'm really not sure about
191// the usefullness of the whole idea - IMHO it's much better to not call
192// base class OnPaint() at all, or, if we really want to allow it, add a
193// "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
194// !NULL instead of creating a new DC.
195
196wxArrayDCInfo wxPaintDC::ms_cache;
197
198wxPaintDC::wxPaintDC()
199{
200 m_canvas = NULL;
201 m_hDC = 0;
202}
203
204wxPaintDC::wxPaintDC(wxWindow *canvas)
205{
206 wxCHECK_RET( canvas, T("NULL canvas in wxPaintDC ctor") );
207
208#ifdef __WXDEBUG__
209 if ( g_isPainting <= 0 )
210 {
211 wxFAIL_MSG( T("wxPaintDC may be created only in EVT_PAINT handler!") );
212
213 return;
214 }
215#endif // __WXDEBUG__
216
217 m_canvas = canvas;
218
219 // do we have a DC for this window in the cache?
220 wxPaintDCInfo *info = FindInCache();
221 if ( info )
222 {
223 m_hDC = info->hdc;
224 info->count++;
225 }
226 else // not in cache, create a new one
227 {
228 m_hDC = (WXHDC)::WinBeginPaint(GetWinHwnd(m_canvas), NULLHANDLE, &g_paintStruct);
229 ms_cache.Add(new wxPaintDCInfo(m_canvas, this));
230 }
231 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
232}
233
234wxPaintDC::~wxPaintDC()
235{
236 if ( m_hDC )
237 {
238 SelectOldObjects(m_hDC);
239
240 size_t index;
241 wxPaintDCInfo *info = FindInCache(&index);
242
243 wxCHECK_RET( info, T("existing DC should have a cache entry") );
244
245 if ( !--info->count )
246 {
247 ::WinEndPaint(m_hPS);
248
249 ms_cache.Remove(index);
250 }
251 //else: cached DC entry is still in use
252
253 // prevent the base class dtor from ReleaseDC()ing it again
254 m_hDC = 0;
255 }
256}
257
258wxPaintDCInfo *wxPaintDC::FindInCache(size_t *index) const
259{
260 wxPaintDCInfo *info = NULL;
261 size_t nCache = ms_cache.GetCount();
262 for ( size_t n = 0; n < nCache; n++ )
263 {
264 info = &ms_cache[n];
265 if ( info->hwnd == m_canvas->GetHWND() )
266 {
267 if ( index )
268 *index = n;
269 break;
270 }
271 }
272
273 return info;
274}