简介:
之前有讲到过微软的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;