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