1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/palmos/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: William Osborne - minimal working wxPalmOS port
8 // Copyright: (c) William Osborne
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 #include "wx/dcclient.h"
28 #include "wx/palmos/dcclient.h"
31 #include "wx/string.h"
33 #include "wx/window.h"
36 // ----------------------------------------------------------------------------
38 // ----------------------------------------------------------------------------
40 struct WXDLLEXPORT wxPaintDCInfo
42 wxPaintDCInfo(wxWindow
*win
, wxPaintDCImpl
*dc
)
44 hwnd
= win
->GetHWND();
49 WXHWND hwnd
; // window for this DC
50 WXHDC hdc
; // the DC handle
51 size_t count
; // usage count
54 #include "wx/arrimpl.cpp"
56 WX_DEFINE_OBJARRAY(wxArrayDCInfo
)
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
67 // a global variable which we check to verify that wxPaintDC are only
68 // created in response to WM_PAINT message - doing this from elsewhere is a
69 // common programming error among wxWidgets programmers and might lead to
70 // very subtle and difficult to debug refresh/repaint bugs.
74 // ===========================================================================
76 // ===========================================================================
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl
, wxPalmDCImpl
)
84 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
) :
89 wxWindowDCImpl::wxWindowDCImpl( wxDC
*owner
, wxWindow
*window
) :
92 wxCHECK_RET( window
, _T("invalid window in wxWindowDCImpl") );
95 void wxWindowDCImpl::InitDC()
98 // since we are a window dc we need to grab the palette from the window
104 void wxWindowDCImpl::DoGetSize(int *width
, int *height
) const
106 wxCHECK_RET( m_window
, _T("wxWindowDCImpl without a window?") );
108 m_window
->GetSize(width
, height
);
111 // ----------------------------------------------------------------------------
113 // ----------------------------------------------------------------------------
115 IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl
, wxWindowDCImpl
)
117 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
) :
118 wxWindowDCImpl( owner
)
122 wxClientDCImpl::wxClientDCImpl( wxDC
*owner
, wxWindow
*window
) :
123 wxWindowDCImpl( owner
)
127 void wxClientDCImpl::InitDC()
129 wxWindowDCImpl::InitDC();
131 // in wxUniv build we must manually do some DC adjustments usually
132 // performed by Windows for us
134 // we also need to take the menu/toolbar manually into account under
135 // Windows CE because they're just another control there, not anything
136 // special as usually under Windows
137 #if defined(__WXUNIVERSAL__) || defined(__WXWINCE__)
138 wxPoint ptOrigin
= m_window
->GetClientAreaOrigin();
139 if ( ptOrigin
.x
|| ptOrigin
.y
)
141 // no need to shift DC origin if shift is null
142 SetDeviceOrigin(ptOrigin
.x
, ptOrigin
.y
);
145 // clip the DC to avoid overwriting the non client area
146 SetClippingRegion(wxPoint(0,0), m_window
->GetClientSize());
147 #endif // __WXUNIVERSAL__ || __WXWINCE__
150 wxClientDCImpl::~wxClientDCImpl()
154 void wxClientDCImpl::DoGetSize(int *width
, int *height
) const
156 wxCHECK_RET( m_window
, _T("wxClientDCImpl without a window?") );
158 m_window
->GetClientSize(width
, height
);
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 // VZ: initial implementation (by JACS) only remembered the last wxPaintDC
166 // created and tried to reuse it - this was supposed to take care of a
167 // situation when a derived class OnPaint() calls base class OnPaint()
168 // because in this case ::BeginPaint() shouldn't be called second time.
170 // I'm not sure how useful this is, however we must remember the HWND
171 // associated with the last HDC as well - otherwise we may (and will!) try
172 // to reuse the HDC for another HWND which is a nice recipe for disaster.
174 // So we store a list of windows for which we already have the DC and not
175 // just one single hDC. This seems to work, but I'm really not sure about
176 // the usefullness of the whole idea - IMHO it's much better to not call
177 // base class OnPaint() at all, or, if we really want to allow it, add a
178 // "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
179 // !NULL instead of creating a new DC.
181 IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl
, wxClientDCImpl
)
183 wxArrayDCInfo
wxPaintDCImpl::ms_cache
;
185 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
) :
186 wxClientDCImpl( owner
)
190 wxPaintDCImpl::wxPaintDCImpl( wxDC
*owner
, wxWindow
*window
) :
191 wxClientDCImpl( owner
)
193 wxCHECK_RET( window
, wxT("NULL canvas in wxPaintDCImpl ctor") );
196 if ( g_isPainting
<= 0 )
198 wxFAIL_MSG( wxT("wxPaintDCImpl may be created only in EVT_PAINT handler!") );
202 #endif // __WXDEBUG__
206 // do we have a DC for this window in the cache?
207 wxPaintDCInfo
*info
= FindInCache();
213 else // not in cache, create a new one
215 //m_hDC = (WXHDC)::BeginPaint(GetHwndOf(m_window), &g_paintStruct);
217 ms_cache
.Add(new wxPaintDCInfo(m_window
, this));
220 // Note: at this point m_hDC can be NULL under MicroWindows, when dragging.
224 // (re)set the DC parameters.
227 // the HDC can have a clipping box (which we didn't set), make sure our
228 // DoGetClippingBox() checks for it
232 wxPaintDCImpl::~wxPaintDCImpl()
236 SelectOldObjects(m_hDC
);
239 wxPaintDCInfo
*info
= FindInCache(&index
);
241 wxCHECK_RET( info
, wxT("existing DC should have a cache entry") );
243 if ( --info
->count
== 0 )
245 //::EndPaint(GetHwndOf(m_window), &g_paintStruct);
247 ms_cache
.RemoveAt(index
);
249 // Reduce the number of bogus reports of non-freed memory
251 if (ms_cache
.IsEmpty())
254 //else: cached DC entry is still in use
256 // prevent the base class dtor from ReleaseDC()ing it again
261 wxPaintDCInfo
*wxPaintDCImpl::FindInCache(size_t *index
) const
263 wxPaintDCInfo
*info
= NULL
;
264 size_t nCache
= ms_cache
.GetCount();
265 for ( size_t n
= 0; n
< nCache
; n
++ )
267 wxPaintDCInfo
*info1
= &ms_cache
[n
];
268 if ( info1
->hwnd
== m_window
->GetHWND() )
280 // find the entry for this DC in the cache (keyed by the window)
281 WXHDC
wxPaintDCImpl::FindDCInCache(wxWindow
* win
)
283 size_t nCache
= ms_cache
.GetCount();
284 for ( size_t n
= 0; n
< nCache
; n
++ )
286 wxPaintDCInfo
*info
= &ms_cache
[n
];
287 if ( info
->hwnd
== win
->GetHWND() )