]> git.saurik.com Git - wxWidgets.git/blame - src/msw/region.cpp
WXUNUSED_UNLESS_ODRAWN does not reflect wxUSE_MENUS_NATIVE.
[wxWidgets.git] / src / msw / region.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
789295bf 2// Name: msw/region.cpp
2b5f62a0 3// Purpose: wxRegion implementation using Win32 API
6c9a19aa 4// Author: Vadim Zeitlin
a3b46648 5// Modified by:
2bda0e17 6// Created: Fri Oct 24 10:46:34 MET 1997
789295bf 7// RCS-ID: $Id$
77ffb593 8// Copyright: (c) 1997-2002 wxWidgets team
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
2b5f62a0
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
2b5f62a0 21 #pragma implementation "region.h"
2bda0e17
KB
22#endif
23
a3b46648 24// For compilers that support precompilation, includes "wx.h".
2bda0e17
KB
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28#pragma hdrstop
29#endif
30
2b5f62a0 31#include "wx/region.h"
2bda0e17
KB
32#include "wx/gdicmn.h"
33
789295bf 34#include "wx/msw/private.h"
2bda0e17 35
2c40e41c
VZ
36IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
37IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
2bda0e17 38
2b5f62a0 39// ----------------------------------------------------------------------------
2bda0e17 40// wxRegionRefData implementation
2b5f62a0 41// ----------------------------------------------------------------------------
2bda0e17 42
789295bf
VZ
43class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
44{
2bda0e17 45public:
789295bf
VZ
46 wxRegionRefData()
47 {
b823f5a1 48 m_region = 0;
789295bf 49 }
2bda0e17 50
789295bf
VZ
51 wxRegionRefData(const wxRegionRefData& data)
52 {
4676948b 53#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
2bda0e17
KB
54 DWORD noBytes = ::GetRegionData(data.m_region, 0, NULL);
55 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
789295bf 56 ::GetRegionData(data.m_region, noBytes, rgnData);
2bda0e17
KB
57 m_region = ::ExtCreateRegion(NULL, noBytes, rgnData);
58 delete[] (char*) rgnData;
59#else
60 RECT rect;
61 ::GetRgnBox(data.m_region, &rect);
62 m_region = ::CreateRectRgnIndirect(&rect);
63#endif
789295bf 64 }
2bda0e17 65
2b5f62a0 66 virtual ~wxRegionRefData()
789295bf
VZ
67 {
68 ::DeleteObject(m_region);
2bda0e17 69 m_region = 0;
789295bf 70 }
2bda0e17 71
789295bf 72 HRGN m_region;
22f3361e
VZ
73
74private:
75// Cannot use
76// DECLARE_NO_COPY_CLASS(wxRegionRefData)
77// because copy constructor is explicitly declared above;
78// but no copy assignment operator is defined, so declare
79// it private to prevent the compiler from defining it:
80 wxRegionRefData& operator=(const wxRegionRefData&);
2bda0e17
KB
81};
82
83#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
3317223b 84#define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_region)
2bda0e17 85
2b5f62a0
VZ
86// ============================================================================
87// wxRegion implementation
88// ============================================================================
89
90// ----------------------------------------------------------------------------
91// ctors and dtor
92// ----------------------------------------------------------------------------
2bda0e17 93
789295bf 94wxRegion::wxRegion()
2bda0e17 95{
f7bd3a7d 96 m_refData = (wxRegionRefData *)NULL;
2bda0e17
KB
97}
98
81d66cf3
JS
99wxRegion::wxRegion(WXHRGN hRegion)
100{
101 m_refData = new wxRegionRefData;
102 M_REGION = (HRGN) hRegion;
103}
104
9b1801c1 105wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
2bda0e17
KB
106{
107 m_refData = new wxRegionRefData;
108 M_REGION = ::CreateRectRgn(x, y, x + w, y + h);
109}
110
111wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
112{
113 m_refData = new wxRegionRefData;
114 M_REGION = ::CreateRectRgn(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
115}
116
117wxRegion::wxRegion(const wxRect& rect)
118{
119 m_refData = new wxRegionRefData;
bc2e39e3 120 M_REGION = ::CreateRectRgn(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
2bda0e17
KB
121}
122
5549e9f7
VZ
123wxRegion::wxRegion(size_t n, const wxPoint *points, int fillStyle)
124{
4676948b 125#if defined(__WXMICROWIN__) || defined(__WXWINCE__)
17a6a2e0
WS
126 wxUnusedVar(n);
127 wxUnusedVar(points);
128 wxUnusedVar(fillStyle);
c67d6888
JS
129 m_refData = NULL;
130 M_REGION = NULL;
131#else
5549e9f7
VZ
132 m_refData = new wxRegionRefData;
133 M_REGION = ::CreatePolygonRgn
134 (
135 (POINT*)points,
136 n,
137 fillStyle == wxODDEVEN_RULE ? ALTERNATE : WINDING
138 );
c67d6888 139#endif
5549e9f7
VZ
140}
141
789295bf 142wxRegion::~wxRegion()
2bda0e17
KB
143{
144 // m_refData unrefed in ~wxObject
145}
146
02576308 147wxObjectRefData *wxRegion::CreateRefData() const
0fb067bb
VZ
148{
149 return new wxRegionRefData;
150}
151
b8027888 152wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
0fb067bb
VZ
153{
154 return new wxRegionRefData(*(wxRegionRefData *)data);
155}
156
2b5f62a0
VZ
157// ----------------------------------------------------------------------------
158// wxRegion operations
159// ----------------------------------------------------------------------------
2bda0e17 160
789295bf
VZ
161// Clear current region
162void wxRegion::Clear()
2bda0e17 163{
789295bf 164 UnRef();
2bda0e17
KB
165}
166
0fb067bb
VZ
167bool wxRegion::Offset(wxCoord x, wxCoord y)
168{
4d08943e 169 wxCHECK_MSG( M_REGION, false, _T("invalid wxRegion") );
3317223b 170
0fb067bb
VZ
171 if ( !x && !y )
172 {
173 // nothing to do
4d08943e 174 return true;
0fb067bb
VZ
175 }
176
177 AllocExclusive();
178
179 if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR )
180 {
181 wxLogLastError(_T("OffsetRgn"));
182
4d08943e 183 return false;
0fb067bb
VZ
184 }
185
4d08943e 186 return true;
0fb067bb
VZ
187}
188
3317223b
VZ
189// combine another region with this one
190bool wxRegion::Combine(const wxRegion& rgn, wxRegionOp op)
2bda0e17 191{
3317223b
VZ
192 // we can't use the API functions if we don't have a valid region handle
193 if ( !m_refData )
2bda0e17 194 {
3317223b
VZ
195 // combining with an empty/invalid region works differently depending
196 // on the operation
197 switch ( op )
198 {
199 case wxRGN_COPY:
200 case wxRGN_OR:
201 case wxRGN_XOR:
202 *this = rgn;
203 break;
204
205 default:
206 wxFAIL_MSG( _T("unknown region operation") );
207 // fall through
208
209 case wxRGN_AND:
210 case wxRGN_DIFF:
211 // leave empty/invalid
4d08943e 212 return false;
3317223b 213 }
2bda0e17 214 }
3317223b 215 else // we have a valid region
0fb067bb 216 {
2b5f62a0
VZ
217 AllocExclusive();
218
3317223b
VZ
219 int mode;
220 switch ( op )
221 {
222 case wxRGN_AND:
223 mode = RGN_AND;
224 break;
2bda0e17 225
3317223b
VZ
226 case wxRGN_OR:
227 mode = RGN_OR;
228 break;
2bda0e17 229
3317223b
VZ
230 case wxRGN_XOR:
231 mode = RGN_XOR;
232 break;
2bda0e17 233
3317223b
VZ
234 case wxRGN_DIFF:
235 mode = RGN_DIFF;
236 break;
789295bf 237
3317223b
VZ
238 default:
239 wxFAIL_MSG( _T("unknown region operation") );
240 // fall through
2bda0e17 241
3317223b
VZ
242 case wxRGN_COPY:
243 mode = RGN_COPY;
244 break;
245 }
246
247 if ( ::CombineRgn(M_REGION, M_REGION, M_REGION_OF(rgn), mode) == ERROR )
248 {
249 wxLogLastError(_T("CombineRgn"));
250
4d08943e 251 return false;
3317223b 252 }
2bda0e17
KB
253 }
254
4d08943e 255 return true;
3317223b
VZ
256}
257
258// Combine rectangle (x, y, w, h) with this.
259bool wxRegion::Combine(wxCoord x, wxCoord y,
260 wxCoord width, wxCoord height,
261 wxRegionOp op)
262{
263 return Combine(wxRegion(x, y, width, height), op);
2bda0e17
KB
264}
265
266bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
267{
3317223b
VZ
268 return Combine(rect.GetLeft(), rect.GetTop(),
269 rect.GetWidth(), rect.GetHeight(), op);
2bda0e17
KB
270}
271
2b5f62a0
VZ
272// ----------------------------------------------------------------------------
273// wxRegion bounding box
274// ----------------------------------------------------------------------------
2bda0e17
KB
275
276// Outer bounds of region
9b1801c1 277void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
2bda0e17 278{
2c40e41c
VZ
279 if (m_refData)
280 {
2bda0e17
KB
281 RECT rect;
282 ::GetRgnBox(M_REGION, & rect);
789295bf
VZ
283 x = rect.left;
284 y = rect.top;
285 w = rect.right - rect.left;
286 h = rect.bottom - rect.top;
2c40e41c
VZ
287 }
288 else
289 {
789295bf
VZ
290 x = y = w = h = 0;
291 }
2bda0e17
KB
292}
293
789295bf 294wxRect wxRegion::GetBox() const
2bda0e17 295{
9b1801c1 296 wxCoord x, y, w, h;
2bda0e17
KB
297 GetBox(x, y, w, h);
298 return wxRect(x, y, w, h);
299}
300
301// Is region empty?
789295bf 302bool wxRegion::Empty() const
2bda0e17 303{
9b1801c1 304 wxCoord x, y, w, h;
2bda0e17
KB
305 GetBox(x, y, w, h);
306
2c40e41c 307 return (w == 0) && (h == 0);
2bda0e17
KB
308}
309
2b5f62a0
VZ
310// ----------------------------------------------------------------------------
311// wxRegion hit testing
312// ----------------------------------------------------------------------------
2bda0e17
KB
313
314// Does the region contain the point (x,y)?
9b1801c1 315wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const
2bda0e17 316{
789295bf
VZ
317 if (!m_refData)
318 return wxOutRegion;
2bda0e17 319
2b5f62a0 320 return ::PtInRegion(M_REGION, (int) x, (int) y) ? wxInRegion : wxOutRegion;
2bda0e17
KB
321}
322
323// Does the region contain the point pt?
324wxRegionContain wxRegion::Contains(const wxPoint& pt) const
325{
2b5f62a0 326 return Contains(pt.x, pt.y);
2bda0e17
KB
327}
328
329// Does the region contain the rectangle (x, y, w, h)?
2b5f62a0
VZ
330wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y,
331 wxCoord w, wxCoord h) const
2bda0e17 332{
789295bf
VZ
333 if (!m_refData)
334 return wxOutRegion;
2bda0e17
KB
335
336 RECT rect;
337 rect.left = x;
338 rect.top = y;
339 rect.right = x + w;
340 rect.bottom = y + h;
341
2b5f62a0 342 return ::RectInRegion(M_REGION, &rect) ? wxInRegion : wxOutRegion;
2bda0e17
KB
343}
344
345// Does the region contain the rectangle rect
346wxRegionContain wxRegion::Contains(const wxRect& rect) const
347{
2b5f62a0 348 return Contains(rect.x, rect.y, rect.width, rect.height);
2bda0e17
KB
349}
350
a724d789
JS
351// Get internal region handle
352WXHRGN wxRegion::GetHRGN() const
353{
2b5f62a0 354 return (WXHRGN)(m_refData ? M_REGION : 0);
a724d789
JS
355}
356
2b5f62a0
VZ
357// ============================================================================
358// wxRegionIterator implementation
359// ============================================================================
360
361// ----------------------------------------------------------------------------
362// wxRegionIterator ctors/dtor
363// ----------------------------------------------------------------------------
2bda0e17 364
2b5f62a0 365void wxRegionIterator::Init()
2bda0e17 366{
2b5f62a0
VZ
367 m_current =
368 m_numRects = 0;
369
370 m_rects = NULL;
2bda0e17
KB
371}
372
789295bf 373wxRegionIterator::~wxRegionIterator()
2bda0e17 374{
2b5f62a0 375 delete [] m_rects;
2bda0e17
KB
376}
377
2b5f62a0 378// Initialize iterator for region
2bda0e17
KB
379wxRegionIterator::wxRegionIterator(const wxRegion& region)
380{
381 m_rects = NULL;
382
789295bf 383 Reset(region);
2bda0e17
KB
384}
385
2b5f62a0
VZ
386wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& ri)
387{
388 delete [] m_rects;
389
390 m_current = ri.m_current;
391 m_numRects = ri.m_numRects;
392 if ( m_numRects )
393 {
394 m_rects = new wxRect[m_numRects];
395 for ( long n = 0; n < m_numRects; n++ )
396 m_rects[n] = ri.m_rects[n];
397 }
398 else
399 {
400 m_rects = NULL;
401 }
402
403 return *this;
404}
405
406// ----------------------------------------------------------------------------
407// wxRegionIterator operations
408// ----------------------------------------------------------------------------
409
410// Reset iterator for a new region.
2bda0e17
KB
411void wxRegionIterator::Reset(const wxRegion& region)
412{
789295bf
VZ
413 m_current = 0;
414 m_region = region;
2bda0e17
KB
415
416 if (m_rects)
2b5f62a0 417 {
2bda0e17
KB
418 delete[] m_rects;
419
2b5f62a0
VZ
420 m_rects = NULL;
421 }
2bda0e17 422
789295bf
VZ
423 if (m_region.Empty())
424 m_numRects = 0;
425 else
2bda0e17 426 {
2bda0e17
KB
427 DWORD noBytes = ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, 0, NULL);
428 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
789295bf 429 ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, noBytes, rgnData);
2bda0e17
KB
430
431 RGNDATAHEADER* header = (RGNDATAHEADER*) rgnData;
432
433 m_rects = new wxRect[header->nCount];
434
3317223b 435 RECT* rect = (RECT*) ((char*)rgnData + sizeof(RGNDATAHEADER));
c86f1403 436 size_t i;
2bda0e17
KB
437 for (i = 0; i < header->nCount; i++)
438 {
439 m_rects[i] = wxRect(rect->left, rect->top,
440 rect->right - rect->left, rect->bottom - rect->top);
cba2db0c 441 rect ++; // Advances pointer by sizeof(RECT)
2bda0e17
KB
442 }
443
444 m_numRects = header->nCount;
445
446 delete[] (char*) rgnData;
2bda0e17
KB
447 }
448}
449
2b5f62a0 450wxRegionIterator& wxRegionIterator::operator++()
2bda0e17 451{
789295bf
VZ
452 if (m_current < m_numRects)
453 ++m_current;
2b5f62a0
VZ
454
455 return *this;
2bda0e17
KB
456}
457
2b5f62a0 458wxRegionIterator wxRegionIterator::operator ++ (int)
2bda0e17 459{
2b5f62a0 460 wxRegionIterator tmp = *this;
789295bf
VZ
461 if (m_current < m_numRects)
462 ++m_current;
2b5f62a0
VZ
463
464 return tmp;
2bda0e17
KB
465}
466
2b5f62a0
VZ
467// ----------------------------------------------------------------------------
468// wxRegionIterator accessors
469// ----------------------------------------------------------------------------
470
9b1801c1 471wxCoord wxRegionIterator::GetX() const
2bda0e17 472{
2b5f62a0
VZ
473 wxCHECK_MSG( m_current < m_numRects, 0, _T("invalid wxRegionIterator") );
474
475 return m_rects[m_current].x;
2bda0e17
KB
476}
477
9b1801c1 478wxCoord wxRegionIterator::GetY() const
2bda0e17 479{
2b5f62a0
VZ
480 wxCHECK_MSG( m_current < m_numRects, 0, _T("invalid wxRegionIterator") );
481
482 return m_rects[m_current].y;
2bda0e17
KB
483}
484
9b1801c1 485wxCoord wxRegionIterator::GetW() const
2bda0e17 486{
2b5f62a0
VZ
487 wxCHECK_MSG( m_current < m_numRects, 0, _T("invalid wxRegionIterator") );
488
489 return m_rects[m_current].width;
2bda0e17
KB
490}
491
9b1801c1 492wxCoord wxRegionIterator::GetH() const
2bda0e17 493{
2b5f62a0
VZ
494 wxCHECK_MSG( m_current < m_numRects, 0, _T("invalid wxRegionIterator") );
495
496 return m_rects[m_current].height;
2bda0e17
KB
497}
498