【问题标题】:WPF Clear Region on a Drawing Context?绘图上下文上的WPF清除区域?
【发布时间】:2014-10-25 04:42:27
【问题描述】:

所以我正在使用 DrawingContext 和 DrawingVisual 生成透明 PNG。

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

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

【问题讨论】:

    标签: wpf drawingcontext


    【解决方案1】:

    您可以尝试使用 CombinedGeometry 组合 2 个几何图形(每次)。它有GeometryCombineMode 允许您指定一些逻辑组合。在这种情况下,您需要的是GeometryCombineMode.Xor。 Rect 和 Ellipse(圆)的交点将被切掉。这是演示它的简单代码:

    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 中,然后您有多种方式来显示此位图。

    截图如下:

    黑色区域表示颜色是透明的。

    如果您想剪切一些复杂的图像(例如绘制的文本或图像)。您可以将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 应该具有整个绘图的大小。然后定位 hole 和其他绘制的东西将完全符合您的要求。

    最后,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;
    

    【讨论】:

    • 好的...很简单...但是,我还有另一个问题。如果我不想从绘制的矩形中剪切出绘制的圆形,而是要从绘制的文本中剪切出来怎么办?
    • @JasonAxelrod 查看我的更新。我唯一能想到的就是使用一些OpacityMask
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-13
    • 1970-01-01
    • 2015-08-15
    • 2012-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多