RegionsWhereas paths define a set of figures, with both a frame and an area, a region defines only an area. A region can be used for filling or, most importantly, clipping. A region is modeled in .NET with the Region class from the System.Drawing namespace: NotInheritable Class Region ' Constructors Public Sub New(...) ' Methods Sub Complement(...) Sub Exclude(...) Shared Function FromHrgn(hrgn As IntPtr) As Region Function GetBounds(g As Graphics) As RectangleF Function GetHrgn(g As Graphics) As IntPtr Function GetRegionData() As RegionData Function GetRegionScans(matrix As Matrix) As RectangleF() Sub Intersect(...) Function IsEmpty(g As Graphics) As Boolean Function IsInfinite(g As Graphics) As Boolean Function IsVisible(...) As Boolean Sub MakeEmpty() Sub MakeInfinite() Sub Transform(...) Sub Union(...) Sub Xor(...) End Class Constructing and Filling a RegionThere are ways to construct regions from unmanaged, native Win32 region structures. However, without resorting to Win32 interoperability, you can also construct regions from Rectangle objects or, more generally , from GraphicsPath objects: Dim path As GraphicsPath = New GraphicsPath() path.AddEllipse(rect) path.Flatten(New Matrix(), 13) path.AddString("Flattened Ellipse"), . . .) Dim myregion As Region = New Region(path) g.FillRegion(Brushes.Red, myregion) myregion.Dispose() path.Dispose() You might be curious about what might drive you to fill a region, especially given that paths can be drawn or filled but regions can only be filled. The answer is that you probably won't be using regions to draw. You'll probably be using regions to decide what not to draw. Clipping to a RegionEvery Graphics object has a region to which all drawing is clipped ; any drawing outside the clip region is ignored. By default, the clip region is an infinite region, and this means that it has no bounds and nothing inside the region being drawn will be thrown out. Windows itself will clip outside the region that isn't part of the invalid region that triggered the Paint event, but that's a separate region from the region exposed by the Graphics object. You can set the clip region on the Graphics object by setting the Clip property (as shown in Figure 6.9): Dim path As GraphicsPath = New GraphicsPath() path.AddEllipse(Me.ClientRectangle) Dim myregion As Region = New Region(path) ' Frame clipping region (for illustration only) g.DrawPath(Pens.Red, path) ' Don't draw outside the ellipse region g.Clip = myregion ' Draw a rectangle Dim rect As Rectangle = Me.ClientRectangle rect.Offset(10, 10) rect.Width = rect.Width 20 rect.Height = rect.Height 20 g.FillRectangle(Brushes.Black, rect) g.DrawString("Rectangle clipped to Ellipse", ...) Figure 6.9. Rectangle Clipped to an Ellipse Region
If you'd rather call a method than set a property when setting the clip region, you can use the SetClip method. It has overloads that take rectangles and paths and create the underlying clip region itself from those. If you'd like to go back to no clipping, you can use the ResetClip method. There are also several clip- related methods on the Region class that deal with intersecting and combining clip regions. All these operate on the underlying methods of the Region class itself, which supports various combination techniques. Region Combination OperationsRegions support several combination operations for creating more complicated regions from several combined simpler regions. These operations are complement, exclude, intersect, union, and xor, as shown in Figure 6.10. Figure 6.10. Region Combination Operations
Each region combination method takes a path, a region, or a rectangle and combines it with the existing one. By default, a region with no constructor argument is infinite, but you can make it empty by calling MakeEmpty. Creating a region with a constructor argument is like creating it as empty and then using the Union method to add a new shape to the region. The following are equivalent: ' Intersect the easy way Dim myregion As Region = New Region(path1) myregion.Intersect(path2) g.FillRegion(Brushes.Red, myregion) ' Intersect the hard way Dim myregion As Region = New Region() ' Defaults to myregion.IsInfinite(g) = true If Not(myregion.IsEmpty(g)) Then myregion.MakeEmpty() myregion.Union(path1) ' Add a path myregion.Intersect(path2) ' Intersect with another path g.FillRegion(Brushes.Red, myregion) Taken together, these combining operations provide a complete set of ways to combine regions for filling and clipping. |