WPF如何在绘图上下文中清除区域?

3

我正在使用DrawingContext和DrawingVisual生成一个透明的PNG。

在DrawingContext中,我画了一个矩形。

现在我想在矩形内部“切出”一个圆。我该怎么做?我没有找到任何可以清除区域的绘图上下文函数。

1个回答

5
您可以尝试使用 CombinedGeometry 来组合两个几何图形。它具有 GeometryCombineMode,允许您指定一些逻辑组合方式。在这种情况下,您需要的是 GeometryCombineMode.Xor。矩形和椭圆(圆)的相交部分将被“剪切”。以下是演示此过程的简单代码:
DrawingVisual dv = new DrawingVisual();
using (var dc = dv.RenderOpen()) {                    
  var rect = new Rect(0, 0, 300, 200);        
  var cb = new CombinedGeometry(GeometryCombineMode.Xor, 
                                new RectangleGeometry(rect),
                               new EllipseGeometry(new Point(150, 100), 50, 50));
  dc.DrawGeometry(Brushes.Blue, null, cb);                    
}

我希望您知道如何呈现DrawingVisual。 您可以使用一些RenderTargetBitmap将其捕捉到某种类型的BitmapSource中,然后您有许多方法来显示此位图。
以下是截图: enter image description here 黑色区域表示颜色是透明的。
如果您想剪切某些复杂的图像(例如绘制的文本或图像)。 您可以将CombinedGeometry转换为某种类型的OpacityMaskBrush的一种类型)。 我们可以将其转换为DrawingBrush,并且此刷子可以用作OpacityMask,可以传递到DrawingContext.PushOpacityMask方法中:
DrawingVisual dv = new DrawingVisual();                
using (var dc = dv.RenderOpen()) {                    
  var rect = new Rect(0, 0, 300, 200);
  var cb = new CombinedGeometry(GeometryCombineMode.Xor, 
                                new RectangleGeometry(rect),
                               new EllipseGeometry(new Point(150, 100), 50, 50));
  var mask = new DrawingBrush(new GeometryDrawing(Brushes.Blue, null, cb));      
  dc.PushOpacityMask(mask);
  dc.DrawImage(someImage, rect);
  dc.DrawText(new FormattedText("Windows Presentation Foundation", 
                                 System.Globalization.CultureInfo.CurrentCulture, 
                                 System.Windows.FlowDirection.LeftToRight,
                                 new Typeface("Lucida Bright"), 30, Brushes.Red){ 
                                   MaxTextWidth = rect.Width, 
                                   MaxTextHeight = rect.Height, 
                                   TextAlignment = TextAlignment.Center
                                 }, new Point());
}

输入图像描述

请注意,rect 应该具有整个绘图的大小。然后定位 和其他绘制内容将与您想要的完全相同。

最后,DrawingVisual 还有一个称为 Clip 的有用属性,它是一种 Geometry。因此,您可以准备一些 CombinedGeometry 并将其分配给 DrawingVisual.Clip 属性。

假设您已经拥有您的DrawingVisual(包括文本、图片等一些绘制内容)。下面的代码将通过它来创建一个

//prepare the geometry, which can be considered as the puncher.
var rect = new Rect(0, 0, 300, 200);
var cb = new CombinedGeometry(GeometryCombineMode.Xor, 
                              new RectangleGeometry(rect),
                             new EllipseGeometry(new Point(150, 100), 50, 50));
//punch the DrawingVisual
yourDrawingVisual.Clip = cb;

好的...很简单...但是,我有另一个复杂情况。如果我想从绘制的文本中裁剪出来,而不是从绘制的矩形中裁剪出一个圆形呢? - Jason Axelrod
@JasonAxelrod 看看我的更新。我能想到的唯一办法就是使用一些 OpacityMask - King King

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接