WPF程序使用矢量图资源绘制井口装置图

一、简介

石油行业软件开发中需要使用大量的不同类型的图件,由于具体项目需求多变,很难找到完全符合项目需要的图件库。在之前的项目中曾经使用GDI技术开发了一套基础绘图框架,实现代码量很大,绘制效果比较简陋。而WPF技术支持使用矢量图资源绘制,我们可以通过使用专业的矢量图工具软件,设计精美的矢量图资源,使用这些资源来绘制图形。实现简单,代码量小,可灵活组合,生成不同类型的图元库。

二、矢量图元资源制作

矢量图元工具种类繁多,我这里使用CorelDRAW X8软件。

打开软件,新建一个图片文件。

添加矩形

使用交互式填充工具,填充渐变颜色

点击右上方“重复和镜像”,实现仿立体的渐变效果。

使用类似的方式,组合设计井口装置不同类型图元

 

 

 

套管头

 

四通

 

单闸板分割器

双闸板分割器

 

所有的图元设计完成后,为了能在WPF中使用还需要转换成微软提供的xaml矢量图格式。

把图元导出成“.emf”格式文件。

使用微软的Microsoft Expression Design工具,导入EMF文件,转换导出成.xaml格式的资源文件。

 

 

也可以使用其它第三方软件进行转换,网上也有免费在线转换URL,可在线转换。

三、WPF绘图库设计

Win32、WinFormsGDI是当今Window桌面应用程序的主流图形库,GDI图形系统已经形成了很多年。它提供了2D图形和文本功能,以及受限的图像处理功能。在WPF中,引入一种新的图形合成引擎。可以提供更高丰富的图形显式合成,而且不会有任何的窗口闪烁问题。这种新的显式提交引擎与传统的Win32、Windows Forms相比主要有两个优点: 1、所有的每个窗口元素都可以任意的交替重叠。 2、所有的合成操作都是Direct3D中的离屏表面(Off-screen Surface)中实现的。

(一) 画布面板类(DrawingCanvas):支持从Canvas对象继承,内部有VisualCollection集合用来记录画布面板里包含的图元对象。

功能包括:图元对象组织、图元添加和删除、图元对象排序(图层,上下排序)、画布缩放、鼠标事件代理(图元选择、图元右键菜单等)、绘图对象属性设置(字体、画笔、大小、位置等相关数据),图元对象绘图工具集合、命令模式封装实现(图元编辑的撤销操作)等。

public class DrawingCanvas : Canvas

{

#region Class Members

// Collection contains instances of GraphicsBase-derived classes.

private VisualCollection graphicsList;

// Dependency properties

public static readonly DependencyProperty ToolProperty;

public static readonly DependencyProperty ActualScaleProperty;

public static readonly DependencyProperty IsDirtyProperty;

public static readonly DependencyProperty LineWidthProperty;

public static readonly DependencyProperty ObjectColorProperty;

public static readonly DependencyProperty TextFontFamilyNameProperty;

public static readonly DependencyProperty TextFontStyleProperty;

public static readonly DependencyProperty TextFontWeightProperty;

public static readonly DependencyProperty TextFontStretchProperty;

public static readonly DependencyProperty TextFontSizeProperty;

public static readonly DependencyProperty CanUndoProperty;

public static readonly DependencyProperty CanRedoProperty;

public static readonly DependencyProperty CanSelectAllProperty;

public static readonly DependencyProperty CanUnselectAllProperty;

public static readonly DependencyProperty CanDeleteProperty;

public static readonly DependencyProperty CanDeleteAllProperty;

public static readonly DependencyProperty CanMoveToFrontProperty;

public static readonly DependencyProperty CanMoveToBackProperty;

public static readonly DependencyProperty CanSetPropertiesProperty;

public static readonly RoutedEvent IsDirtyChangedEvent;

private Tool[] tools; // Array of tools

ToolText toolText;

ToolPointer toolPointer;

private ContextMenu contextMenu;

private UndoManager undoManager;

public DrawingCanvas()

: base()

{

graphicsList = new VisualCollection(this);

CreateContextMenu();

this.FocusVisualStyle = null;

this.Loaded += new RoutedEventHandler(DrawingCanvas_Loaded);

this.MouseDown += new MouseButtonEventHandler(DrawingCanvas_MouseDown);

this.MouseMove += new MouseEventHandler(DrawingCanvas_MouseMove);

this.MouseUp += new MouseButtonEventHandler(DrawingCanvas_MouseUp);

this.KeyDown += new KeyEventHandler(DrawingCanvas_KeyDown);

this.LostMouseCapture += new MouseEventHandler(DrawingCanvas_LostMouseCapture);}

(一) 基本图元对象GraphicsBase:这是个抽象类,从DrawingVisual对象继承。DrawingVisual对象是WPF绘图系统提供的轻量级高性能的绘图类。

Visual 类的层次结构如下:

DrawingVisual 继承自Visual,是一个用于呈现形状、图像或文本的轻量绘图类。 此类之所以被视为轻量,是因为它不提供布局或事件处理功能,从而能够改善运行时性能。 因此,绘图最适于背景和剪贴画。

图元对象中定义最重要的虚方法使用DrawingContext对象绘制图元,我们扩展图元绘制的逻辑是在这里来实现的

public abstract class GraphicsBase : DrawingVisual

public virtual void Draw(DrawingContext drawingContext)

{

}

//接下来,定义不同类型的图元类:

//直线

public class GraphicsLine : GraphicsBase

//圆形

public class GraphicsEllipse : GraphicsRectangleBase

//矩形抽象类

public abstract class GraphicsRectangleBase : GraphicsBase

//多边形

public class GraphicsPolyLine : GraphicsBase

//不同的图元通过重写Draw虚方法来,实现不同的绘制方法

//直线绘制:

public override void Draw(DrawingContext drawingContext)

{

if ( drawingContext == null )

{

throw new ArgumentNullException("drawingContext");

}

drawingContext.DrawLine(

new Pen(new SolidColorBrush(ObjectColor), ActualLineWidth),

lineStart,

lineEnd);

base.Draw(drawingContext);

}

//圆形绘制:

public override void Draw(DrawingContext drawingContext)

{

if ( drawingContext == null )

{

throw new ArgumentNullException("drawingContext");

}

Rect r = Rectangle;

Point center = new Point(

(r.Left + r.Right) / 2.0,

(r.Top + r.Bottom) / 2.0);

double radiusX = (r.Right - r.Left) / 2.0;

double radiusY = (r.Bottom - r.Top) / 2.0;

drawingContext.DrawEllipse(

null,

new Pen(new SolidColorBrush(ObjectColor), ActualLineWidth),

center,

radiusX,

radiusY);

}

(三) 基于矢量图资源的井口装置图图元绘制

我们可扩展矩形绘图图元,使其支持矢量图绘制功能,来实现绘制井口装置图。

具体做法是,不绘制矩形边线,使用矢量图资源当作背景,来绘制矩形图元。

1) 把xaml格式的矢量图图元文件以“content”的形式引入项目中

 

 

1) 把文件添加到项目App.xaml文件,添加到Application Resources字典里

<Application.Resources>

<ResourceDictionary>

<ResourceDictionary.MergedDictionaries>

<ResourceDictionary Source="pack://siteoforigin:,,,/../3.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../st.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../hx.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../dzb.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../szb.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../jk.xaml" />

<ResourceDictionary Source="pack://siteoforigin:,,,/../tgt.xaml" />

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

</Application.Resources>

2) 重新Draw方法,使用矢量图资源绘制图元

public override void Draw(DrawingContext drawingContext)

{

if (drawingContext == null)

{

throw new ArgumentNullException("drawingContext");

}

DrawingBrush background = null;

//获取井口矢量图图元

background = Application.Current.FindResource("jk") as DrawingBrush;

//绘制图元

drawingContext.DrawRectangle(

background,

new Pen(Brushes.Transparent, 0),

Rectangle);

//drawingContext.DrawText()

base.Draw(drawingContext);

}

四、示例介绍

我简单实现了个示例来展示井口装置图绘制

 

 

 

 

单击上面井口装置图标,添加所对应的装置到当前画板。

可选中图标,可缩放调节宽高,拖拽移动等。

调整宽度组合图元,来实现井口装置图,还可以在任意位置添加文本,线端等其它图元。

可保存绘图到xml文件中。

 

 

转自:https://zhuanlan.zhihu.com/p/37167062

 

原文地址:https://www.cnblogs.com/nepulgh/p/13129276.html