即使在相对乏味的二维矢量图形领域中,Windows Presentation Foundation (WPF) 仍会要求程 序员们学习许多新概念。在 WPF 中,图形对象已提升到与控件几乎平等的地位,经常参与布局并接收鼠 标、键盘和笔针输入。此外,图形系统会保留这些图形对象以便不再像过去使用图形时那样频繁地进行重 绘,并且它们还可移动和用作数据绑定的目标。
开始研究 WPF 时,我立刻想到将 System.Windows.Shapes 作为包含“婴儿”图形类的命 名空间。这些类似乎适合于显示简单的线条和矩形,但我认为成熟的 WPF 程序可能希望通过重写 OnRender 方法并调用 DrawingContext 类中的方法来实现各种功能。
DrawGeometry 方法似乎特 别诱人:在 WPF 中,Geometry 对象是已连接和未连接直线、弧线和 Bézier 曲线(在传统图形 编程中称为“路径”)的组合。DrawGeometry 的三个参数包括 Geometry 对象、用于绘制 Geometry 的直线和曲线的 Pen 以及用于填充封闭区域的 Brush。
Shapes 命名空间的作用
很快,我发现自己对 WPF 矢量图形的第一印象是错误的。大多数 WPF 程序并不需要重写 OnRender 方法和调用 DrawingContext 类中的方法。虽然重写 OnRender 是个不错的培训练习,但通常 在大多数主流应用程序中都不必重写它。
因此,至少在我看来,System.Windows.Shapes 命名空 间成为了用于在 WPF 中呈现二维矢量图形的命名空间。System.Windows.Shapes 命名空间包含以下类: Shape(抽象类)和 Line、Polyline、Polygon、Path、Rectangle 和 Ellipse(都是封装类)。
Shape 类自身是从 FrameworkElement 派生而来。最重要的 Shape 派生类无疑是 Path;该类与 DrawingContext 的 DrawGeometry 方法具有相同的功能,但麻烦要少得多。在 XAML 中使用 Path 类时 ,甚至可以使用编码绘图命令字符串来定义 Geometry 对象。
这并不表示 Shapes 类为所有应用 程序构建了一个通用的矢量图形解决方案。每个类的各个实例都是一个成熟的 WPF 元素,并且可能带来 更大开销。此外,每个类都只有一个画笔和一个填充画刷,而且提供的颜色可能比您需要的要少。
要呈现包含多种颜色的复杂矢量图形,有多种方法可供选择。当然,可以创建多个 Path 对象, 但如果希望将复杂图像用作自身的实体,则这种方法可能过于繁杂。此时,更好的解决方案是使用 DrawingGroup 类,它可以包含多个 GeometryDrawing 对象,而每个此类对象又都包含 Geometry、画笔 和填充画刷。DrawingGroup 对象可能是 WPF 中最接近传统图形元文件的实体。DrawingGroup 对象可作 为画刷的基础(通过 DrawingBrush),或者可通过 Image 类将其变成显示的 DrawingImage 对象。
如果仅需要适当数量的图形基元(尤其是当这些对象需要接收鼠标、键盘或笔针输入,或者进行 自身转换时),Shapes 命名空间中的类将是理想之选。
现在,我将介绍从 Shapes 命名空间中的 唯一未封装类 Shape 进行派生。可从 Shape 类进行派生以实现自定义矢量图形基元。从 Shape 派生是 确保这些自定义基元使用 WPF 布局系统的协议的最简单方法。