1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:      src/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 wxWidgets team 
   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/region.h" 
  30     #include "wx/gdicmn.h" 
  33 #include "wx/msw/private.h" 
  35 IMPLEMENT_DYNAMIC_CLASS(wxRegion
, wxGDIObject
) 
  36 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator
, wxObject
) 
  38 // ---------------------------------------------------------------------------- 
  39 // wxRegionRefData implementation 
  40 // ---------------------------------------------------------------------------- 
  42 class WXDLLEXPORT wxRegionRefData 
: public wxGDIRefData
 
  50     wxRegionRefData(const wxRegionRefData
& data
) : wxGDIRefData() 
  52 #if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXWINCE__) 
  53         DWORD noBytes 
= ::GetRegionData(data
.m_region
, 0, NULL
); 
  54         RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
  55         ::GetRegionData(data
.m_region
, noBytes
, rgnData
); 
  56         m_region 
= ::ExtCreateRegion(NULL
, noBytes
, rgnData
); 
  57         delete[] (char*) rgnData
; 
  60         ::GetRgnBox(data
.m_region
, &rect
); 
  61         m_region 
= ::CreateRectRgnIndirect(&rect
); 
  65     virtual ~wxRegionRefData() 
  67         ::DeleteObject(m_region
); 
  75 //  DECLARE_NO_COPY_CLASS(wxRegionRefData) 
  76 // because copy constructor is explicitly declared above; 
  77 // but no copy assignment operator is defined, so declare 
  78 // it private to prevent the compiler from defining it: 
  79     wxRegionRefData
& operator=(const wxRegionRefData
&); 
  82 #define M_REGION (((wxRegionRefData*)m_refData)->m_region) 
  83 #define M_REGION_OF(rgn) (((wxRegionRefData*)(rgn.m_refData))->m_region) 
  85 // ============================================================================ 
  86 // wxRegion implementation 
  87 // ============================================================================ 
  89 // ---------------------------------------------------------------------------- 
  91 // ---------------------------------------------------------------------------- 
  95     m_refData 
= (wxRegionRefData 
*)NULL
; 
  98 wxRegion::wxRegion(WXHRGN hRegion
) 
 100     m_refData 
= new wxRegionRefData
; 
 101     M_REGION 
= (HRGN
) hRegion
; 
 104 wxRegion::wxRegion(wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
) 
 106     m_refData 
= new wxRegionRefData
; 
 107     M_REGION 
= ::CreateRectRgn(x
, y
, x 
+ w
, y 
+ h
); 
 110 wxRegion::wxRegion(const wxPoint
& topLeft
, const wxPoint
& bottomRight
) 
 112     m_refData 
= new wxRegionRefData
; 
 113     M_REGION 
= ::CreateRectRgn(topLeft
.x
, topLeft
.y
, bottomRight
.x
, bottomRight
.y
); 
 116 wxRegion::wxRegion(const wxRect
& rect
) 
 118     m_refData 
= new wxRegionRefData
; 
 119     M_REGION 
= ::CreateRectRgn(rect
.x
, rect
.y
, rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
 122 wxRegion::wxRegion(size_t n
, const wxPoint 
*points
, int fillStyle
) 
 124 #if defined(__WXMICROWIN__) || defined(__WXWINCE__) 
 127     wxUnusedVar(fillStyle
); 
 131     m_refData 
= new wxRegionRefData
; 
 132     M_REGION 
= ::CreatePolygonRgn
 
 136                     fillStyle 
== wxODDEVEN_RULE 
? ALTERNATE 
: WINDING
 
 141 wxRegion::~wxRegion() 
 143     // m_refData unrefed in ~wxObject 
 146 wxObjectRefData 
*wxRegion::CreateRefData() const 
 148     return new wxRegionRefData
; 
 151 wxObjectRefData 
*wxRegion::CloneRefData(const wxObjectRefData 
*data
) const 
 153     return new wxRegionRefData(*(wxRegionRefData 
*)data
); 
 156 // ---------------------------------------------------------------------------- 
 157 // wxRegion operations 
 158 // ---------------------------------------------------------------------------- 
 160 // Clear current region 
 161 void wxRegion::Clear() 
 166 bool wxRegion::Offset(wxCoord x
, wxCoord y
) 
 168     wxCHECK_MSG( M_REGION
, false, _T("invalid wxRegion") ); 
 178     if ( ::OffsetRgn(GetHrgn(), x
, y
) == ERROR 
) 
 180         wxLogLastError(_T("OffsetRgn")); 
 188 // combine another region with this one 
 189 bool wxRegion::Combine(const wxRegion
& rgn
, wxRegionOp op
) 
 191     // we can't use the API functions if we don't have a valid region handle 
 194         // combining with an empty/invalid region works differently depending 
 205                 wxFAIL_MSG( _T("unknown region operation") ); 
 210                 // leave empty/invalid 
 214     else // we have a valid region 
 238                 wxFAIL_MSG( _T("unknown region operation") ); 
 246         if ( ::CombineRgn(M_REGION
, M_REGION
, M_REGION_OF(rgn
), mode
) == ERROR 
) 
 248             wxLogLastError(_T("CombineRgn")); 
 257 // Combine rectangle (x, y, w, h) with this. 
 258 bool wxRegion::Combine(wxCoord x
, wxCoord y
, 
 259                        wxCoord width
, wxCoord height
, 
 262     return Combine(wxRegion(x
, y
, width
, height
), op
); 
 265 bool wxRegion::Combine(const wxRect
& rect
, wxRegionOp op
) 
 267     return Combine(rect
.GetLeft(), rect
.GetTop(), 
 268                    rect
.GetWidth(), rect
.GetHeight(), op
); 
 271 // ---------------------------------------------------------------------------- 
 272 // wxRegion bounding box 
 273 // ---------------------------------------------------------------------------- 
 275 // Outer bounds of region 
 276 void wxRegion::GetBox(wxCoord
& x
, wxCoord
& y
, wxCoord
&w
, wxCoord 
&h
) const 
 281         ::GetRgnBox(M_REGION
, & rect
); 
 284         w 
= rect
.right 
- rect
.left
; 
 285         h 
= rect
.bottom 
- rect
.top
; 
 293 wxRect 
wxRegion::GetBox() const 
 297     return wxRect(x
, y
, w
, h
); 
 301 bool wxRegion::Empty() const 
 306     return (w 
== 0) && (h 
== 0); 
 309 // ---------------------------------------------------------------------------- 
 310 // wxRegion hit testing 
 311 // ---------------------------------------------------------------------------- 
 313 // Does the region contain the point (x,y)? 
 314 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
) const 
 319     return ::PtInRegion(M_REGION
, (int) x
, (int) y
) ? wxInRegion 
: wxOutRegion
; 
 322 // Does the region contain the point pt? 
 323 wxRegionContain 
wxRegion::Contains(const wxPoint
& pt
) const 
 325     return Contains(pt
.x
, pt
.y
); 
 328 // Does the region contain the rectangle (x, y, w, h)? 
 329 wxRegionContain 
wxRegion::Contains(wxCoord x
, wxCoord y
, 
 330                                    wxCoord w
, wxCoord h
) const 
 341     return ::RectInRegion(M_REGION
, &rect
) ? wxInRegion 
: wxOutRegion
; 
 344 // Does the region contain the rectangle rect 
 345 wxRegionContain 
wxRegion::Contains(const wxRect
& rect
) const 
 347     return Contains(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 350 // Get internal region handle 
 351 WXHRGN 
wxRegion::GetHRGN() const 
 353     return (WXHRGN
)(m_refData 
? M_REGION 
: 0); 
 356 // ============================================================================ 
 357 // wxRegionIterator implementation 
 358 // ============================================================================ 
 360 // ---------------------------------------------------------------------------- 
 361 // wxRegionIterator ctors/dtor 
 362 // ---------------------------------------------------------------------------- 
 364 void wxRegionIterator::Init() 
 372 wxRegionIterator::~wxRegionIterator() 
 377 // Initialize iterator for region 
 378 wxRegionIterator::wxRegionIterator(const wxRegion
& region
) 
 385 wxRegionIterator
& wxRegionIterator::operator=(const wxRegionIterator
& ri
) 
 389     m_current 
= ri
.m_current
; 
 390     m_numRects 
= ri
.m_numRects
; 
 393         m_rects 
= new wxRect
[m_numRects
]; 
 394         for ( long n 
= 0; n 
< m_numRects
; n
++ ) 
 395             m_rects
[n
] = ri
.m_rects
[n
]; 
 405 // ---------------------------------------------------------------------------- 
 406 // wxRegionIterator operations 
 407 // ---------------------------------------------------------------------------- 
 409 // Reset iterator for a new region. 
 410 void wxRegionIterator::Reset(const wxRegion
& region
) 
 422     if (m_region
.Empty()) 
 426         DWORD noBytes 
= ::GetRegionData(((wxRegionRefData
*)region
.m_refData
)->m_region
, 0, NULL
); 
 427         RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
 428         ::GetRegionData(((wxRegionRefData
*)region
.m_refData
)->m_region
, noBytes
, rgnData
); 
 430         RGNDATAHEADER
* header 
= (RGNDATAHEADER
*) rgnData
; 
 432         m_rects 
= new wxRect
[header
->nCount
]; 
 434         RECT
* rect 
= (RECT
*) ((char*)rgnData 
+ sizeof(RGNDATAHEADER
)); 
 436         for (i 
= 0; i 
< header
->nCount
; i
++) 
 438             m_rects
[i
] = wxRect(rect
->left
, rect
->top
, 
 439                                  rect
->right 
- rect
->left
, rect
->bottom 
- rect
->top
); 
 440             rect 
++; // Advances pointer by sizeof(RECT) 
 443         m_numRects 
= header
->nCount
; 
 445         delete[] (char*) rgnData
; 
 449 wxRegionIterator
& wxRegionIterator::operator++() 
 451     if (m_current 
< m_numRects
) 
 457 wxRegionIterator 
wxRegionIterator::operator ++ (int) 
 459     wxRegionIterator tmp 
= *this; 
 460     if (m_current 
< m_numRects
) 
 466 // ---------------------------------------------------------------------------- 
 467 // wxRegionIterator accessors 
 468 // ---------------------------------------------------------------------------- 
 470 wxCoord 
wxRegionIterator::GetX() const 
 472     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 474     return m_rects
[m_current
].x
; 
 477 wxCoord 
wxRegionIterator::GetY() const 
 479     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 481     return m_rects
[m_current
].y
; 
 484 wxCoord 
wxRegionIterator::GetW() const 
 486     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 488     return m_rects
[m_current
].width
; 
 491 wxCoord 
wxRegionIterator::GetH() const 
 493     wxCHECK_MSG( m_current 
< m_numRects
, 0, _T("invalid wxRegionIterator") ); 
 495     return m_rects
[m_current
].height
;