WPF之DrawingContext

简介:

之前有讲到过微软的GDI+技术,这个大多数是在WinForm上使用的,而在WPF中用到最多的就是DrawingContext技术了。
DrawingContext是一个抽象类,不能直接创建类的实例。而且也不能创建它的子类(因为它没有公开的构造函数)。要创建DrawingContext对象,有两种方式:
- 使用类的方法

// DrawingVisual.RendOpen()方法
DrawingVisual dv = new DrawingVisual();
using DrawingContext context = dv.RenderOpen();
context.DrawXX(...);     // 绘制图形

// DrawingGroup.Open()方法
DrawingGroup dg = new DrawingGroup();
using DrawingContext dc = dg.Open();
dc.DrawXX(...);           // 绘制图形

- 继承自UIElement类

public class visualElement:UIElement
    {
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
        }
    }

画图:

DrawingContext类提供了很多的方法,比如画线,画圆等,这里就不一一列举了,感兴趣的可以去看下微软官网对DrawingContext类的介绍。这里我们就简单画线做示例:
- DrawingVisual

private void DrawingVisualTest()
{
    //轻量级视觉对象,用于高效绘制单次渲染的矢量图形(如动态生成内容)。
    DrawingVisual dv = new DrawingVisual();
    using (DrawingContext dc = dv.RenderOpen())
    {
        Pen pen = new()
        {
            Thickness = 3,
            Brush = new SolidColorBrush(Colors.Red)
        };
        dc.DrawRectangle(null, new Pen(Brushes.Blue, 2), new Rect(0, 0, 298, 298));
        dc.DrawLine(pen, new Point(0, 0), new Point(150, 150));
        // 改成虚线,上面也会改的,如果只想该下面,就重新new一个pen
        pen.DashStyle = DashStyles.Dash;
        //dc.DrawLine(pen, new Point(0, 150), new Point(150, 150));
        LineGeometry line = new LineGeometry(new Point(0, 150), new Point(150, 150));// 无需额外对象,内存占用极低。
        dc.DrawGeometry(null, pen, line);//需预先创建 Geometry 对象,可能增加内存开销(但可复用)。null 表示不填充内部(仅描边)
    }

    //DrawingContext不是一个Visual对象,而仅仅只是一个绘图环境,绘制的图形仅保存在系统中。如果要显示出来,就必须将其转换为Visual对象。

    // 将 DrawingVisual 的内容转换为 DrawingImage
    DrawingImage drawingImage = new DrawingImage(dv.Drawing);
    img.Source = drawingImage;
}

- DrawingGroup

private void DrawingGroupTest()
{
    //组合多个 Drawing 对象,形成逻辑分组,便于统一管理、变换或共享属性。
    DrawingGroup group = new DrawingGroup();
    using (DrawingContext dc = group.Open())
    {
        Pen pen = new()
        {
            Thickness = 3,
            Brush = new SolidColorBrush(Colors.Red),
            //DashStyle = DashStyles.Dash, // 设置为虚线样式
        };
        // 或者这样也可以
        //Pen pen = new Pen(Brushes.White, 1);
        //pen.DashStyle = DashStyles.Dash;
        // 先画一个矩形,告诉坐标系0,0位置,如果不这样就需要在xaml中设置对齐方式,就是水平和垂直方式(控件默认是居中)
        // 设置image对其方式如果为top和left 那么左上角就是0,0坐标系,如果是bottom和right 那么右下角就是0,0坐标系
        dc.DrawRectangle(null, new Pen(Brushes.Blue, 2), new Rect(0, 0, 298, 298));
        dc.DrawLine(pen, new Point(0, 0), new Point(0, 150));
        dc.DrawLine(pen, new Point(0, 150), new Point(150, 150));
        //group.Transform = new RotateTransform(45); // 整体旋转45度
    }

    //DrawingContext不是一个Visual对象,而仅仅只是一个绘图环境,绘制的图形仅保存在系统中。如果要显示出来,就必须将其转换为Visual对象。

    // 将 DrawingVisual 的内容转换为 DrawingImage
    DrawingImage drawingImage = new DrawingImage(group);
    img.Source = drawingImage;
}

Geometry(几何)和Shape(形状)

- Geometry:
.Net中,Geometry类就是用于描述这种几何图形的类。它只包含描述几何图形的必要属性,并提供包括命中测试、动画等功能。它派生出以下七个类,以简化对图形的描述:

类名 功能
LineGeometry 直线
EllipseGeometry 椭圆(圆也是椭圆的一种)
RectangleGeometry 矩形
PathGeometry 路线(类似与随手画的一条任意线)
GeometryGroup 几何图形组(把多个几何图形放在一起)
CombinedGeometry 组合图形(将多个几何图形做布尔运算)
StreamGeometry 它是PathGeometry的轻量级对象

- Shape:
形状(Shape),就是一个能看得到的几何图形。例如我们在白纸上,用红色的笔画一条直线,一个矩形。
由此可见,Shape的本质,就是在几何图形(Geometry)的基础上,加上画笔,颜色等信息,绘制而成。
.Net中,Shape就是表示“形状”的类。它是一个抽象类,继承自FrameworkElement,这意味着它是一个元素,可以直接显示在窗体上。

类型 功能
Ellipse 椭圆形
Line 直线
Path 路径
Polygon 多边形
Polyline 多段线
Rectangle 矩形

使用图元转换器绘制图形

上面的例子中我们看到绘制的图形需要通过将 DrawingVisual 的内容转换为 DrawingImage才能赋值显示。这就牵涉到了图元转换或包装。
- 图元包装器:Drawing
Drawing类用于包装2D图元(图元可以是Geometry,也可以是GlyphRun、Image、Video),并为其添加一些额外的信息,比如Pen,Brush等属性。它是一个抽象类,可以使用它的派生类来包装不同的图形:

类名 功能
GeometryDrawing 包装几何图形
GlyphRunDrawing 包装字符
ImageDrawing 包装图片
VideoDrawing 包装视频
DrawingGroup 将多个Drawing对象组合到一个绘图器中,进行统一包装

- 图元转换器:DrawingXX

类名 功能
DrawingBrush 将Drawing对象当成画刷。类似与Photoshop中的画刷功能
DrawingImage 将Drawing对象当成ImageSource。

DrawingBrush:

DrawingBrush的作用是将Drawing对象转换为Brush。在任何需要用到Brush的地方,就可以使用它。

// 创建几何图形
EllipseGeometry cicle = new(new Point(5, 5), 5, 5);
EllipseGeometry cicle2 = new(new Rect(new Size(20, 16)));
GeometryGroup geoGroup = new() { Children = { cicle, cicle2 }, FillRule= FillRule.EvenOdd };

// 创建图画
GeometryDrawing drawing = new(Brushes.Red, new Pen(Brushes.Blue, 2), geoGroup);

// 创建DrawingBrush
DrawingBrush brushes = new DrawingBrush(drawing);

border.BorderThickness = new Thickness(50);
border.Background = brushes;

DrawingImage:

DrawingImage的作用是把Drawing对象转换为ImageSource。在任何需要ImageSource的地方,就可以使用它。

// 创建几何图形
EllipseGeometry cicle = new(new Point(5, 5), 5, 5);
EllipseGeometry cicle2 = new(new Rect(new Size(20, 16)));
GeometryGroup geoGroup = new() { Children = { cicle, cicle2 }, FillRule= FillRule.EvenOdd };

// 创建图画
GeometryDrawing drawing = new(Brushes.Red, new Pen(Brushes.Blue, 2), geoGroup);

// 创建DrawingBrush
DrawingBrush brushes = new DrawingBrush(drawing);

DrawingImage image = new(drawing);
img.Source = image;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容