1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:      msw/region.cpp 
   3 // Purpose:   wxRegion implementation using Win32 API 
   4 // Author:    Vadim Zeitlin 
   6 // Created:   Fri Oct 24 10:46:34 MET 1997 
   8 // Copyright: (c) 1997-2002 wxWindows team 
   9 // Licence:   wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "region.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #include "wx/region.h" 
  32 #include "wx/gdicmn.h" 
  34 #include "wx/msw/private.h" 
  36 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  37 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  39 // ---------------------------------------------------------------------------- 
  40 // wxRegionRefData implementation 
  41 // ---------------------------------------------------------------------------- 
  43 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData
 
  51     wxRegionRefData(const wxRegionRefData
& data
) 
  53 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  54         DWORD noBytes 
= ::GetRegionData(data
.m_region
, 0, NULL
); 
  55         RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
  56         ::GetRegionData(data
.m_region
, noBytes
, rgnData
); 
  57         m_region 
= ::ExtCreateRegion(NULL
, noBytes
, rgnData
); 
  58         delete[] (char*) rgnData
; 
  61         ::GetRgnBox(data
.m_region
, &rect
); 
  62         m_region 
= ::CreateRectRgnIndirect(&rect
); 
  66     virtual ~wxRegionRefData() 
  68         ::DeleteObject(m_region
); 
  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
&); 
  83 #define M_REGION (((wxRegionRefData*)m_refData)->m_region) 
  84 #define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_region) 
  86 // ============================================================================ 
  87 // wxRegion implementation 
  88 // ============================================================================ 
  90 // ---------------------------------------------------------------------------- 
  92 // ---------------------------------------------------------------------------- 
  96     m_refData 
= (wxRegionRefData 
*)NULL
; 
  99 wxRegion::wxRegion(WXHRGN hRegion
) 
 101     m_refData 
= new wxRegionRefData
; 
 102     M_REGION 
= (HRGN
) hRegion
; 
 105 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 107     m_refData 
= new wxRegionRefData
; 
 108     M_REGION 
= ::CreateRectRgn(x
, y
, x 
+ w
, y 
+ h
); 
 111 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
 113     m_refData 
= new wxRegionRefData
; 
 114     M_REGION 
= ::CreateRectRgn(topLeft
.x
, topLeft
.y
, bottomRight
.x
, bottomRight
.y
); 
 117 wxRegion::wxRegion(const wxRect
& rect
) 
 119     m_refData 
= new wxRegionRefData
; 
 120     M_REGION 
= ::CreateRectRgn(rect
.x
, rect
.y
, rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
 123 wxRegion::wxRegion(size_t n
, const wxPoint 
*points
, int fillStyle
) 
 125 #if defined(__WXMICROWIN__) || defined(__WXWINCE__) 
 129     m_refData 
= new wxRegionRefData
; 
 130     M_REGION 
= ::CreatePolygonRgn
 
 134                     fillStyle 
== wxODDEVEN_RULE 
? ALTERNATE 
: WINDING
 
 139 wxRegion::~wxRegion() 
 141     // m_refData unrefed in ~wxObject 
 144 wxObjectRefData 
*wxRegion::CreateRefData() const 
 146     return new wxRegionRefData
; 
 149 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
 151     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 154 // ---------------------------------------------------------------------------- 
 155 // wxRegion operations 
 156 // ---------------------------------------------------------------------------- 
 158 // Clear current region 
 159 void wxRegion::Clear() 
 164 bool wxRegion::Offset(wxCoord x
, wxCoord y
) 
 166     wxCHECK_MSG( M_REGION
, FALSE
, _T("invalid wxRegion") ); 
 176     if ( ::OffsetRgn(GetHrgn(), x
, y
) == ERROR 
) 
 178         wxLogLastError(_T("OffsetRgn")); 
 186 // combine another region with this one 
 187 bool wxRegion::Combine(const wxRegion
& rgn
, wxRegionOp op
) 
 189     // we can't use the API functions if we don't have a valid region handle 
 192         // combining with an empty/invalid region works differently depending 
 203                 wxFAIL_MSG( _T("unknown region operation") ); 
 208                 // leave empty/invalid 
 212     else // we have a valid region 
 236                 wxFAIL_MSG( _T("unknown region operation") ); 
 244         if ( ::CombineRgn(M_REGION
, M_REGION
, M_REGION_OF(rgn
), mode
) == ERROR 
) 
 246             wxLogLastError(_T("CombineRgn")); 
 255 // Combine rectangle (x, y, w, h) with this. 
 256 bool wxRegion::Combine(wxCoord x
, wxCoord y
, 
 257                        wxCoord width
, wxCoord height
, 
 260     return Combine(wxRegion(x
, y
, width
, height
), op
); 
 263 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
) 
 265     return Combine(rect
.GetLeft(), rect
.GetTop(), 
 266                    rect
.GetWidth(), rect
.GetHeight(), op
); 
 269 // ---------------------------------------------------------------------------- 
 270 // wxRegion bounding box 
 271 // ---------------------------------------------------------------------------- 
 273 // Outer bounds of region 
 274 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord 
&h
) const 
 279         ::GetRgnBox(M_REGION
, & rect
); 
 282         w 
= rect
.right 
- rect
.left
; 
 283         h 
= rect
.bottom 
- rect
.top
; 
 291 wxRect 
wxRegion::GetBox() const 
 295     return wxRect(x
, y
, w
, h
); 
 299 bool wxRegion::Empty() const 
 304     return (w 
== 0) && (h 
== 0); 
 307 // ---------------------------------------------------------------------------- 
 308 // wxRegion hit testing 
 309 // ---------------------------------------------------------------------------- 
 311 // Does the region contain the point (x,y)? 
 312 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
) const 
 317     return ::PtInRegion(M_REGION
, (int) x
, (int) y
) ? wxInRegion 
: wxOutRegion
; 
 320 // Does the region contain the point pt? 
 321 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 323     return Contains(pt
.x
, pt
.y
); 
 326 // Does the region contain the rectangle (x, y, w, h)? 
 327 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
, 
 328                                    wxCoord w
, wxCoord h
) const 
 339     return ::RectInRegion(M_REGION
, &rect
) ? wxInRegion 
: wxOutRegion
; 
 342 // Does the region contain the rectangle rect 
 343 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 345     return Contains(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 348 // Get internal region handle 
 349 WXHRGN 
wxRegion::GetHRGN() const 
 351     return (WXHRGN
)(m_refData 
? M_REGION 
: 0); 
 354 // ============================================================================ 
 355 // wxRegionIterator implementation 
 356 // ============================================================================ 
 358 // ---------------------------------------------------------------------------- 
 359 // wxRegionIterator ctors/dtor 
 360 // ---------------------------------------------------------------------------- 
 362 void wxRegionIterator::Init() 
 370 wxRegionIterator::~wxRegionIterator() 
 375 // Initialize iterator for region 
 376 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 383 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& ri
) 
 387     m_current 
= ri
.m_current
; 
 388     m_numRects 
= ri
.m_numRects
; 
 391         m_rects 
= new wxRect
[m_numRects
]; 
 392         for ( long n 
= 0; n 
< m_numRects
; n
++ ) 
 393             m_rects
[n
] = ri
.m_rects
[n
]; 
 403 // ---------------------------------------------------------------------------- 
 404 // wxRegionIterator operations 
 405 // ---------------------------------------------------------------------------- 
 407 // Reset iterator for a new region. 
 408 void wxRegionIterator::Reset(const wxRegion
& region
) 
 420     if (m_region
.Empty()) 
 424         DWORD noBytes 
= ::GetRegionData(((wxRegionRefData
*)region
.m_refData
)->m_region
, 0, NULL
); 
 425         RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
 426         ::GetRegionData(((wxRegionRefData
*)region
.m_refData
)->m_region
, noBytes
, rgnData
); 
 428         RGNDATAHEADER
* header 
= (RGNDATAHEADER
*) rgnData
; 
 430         m_rects 
= new wxRect
[header
->nCount
]; 
 432         RECT
* rect 
= (RECT
*) ((char*)rgnData 
+ sizeof(RGNDATAHEADER
)); 
 434         for (i 
= 0; i 
< header
->nCount
; i
++) 
 436             m_rects
[i
] = wxRect(rect
->left
, rect
->top
, 
 437                                  rect
->right 
- rect
->left
, rect
->bottom 
- rect
->top
); 
 438             rect 
++; // Advances pointer by sizeof(RECT) 
 441         m_numRects 
= header
->nCount
; 
 443         delete[] (char*) rgnData
; 
 447 wxRegionIterator
& wxRegionIterator::operator++() 
 449     if (m_current 
< m_numRects
) 
 455 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 457     wxRegionIterator tmp 
= *this; 
 458     if (m_current 
< m_numRects
) 
 464 // ---------------------------------------------------------------------------- 
 465 // wxRegionIterator accessors 
 466 // ---------------------------------------------------------------------------- 
 468 wxCoord 
wxRegionIterator::GetX() const 
 470     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 472     return m_rects
[m_current
].x
; 
 475 wxCoord 
wxRegionIterator::GetY() const 
 477     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 479     return m_rects
[m_current
].y
; 
 482 wxCoord 
wxRegionIterator::GetW() const 
 484     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 486     return m_rects
[m_current
].width
; 
 489 wxCoord 
wxRegionIterator::GetH() const 
 491     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 493     return m_rects
[m_current
].height
;