]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
wxDialUpManager fixes
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose: wxClientDC class
23e4b7d8 4// Author: Julian Smart
0e320a79
DW
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
23e4b7d8
DW
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20#ifdef __GNUG__
21 #pragma implementation "dcclient.h"
22#endif
0e320a79 23
23e4b7d8
DW
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
0e320a79 26
23e4b7d8
DW
27#ifdef __BORLANDC__
28 #pragma hdrstop
0e320a79
DW
29#endif
30
23e4b7d8
DW
31#include "wx/string.h"
32#include "wx/log.h"
33#include "wx/window.h"
0e320a79 34
ce44c50e 35#include "wx/os2/private.h"
0e320a79 36
23e4b7d8 37#include "wx/dcclient.h"
0e320a79 38
23e4b7d8
DW
39// ----------------------------------------------------------------------------
40// array/list types
41// ----------------------------------------------------------------------------
0e320a79 42
23e4b7d8 43struct WXDLLEXPORT wxPaintDCInfo
0e320a79 44{
23e4b7d8
DW
45 wxPaintDCInfo(wxWindow *win, wxDC *dc)
46 {
47 hwnd = win->GetHWND();
48 hdc = dc->GetHDC();
49 count = 1;
50 }
0e320a79 51
23e4b7d8
DW
52 WXHWND hwnd; // window for this DC
53 WXHDC hdc; // the DC handle
54 size_t count; // usage count
0e320a79
DW
55};
56
23e4b7d8 57#include "wx/arrimpl.cpp"
1408104d 58
23e4b7d8 59WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 60
23e4b7d8
DW
61// ----------------------------------------------------------------------------
62// macros
63// ----------------------------------------------------------------------------
0e320a79 64
23e4b7d8
DW
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
0e320a79 70
23e4b7d8
DW
71// ----------------------------------------------------------------------------
72// global variables
73// ----------------------------------------------------------------------------
1408104d 74
ce44c50e 75static RECT g_paintStruct;
1408104d 76
23e4b7d8
DW
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__
1408104d 84
23e4b7d8
DW
85// ===========================================================================
86// implementation
87// ===========================================================================
1408104d 88
23e4b7d8
DW
89// ----------------------------------------------------------------------------
90// wxWindowDC
91// ----------------------------------------------------------------------------
0e320a79 92
23e4b7d8 93wxWindowDC::wxWindowDC()
0e320a79 94{
23e4b7d8
DW
95 m_canvas = NULL;
96}
0e320a79 97
23e4b7d8 98wxWindowDC::wxWindowDC(wxWindow *the_canvas)
0e320a79 99{
23e4b7d8
DW
100 m_canvas = the_canvas;
101 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas) );
102 m_hDCCount++;
ce44c50e
DW
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);
23e4b7d8
DW
116 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
117}
0e320a79 118
23e4b7d8 119wxWindowDC::~wxWindowDC()
0e320a79 120{
23e4b7d8
DW
121 if (m_canvas && m_hDC)
122 {
123 SelectOldObjects(m_hDC);
1408104d 124
23e4b7d8
DW
125 //
126 // In PM one does not explicitly close or release an open WindowDC
127 // They automatically close with the window, unless explicitly detached
ce44c50e 128 // but we need to destroy our PS
23e4b7d8 129 //
ce44c50e
DW
130 ::GpiAssociate(m_hPS, NULLHANDLE);
131 ::GpiDestroyPS(m_hPS);
132 m_hPS = NULLHANDLE;
133 m_hDC = NULLHANDLE;
23e4b7d8 134 }
1408104d 135
23e4b7d8
DW
136 m_hDCCount--;
137}
0e320a79 138
23e4b7d8
DW
139// ----------------------------------------------------------------------------
140// wxClientDC
141// ----------------------------------------------------------------------------
0e320a79 142
23e4b7d8 143wxClientDC::wxClientDC()
0e320a79 144{
23e4b7d8
DW
145 m_canvas = NULL;
146}
0e320a79 147
23e4b7d8 148wxClientDC::wxClientDC(wxWindow *the_canvas)
0e320a79 149{
23e4b7d8 150 m_canvas = the_canvas;
0e320a79 151
ce44c50e
DW
152 //
153 // default under PM is that Window and Client DC's are the same
154 //
155 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas));
1408104d 156
ce44c50e
DW
157 //
158 // Default mode is BM_LEAVEALONE so we make no call Set the mix
159 //
23e4b7d8
DW
160 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
161}
0e320a79 162
23e4b7d8 163wxClientDC::~wxClientDC()
0e320a79 164{
23e4b7d8 165 if ( m_canvas && GetHdc() )
0e320a79 166 {
23e4b7d8 167 SelectOldObjects(m_hDC);
0e320a79 168
ce44c50e
DW
169 // We don't explicitly release Device contexts in PM and
170 // the cached micro PS is already gone
171
23e4b7d8 172 m_hDC = 0;
0e320a79 173 }
23e4b7d8 174}
0e320a79 175
23e4b7d8
DW
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}
0e320a79 203
23e4b7d8 204wxPaintDC::wxPaintDC(wxWindow *canvas)
0e320a79 205{
23e4b7d8 206 wxCHECK_RET( canvas, _T("NULL canvas in wxPaintDC ctor") );
1408104d 207
23e4b7d8
DW
208#ifdef __WXDEBUG__
209 if ( g_isPainting <= 0 )
210 {
211 wxFAIL_MSG( _T("wxPaintDC may be created only in EVT_PAINT handler!") );
1408104d 212
23e4b7d8
DW
213 return;
214 }
215#endif // __WXDEBUG__
0e320a79 216
23e4b7d8 217 m_canvas = canvas;
1408104d 218
23e4b7d8
DW
219 // do we have a DC for this window in the cache?
220 wxPaintDCInfo *info = FindInCache();
221 if ( info )
0e320a79 222 {
23e4b7d8
DW
223 m_hDC = info->hdc;
224 info->count++;
225 }
226 else // not in cache, create a new one
227 {
ce44c50e 228 m_hDC = (WXHDC)::WinBeginPaint(GetWinHwnd(m_canvas), NULLHANDLE, &g_paintStruct);
23e4b7d8 229 ms_cache.Add(new wxPaintDCInfo(m_canvas, this));
0e320a79 230 }
23e4b7d8 231 SetBackground(wxBrush(m_canvas->GetBackgroundColour(), wxSOLID));
0e320a79
DW
232}
233
23e4b7d8 234wxPaintDC::~wxPaintDC()
0e320a79 235{
23e4b7d8
DW
236 if ( m_hDC )
237 {
238 SelectOldObjects(m_hDC);
0e320a79 239
23e4b7d8
DW
240 size_t index;
241 wxPaintDCInfo *info = FindInCache(&index);
0e320a79 242
23e4b7d8 243 wxCHECK_RET( info, _T("existing DC should have a cache entry") );
0e320a79 244
23e4b7d8
DW
245 if ( !--info->count )
246 {
ce44c50e 247 ::WinEndPaint(m_hPS);
0e320a79 248
23e4b7d8
DW
249 ms_cache.Remove(index);
250 }
251 //else: cached DC entry is still in use
0e320a79 252
23e4b7d8
DW
253 // prevent the base class dtor from ReleaseDC()ing it again
254 m_hDC = 0;
0e320a79
DW
255 }
256}
257
23e4b7d8 258wxPaintDCInfo *wxPaintDC::FindInCache(size_t *index) const
0e320a79 259{
23e4b7d8
DW
260 wxPaintDCInfo *info = NULL;
261 size_t nCache = ms_cache.GetCount();
262 for ( size_t n = 0; n < nCache; n++ )
0e320a79 263 {
23e4b7d8
DW
264 info = &ms_cache[n];
265 if ( info->hwnd == m_canvas->GetHWND() )
266 {
267 if ( index )
268 *index = n;
269 break;
270 }
0e320a79
DW
271 }
272
23e4b7d8
DW
273 return info;
274}