WPF 清除绘图上下文上的区域?

Jas*_*rod 3 wpf drawingcontext

因此,我使用 DrawingContext 和 DrawingVisual 生成透明 PNG。

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

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

Kin*_*ing 5

您可以尝试使用CombinedGeometry组合 2 个几何图形(每次)。它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);                    
}
Run Code Online (Sandbox Code Playgroud)

我希望你知道如何渲染DrawingVisual. 您可以使用某些RenderTargetBitmap将其捕获到某种 BitmapSource 中,然后您可以通过多种方式来显示该位图。

这是屏幕截图:

在此输入图像描述

黑色区域意味着颜色是透明的。

如果您想剪切一些复杂的图像(例如绘制的文本或图像)。您可以将 变成CombinedGeometry某种OpacityMask(类型Brush)。我们可以把它变成 aDrawingBrush并且这个画笔可以用作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());
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

请注意,它rect应该具有整个绘图的大小。然后,和其他绘制的东西的位置将完全符合您的要求。

最后,DrawingVisual还有一个有用的属性,称为Clip“which is a” 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;
Run Code Online (Sandbox Code Playgroud)