一、简介
石油行业软件开发中需要使用大量的不同类型的图件,由于具体项目需求多变,很难找到完全符合项目需要的图件库。在之前的项目中曾经使用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