DevExpress提供了一个比较强大的图形绘制工具,可以用于绘制各种图形,如流程图、组织机构图等等,本篇随笔介绍XtraDiagram.DiagramControl的使用,以及利用代码对其属性进行控制,以及利用图形模具的自定义操作,实现一些简单流程图形的绘制和处理。

DiagramControl是类似Visio的绘图控件,以前我2006年的就接触使用Visio的二次开发,当时开始还是利用VB6 + VIsio2003进行二次开发的,后来把它改良为C# + Visio进行二次开发,DiagramControl的对象模型很类似Visio的相关对象模型,如对于工具栏的形状,称之为模具(Stencil),Visio也是称之为Stencil, DiagramControl里面的很多接口名称依旧采用Stencil进行命名,因此估计也是借鉴了很多Visio的对象设计知识,如果您对Visio二次开发感兴趣,可以参考我的随笔文章《Visio二次开发》,里面有很多相关的内容。

而如果想了解这个控件的相关知识和使用,参考官网的案例和说明应该是比较好的教程(https://docs.devexpress.com/WindowsForms/118290/controls-and-libraries/diagrams/getting-started )。

1、DiagramControl控件的使用

DiagramControl是一个界面控件,类似Visio SDK里面的DrawingControl的存在,可以通过它进行图形的绘制,各种窗口的显示和隐藏,以及跟踪各种事件的处理。

DiagramControl控件拖动到窗体中后,会自动增加一些属性窗口,上排的绘图工具中的按钮是我添加的,用来测试该控件的一些属性的控制。

1)属性窗口的显示和隐藏(折叠)

这个通过控制diagramControl1.OptionsView.PropertiesPanelVisibility 属性就可以实现对这个属性窗口的控制了。

里面显示一些系统位置和内容信息,以及一些自定义信息的窗口,后面我会介绍如何自定义处理这些模具的属性。

通过按钮处理的代码,我们可以实现对这个窗口的显示或者隐藏处理。

//切换属性窗口的显示或关闭
var status = diagramControl1.OptionsView.PropertiesPanelVisibility;
diagramControl1.OptionsView.PropertiesPanelVisibility = (status == PropertiesPanelVisibility.Visible ? PropertiesPanelVisibility.Collapsed : PropertiesPanelVisibility.Visible);

2)模具形状窗口的显示或隐藏

模具形状的窗口,它是放在一个面板里面,我们只需要通过控制该面板的显示或者隐藏就可以了,如下代码所示。

//切换模具形状窗口的显示或关闭
var status = diagramToolboxDockPanel1.Visibility;
diagramToolboxDockPanel1.Visibility = (status == DevExpress.XtraBars.Docking.DockVisibility.Visible ? DevExpress.XtraBars.Docking.DockVisibility.Hidden : DevExpress.XtraBars.Docking.DockVisibility.Visible);

或者通过控件的Toolbar属性进行控制,一样的效果。

//切换模具形状窗口的显示或关闭
var status = this.diagramControl1.OptionsView.ToolboxVisibility;
this.diagramControl1.OptionsView.ToolboxVisibility = status == ToolboxVisibility.Closed ? ToolboxVisibility.Full : ToolboxVisibility.Closed;

3)放大缩小窗口的显示或者隐藏

同样我们也可以控制放大缩小窗口的显示或者隐藏,它也是图形绘制的一个常见的窗口。我们只需要判断或者设置diagramControl1.OptionsView.ShowPanAndZoomPanel 属性就可以了,如下代码所示。

//切换放大缩小窗口的显示或关闭
var status = diagramControl1.OptionsView.ShowPanAndZoomPanel;
diagramControl1.OptionsView.ShowPanAndZoomPanel = !status;

4)其他属性的处理

另外,我们可以通过控制一些属性,实现对标尺、网格、只读视图等模式进行控制。

//是否显示标尺
this.diagramControl1.OptionsView.ShowRulers = this.chkRuler.Checked;
//是否显示网格
this.diagramControl1.OptionsView.ShowGrid = this.chkGrid.Checked;
//是否只读视图
this.diagramControl1.OptionsProtection.IsReadOnly = this.chkReadOnly.Checked;

2、绘图的处理事件

在绘制图形的时候,一般来说我们可能需要切换点选模式或者连接线模式,因此可以通过它的属性ActiveTool进行设置。在点选模式下,可以对图形进行拖动、放大缩小、旋转等处理,连接线模式下,则会加亮连接点,便于自动绘制连接线。

private void btnPointerMode_Click(object sender, EventArgs e)
{
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
} private void btnConnectorMode_Click(object sender, EventArgs e)
{
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
}

当然,我们也可以通过对鼠标行为的分析来进行控制,如果鼠标悬停或者放置在图形上,就自动切换模式为连接线模式,否则为点选模式,那么只需要判断鼠标的移动行为即可自动处理,如下代码所示。

        /// <summary>
/// 实现对图形自动切换到连接点模式
/// </summary>
private void diagramControl1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
return; DiagramItem item = diagramControl1.CalcHitItem(e.Location);
if (item == null)
{
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
return;
}
else if (item is DiagramConnector)
{
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
return;
} Rect itemBounds = new Rect(new Point(item.Position.X, item.Position.Y), new Size(item.Width, item.Height));
PointFloat documentPoint = diagramControl1.PointToDocument(new PointFloat(e.Location));
DiagramHitInfo[] hitInfo = diagramControl1.CalcHitInfo(documentPoint);
if (itemBounds.Contains(new Point(documentPoint.X, documentPoint.Y)))
{
itemBounds.Inflate(-5, -5);
if (!itemBounds.Contains(new Point(documentPoint.X, documentPoint.Y)))
{
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.ConnectorTool;
return;
}
}
diagramControl1.OptionsBehavior.ActiveTool = diagramControl1.OptionsBehavior.PointerTool;
}

另外图形的保存xml、PNG、PDF处理和加载代码如下所示。

/// <summary>
/// 保存XML和图片文件
/// </summary>
private void SaveXml()
{
var xml = Path.Combine(Application.StartupPath, "MyFlowShapes.xml");
diagramControl1.SaveDocument(xml); var pngFile = Path.Combine(Application.StartupPath, "MyFlowShapes.png");
diagramControl1.ExportDiagram(pngFile);
}
private void btnLoadXml_Click(object sender, EventArgs e)
{
var xml = FileDialogHelper.OpenXml();
if(!string.IsNullOrEmpty(xml))
{
diagramControl1.LoadDocument(xml);
}
}

最终案例的效果如下所示。

3、注册自定义的形状

在实际的图形绘制开发中,我们可以需要创建一些指定的形状模具,那么我们弄好后一般可以存放在XML中,然后进行加载到控件上来,如下代码就是注册自定义的形状的处理。

/// <summary>
/// 注册自定义的形状。
/// 自定义图形是以XML文件形式进行保存,图形需要按照规定XML格式进行绘制
/// </summary>
private void LoadShapes2()
{
var projectName = "SmallExampleDemo.Examples.XtraDiagram";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(projectName + ".CustomContainers.xml"))
{
var stencil = DiagramStencil.Create(MyStencilId, MyStencilName, stream, shapeName => shapeName);
DiagramToolboxRegistrator.RegisterStencil(stencil);
}
diagramControl1.SelectedStencils = new StencilCollection(MyStencilId);//(MyStencilId, BasicShapes.StencilId);
}

我们只需要设置选中的图形就可以了,其他有需要的可以从More Shapes中选择即可。

我们如果需要在属性窗口中显示自定义的属性,那么我们需要一些代码开发才能实现。

我们首先需要继承一个DiagramShape的子类,然后实现自己自定义的属性定义,如下代码所示。

对自定义属性的处理,需要在事件中实现

diagramControl1.CustomGetEditableItemProperties += DiagramControl_CustomGetEditableItemProperties;

通过对它进行判断可以实现自定义属性的显示处理

void DiagramControl_CustomGetEditableItemProperties(object sender, DiagramCustomGetEditableItemPropertiesEventArgs e)
{
if (e.Item is DiagramShapeEx)
{
e.Properties.Add(TypeDescriptor.GetProperties(typeof(DiagramShapeEx))["Status"]);
e.Properties.Add(TypeDescriptor.GetProperties(typeof(DiagramShapeEx))["TypeName"]);
}
}

然后我们可以注册创建自己的模具形状集合,如下代码所示。

/// <summary>
/// 创建自定义的模具
/// </summary>
/// <returns></returns>
DiagramStencil CreateCustomDrawShapesStencil()
{
var stencilId = "CustomedFlowShape";
var stencilName = "流程图";
var shapeSizeSmall = new Size(100, 37.5);
var shapeSize = new Size(100, 75); DiagramControl.ItemTypeRegistrator.Register(typeof(DiagramShapeEx));
var stencil = new DiagramStencil(stencilId, stencilName); //流程类型
stencil.RegisterTool(new FactoryItemTool("StartEnd", () => "流程开始", diagram => {
var shape = new DiagramShapeEx(BasicFlowchartShapes.StartEnd, "流程开始");
shape.Appearance.BackColor = Color.Red;
return shape;
}, shapeSizeSmall));
stencil.RegisterTool(new FactoryItemTool("Decision", () => "流程条件", diagram => {
var shape = new DiagramShapeEx(BasicFlowchartShapes.Decision, "流程条件");
shape.Appearance.BackColor = Color.FromArgb(199, 115, 1);//Color.Red;
return shape;
}, shapeSize));

这两个流程开始,流程条件,我们直接是从 BasicFlowchartShapes 集合中借用过来,构建自己的自定义对象的,默认创建的对象是方形的。

如果我们需要动态构建其他自定义类型,我们可以指定它的颜色等样式,从而构建不同类型的图形。

//循环添加相关流程节点
var procNames = new List<string> { "审批", "归档", "阅办", "会签", "领导批示分阅"};
//定义几个初始化颜色顺序
var colors = new List<Color> { Color.DeepSkyBlue, Color.ForestGreen, Color.Violet, Color.Yellow, Color.Blue, Color.Orange, Color.Indigo, Color.Purple, Color.Black, Color.Brown, Color.Pink };
int i = 0;
foreach (string name in procNames)
{
var shapeId = string.Format("Process_{0}", i++); stencil.RegisterTool(new FactoryItemTool(shapeId, () => name, diagram =>
{
var shape = new DiagramShapeEx(name, Status.Inactive);
var index = procNames.IndexOf(name);
var color = colors[index % 10];//Color.Red;
var fontColor = (color == Color.Yellow) ? Color.Black : Color.White; //没什么作用
//shape.ThemeStyleId = GetStyle(index); //从Accent1样式开始 DiagramShapeStyleId.Styles[index];//
shape.Appearance.BackColor = color;
shape.Appearance.BorderSize = 3;
shape.Appearance.Font = new Font("宋体", 12f, FontStyle.Bold);
shape.Appearance.ForeColor = fontColor;
return shape;
}, shapeSize));
}

这样就有不同颜色的图形对象了。

根据这些我们就可以绘制出自己的各种流程图了,并且也可以根据数据库的信息,进行动态绘制展示。

利用XtraDiagram.DiagramControl进行流程图形的绘制和控制的更多相关文章

  1. Quartz2D常见图形的绘制:线条、多边形、圆

    UI高级 Quartz2D http://ios.itcast.cn  iOS学院 掌握 drawRect:方法的使用 常见图形的绘制:线条.多边形.圆 绘图状态的设置:文字颜色.线宽等 图形上下文状 ...

  2. HTML5 Canvas ( 填充图形的绘制 ) closePath, fillStyle, fill

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 利用canvas阴影功能与双线技巧绘制轨道交通大屏项目效果

    利用canvas阴影功能与双线技巧绘制轨道交通大屏项目效果 前言 近日公司接到一个轨道系统的需求,需要将地铁线路及列车实时位置展示在大屏上.既然是大屏项目,那视觉效果当然是第一重点,咱们可以先来看看项 ...

  4. 利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解

    本文转载自利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解 导语 由于最近工作需要利用 Jenkins 远程 API 操作 Jenkins 来完成一些列操作,就抽空研究 ...

  5. 【HarmonyOS】【xml】使用xml绘制视频播放控制栏

    本文记录HarmonyOS使用xml绘制视频播放控制栏 效果图如下 代码如下 点击查看代码 <?xml version="1.0" encoding="utf-8& ...

  6. 利用Microsoft VC++6.0 的MFC 的绘图工具实现简单图形的绘制

          MFC运算功能强大,拥有完备的绘图功能.       在Windows平台上,应用程序的图形设备接口(graphics device interface,GDI)被抽象为设备上下文(Dev ...

  7. 利用CSS3 clip-path裁剪各种图形。

    'clip-path'是css3的一个强大属性,我们可以利用它来绘制各种各样的图形,当然不只是这些,接下来一起看看它的强大功能吧. 首先介绍的是clip-path里面的polygon功能,我们可以通过 ...

  8. 利用matplotlib的plot函数实现图像绘制

    模式识别的一个实验,要求画出贝叶斯决策的图.这里我是利用python中的matplotlib库实现的图线的拟合.主要对于matplotlib的使用可以参照博客:webary 如果要绘制三维图像可以参考 ...

  9. Qt之图形(绘制漂亮的圆弧)

    简述 综合前面对二维绘图的介绍,想必我们对一些基本绘图有了深入的了解,下面我们来实现一些漂亮的图形绘制. 简述 圆形 效果 源码 弧形 效果 源码 文本 效果 源码 旋转 效果 源码 圆形 经常地,我 ...

随机推荐

  1. 国产化之银河麒麟.netcore3.1访问https服务的两个问题

    背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用达梦V8,CPU平台的范围包括x64.龙芯.飞腾.鲲鹏等. 考虑到这些基础产品对.NETCore的支持,最终选择了3.1版 ...

  2. [原创][开源]C# Winform DPI自适应方案,SunnyUI三步搞定

    SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...

  3. 单列集合(Collection-List)

    与数组的区别 ArrayList while循环快捷键itit 遍历方法2:增强for循环 快捷键大写的I List接口(少部分常用的) List三种遍历方式 注意事项 ArrrayList底层结构和 ...

  4. Go Context 原理详解

    实现一个小目标 很开心的一件事,学习了一个月的后端拿到一个13k的offer,今年年底目标拿到一个30k的go方向offer. 好了回归正文,这篇文章是回答交流时一个老哥的问题,跟go的context ...

  5. [还不会搭建博客吗?]centos7系统部署hexo博客新手入门-进阶,看这一篇就够了

    @ 目录 *本文说明 请大家务必查看 前言 首先介绍一下主角:Hexo 什么是 Hexo? 环境准备 详细版 入门:搭建步骤 安装git: 安装node: 安装Hexo: 进阶:hexo基本操作 发布 ...

  6. Java 16 新特性:instanceof增强

    instanceof这个关键词,主要用来判断某个对象是不是某个类的实例. 比如,有时候我们要处理一个类似这样的数据集: Map<String, Object> data = new Has ...

  7. psexec.py规避杀软

    前言 在内网渗透中,当获取到一个账号密码后,经常会使用impacket套件中的psexec.py进行远程连接并执行命令,但是因为用的人多了,杀软也对psexec.py特征进行了拦截,也就导致了如果使用 ...

  8. 【多线程】可重入锁 ReentrantLock

    java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能.而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也 ...

  9. 手把手教你使用Git管理你的软件代码

    什么是分布式版本控制系统?Git有哪些常用命令?什么是仓库?Git的操作区域包括哪些?Git有哪些常用对象(object)?git rebase和git merge的区别是什么?git reset,g ...

  10. MAC M1安装多个JDK版本及动态切换

    JDK版本下载 下载地址:https://www.azul.com/downloads/?package=jdk 筛选一下macOS的ARM 64-bit架构的JDK版本,下载对应版本即可.最好直接下 ...