using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; using System.Xml; namespace Dongke.IBOSS.Basics.FlowSetting { /// /// 流程设计器 /// public partial class FlowBox : UserControl { #region 常量 #region 事件 private static readonly object EventNodeDoubleClick = new object(); private static readonly object EventFlowNodeLoading = new object(); #endregion 事件 //private const Version CurrentVersion = new Version(1, 1); #endregion 常量 #region 成员变量 /// /// 流程项目绘制管理器 /// private ItemManager _itemManager = null; /// /// 流程编辑模式 /// private FlowBoxMode _flowBoxMode = FlowBoxMode.Edit; /// /// 加载流程的版本 /// private Version _loadVersion = new Version(1, 1); /// /// 流程名称 /// private string _flowName = null; #endregion 成员变量 #region 构造函数 /// /// 构造函数 /// public FlowBox() { this.InitializeComponent(); this._itemManager = new ItemManager(this, this.canvasBox); this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT); this.canvasBox.CanvasControl.BackgroundImage = new Bitmap(this.GetType(), "Images.backImage1.gif"); this.canvasBox.CanvasControl.MouseDown += this.flowCanvas_MouseDown; this.canvasBox.CanvasControl.MouseMove += this.flowCanvas_MouseMove; this.canvasBox.CanvasControl.MouseUp += this.flowCanvas_MouseUp; this.canvasBox.CanvasControl.Paint += this.flowCanvas_Paint; this.canvasBox.CanvasControl.MouseDoubleClick += this.flowCanvas_MouseDoubleClick; this.canvasBox.KeyControl.KeyDown += this.keyControl_KeyDown; } #endregion 构造函数 #region 属性 /// /// 流程名称 /// public string FlowName { get { return this._flowName; } set { this._flowName = value; } } /// /// 加载流程的版本 /// public Version LoadVersion { get { return this._loadVersion; } } /// /// 流程编辑模式 /// public FlowBoxMode BoxMode { get { return this._flowBoxMode; } set { if (this._flowBoxMode != value) { this._flowBoxMode = value; this._itemManager.BoxMode = value; this.ClearSelection(); // todo } } } /// /// 获取或设置画布大小 /// public Size CanvasSize { get { return this.canvasBox.CanvasSize; } set { this.canvasBox.SetCanvasSize(value); this._itemManager.RefreshItems(); } } /// /// 获取或设置画布背景 /// public Image CanvasBackgroundImage { get { return this.canvasBox.CanvasBackgroundImage; } set { this.canvasBox.CanvasBackgroundImage = value; } } /// /// 获取画布 /// public Image CanvasImage { get { return this.canvasBox.CanvasImage; } //set //{ // this.canvasBox.CanvasImage = value; //} } /// /// 获取画布 /// public Control CanvasControl { get { return this.canvasBox.CanvasControl; } //set //{ // this.canvasBox.CanvasImage = value; //} } /// /// 获取全部流程项目 /// public List Items { get { return this._itemManager.Items; } } /// /// 获取选择的流程项目 /// public List SelectedItems { get { return this._itemManager.SelectedItems; } } /// /// 获取删除的节点 /// public List DeletedNodes { get { return this._itemManager.DeletedNodes; } } /// /// 获取全部的节点(包括删除的) /// public List AllNodes { get { return this._itemManager.AllNodes; } } ///// ///// 获取画板 ///// //internal CanvasBox CanvasBox //{ // get // { // return this.canvasBox; // } //} #endregion 属性 #region 事件处理 #region 画布事件 /// /// 画布绘制 /// /// /// private void flowCanvas_Paint(object sender, PaintEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this.canvasBox.SetSmoothingMode(e.Graphics); //this._itemManager.RefreshActiveItems(e.Graphics); this._itemManager.RefreshMouseSelectRect(e.Graphics); } /// /// 鼠标按下 /// /// /// private void flowCanvas_MouseDown(object sender, MouseEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this._itemManager.MouseDown(e); } /// /// 鼠标移动 /// /// /// private void flowCanvas_MouseMove(object sender, MouseEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this._itemManager.MouseMove(e); } /// /// 鼠标抬起 /// /// /// private void flowCanvas_MouseUp(object sender, MouseEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this._itemManager.MouseUp(e); } /// /// 鼠标双击 /// /// /// private void flowCanvas_MouseDoubleClick(object sender, MouseEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } NodeDoubleClickEventHandler nodeDoubleClick = this.GetNodeDoubleClickEventHandler(); if (nodeDoubleClick != null) { FlowNode node = this._itemManager.MouseDoubleClick(e); if (node != null) { nodeDoubleClick(this, new NodeEventArgs(node)); } } } #endregion 画布事件 #endregion 事件处理 #region 公有方法 #region 新建项目 /// /// 停止新建节点(鼠标操作) /// public void StopDrawingItem() { //if (this._flowBoxMode != FlowBoxMode.Edit) //{ // return; //} this._itemManager.StopDrawingItem(); } /// /// 新建节点(鼠标操作,指定位置) /// public FlowNode DrawingNode() { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.DrawingNode(); } /// /// 新建线段(鼠标操作,指定位置) /// public FlowLine DrawingLine() { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.DrawingLine(); } /// /// 新建节点(默认位置) /// /// 节点 public FlowNode NewNode() { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.NewNode(); } /// /// 新建节点(指定位置) /// /// 节点位置 public FlowNode NewNode(Point location) { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.NewNode(location); } /// /// 新建线段(默认位置) /// /// 线段 public FlowLine NewLine() { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.NewLine(); } /// /// 新建线段(指定位置) /// /// 起始点 /// 结束点 /// 线段 public FlowLine NewLine(Point pointBegin, Point pointEnd) { if (this._flowBoxMode != FlowBoxMode.Edit) { return null; } return this._itemManager.NewLine(pointBegin, pointEnd); } #endregion 新建项目 #region 刷新项目 /// /// 刷新Item的图片 /// public void RefreshItems() { this._itemManager.RefreshItems(); } #endregion 刷新项目 #region 操作项目 /// /// 全部不选择 /// public void ClearSelection() { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this._itemManager.ClearSelection(); this._itemManager.RefreshItems(); } /// /// 全部选择 /// public void SelectAllItem() { if (this._flowBoxMode == FlowBoxMode.Display) { return; } this._itemManager.SelectAllItems(); this._itemManager.RefreshItems(); } /// /// 删除全部项目 /// public void DeleteAllItem() { if (this._flowBoxMode != FlowBoxMode.Edit) { return; } this._itemManager.DeleteAllItems(); this._itemManager.RefreshItems(); } /// /// 删除选择项目 /// public void DeleteSelectedItem() { if (this._flowBoxMode != FlowBoxMode.Edit) { return; } this._itemManager.DeleteSelectedItems(); this._itemManager.RefreshItems(); } /// /// 撤销删除 /// /// 节点编码 public void UndeleteNodeByNodeCode(string nodeCode) { foreach (FlowNode node in this._itemManager.DeletedNodes) { if (node.ItemCode == nodeCode) { this._itemManager.DeletedNodes.Remove(node); this._itemManager.Items.Add(node); if (node.NodeState == FlowNodeState.Detached || node.NodeState == FlowNodeState.Added) { node.NodeState = FlowNodeState.Added; } else { node.NodeState = FlowNodeState.Unchanged; } return; } } } ///// ///// 对齐选定的节点 ///// ///// 对齐方式 //public void ArrangeNodes(ArrangeType arrangeType) //{ // this._itemManager.ArrangeNodes(arrangeType); //} ///// ///// 顶部对齐所有选中的节点 ///// //public void ArrangeNodesTop() //{ // this._itemManager.ArrangeNodesTop(); //} ///// ///// 底部对齐所有选中的节点 ///// //public void ArrangeNodesBottom() //{ // this._itemManager.ArrangeNodesBottom(); //} ///// ///// 左侧对齐所有选中的节点 ///// //public void ArrangeNodesLeft() //{ // this._itemManager.ArrangeNodesLeft(); //} ///// ///// 右侧对齐所有选中的节点 ///// //public void ArrangeNodesRight() //{ // this._itemManager.ArrangeNodesRight(); //} ///// ///// 垂直方向中心对齐所有选中的节点 ///// //public void ArrangeNodesVerticalCenter() //{ // this._itemManager.ArrangeNodesVerticalCenter(); //} ///// ///// 水平方向中心对齐所有选中的节点 ///// //public void ArrangeNodesHorizontalCenter() //{ // this._itemManager.ArrangeNodesHorizontalCenter(); //} #endregion 操作项目 #region 流程校验 /// /// 不完整的线 /// private List _incompleteLines = new List(); /// /// 全部线 /// private List _checkedLines = new List(); /// /// 独立的节点 /// private List _aloneNodes = new List(); /// /// 开始节点(包括前置节点是可以跳过的) /// private List _beginNodes = new List(); /// /// 结束节点(包括后置节点是可以跳过的) /// private List _endNodes = new List(); /// /// 中间节点 /// private List _generalNodes = new List(); /// /// 全部节点 /// private List _checkedNodes = new List(); /// /// 不完整的线(CheckFlow调用后) /// public List IncompleteLines { get { return this._incompleteLines; } } /// /// 全部线(CheckFlow调用后) /// public List CheckedLines { get { return this._checkedLines; } } /// /// 独立的节点(CheckFlow调用后) /// public List AloneNodes { get { return this._aloneNodes; } } /// /// 开始节点(包括前置节点是可以跳过的)(CheckFlow调用后) /// public List BeginNodes { get { return this._beginNodes; } } /// /// 结束节点(包括前置节点是可以跳过的)(CheckFlow调用后) /// public List EndNodes { get { return this._endNodes; } } /// /// 中间节点(CheckFlow调用后) /// public List GeneralNodes { get { return this._generalNodes; } } /// /// 全部节点(CheckFlow调用后) /// public List CheckedNodes { get { return this._checkedNodes; } } /// /// 校验流程 /// /// public bool CheckFlow() { this._incompleteLines.Clear(); this._checkedLines.Clear(); this._beginNodes.Clear(); this._endNodes.Clear(); this._generalNodes.Clear(); this._checkedNodes.Clear(); //this.ErrorNodes.Clear(); //this.ErrorMessages.Clear(); bool checkResult = true; foreach (FlowItem item in this.Items) { if (item is FlowLine) { FlowLine line = item as FlowLine; if (line.AnchorBegin == AnchorKind.None || line.AnchorEnd == AnchorKind.None) { this._incompleteLines.Add(line); } this._checkedLines.Add(line); } if (item is FlowNode) { FlowNode node = item as FlowNode; node.PreNodes.Clear(); node.NextNodes.Clear(); this._checkedNodes.Add(node); // 后续节点 this.SetNextNodes(node, null); // 前置节点 this.SetPreNodes(node, null); if (node.NodeType == FlowNodeType.Begin) { node.CheckedNodeType = FlowNodeType.Begin; this._beginNodes.Add(node); } else if (node.NodeType == FlowNodeType.End) { node.CheckedNodeType = FlowNodeType.End; this._endNodes.Add(node); if (node.CanSkip) { checkResult = false; //this.ErrorMessages.Add("结束节点不能跳过"); } } else if (node.NodeType == FlowNodeType.Alone) { node.CheckedNodeType = FlowNodeType.Alone; this._aloneNodes.Add(node); } //else { bool isBegin = false; bool isEnd = false; foreach (FlowNode preNode in node.PreNodes) { if (preNode.NodeType == FlowNodeType.Begin && preNode.CanSkip) { isBegin = true; break; } } foreach (FlowNode nextNode in node.NextNodes) { if (nextNode.NodeType == FlowNodeType.End && nextNode.CanSkip) { isEnd = true; break; } } if (isBegin && isEnd) { node.CheckedNodeType = FlowNodeType.Alone; this._aloneNodes.Add(node); } else if (isBegin) { node.CheckedNodeType = FlowNodeType.Begin; this._beginNodes.Add(node); } else if (isEnd) { node.CheckedNodeType = FlowNodeType.End; this._endNodes.Add(node); } else { node.CheckedNodeType = FlowNodeType.General; this._generalNodes.Add(node); } } } } if (this._incompleteLines.Count > 0) { checkResult = false; //this.ErrorMessages.Add("有未完成的连接线"); } if (this._beginNodes.Count == 0) { checkResult = false; //this.ErrorMessages.Add("没有开始节点"); } if (this._endNodes.Count == 0) { checkResult = false; //this.ErrorMessages.Add("没有结束节点"); } return checkResult; } #endregion 流程校验 #region 保存、读取 /// /// 清空流程 /// public void ClearFlow() { //if (this._flowBoxMode != FlowBoxMode.Edit) //{ // return; //} this._flowName = null; this._itemManager = new ItemManager(this, this.canvasBox); //this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT); //this.canvasBox.CanvasControl.BackgroundImage = new Bitmap(this.GetType(), "Images.backImage1.gif"); this._itemManager.RefreshItems(); } /// /// 保存流程(1.1) /// /// 二进制 public byte[] SaveFlow() { if (this._flowBoxMode == FlowBoxMode.Display) { return null; } using (MemoryStream memoryStream = new MemoryStream()) { if (this.SaveFlow(memoryStream)) { return memoryStream.ToArray(); } } return null; } /// /// 保存流程(1.1) /// /// 流 /// 是否成功 public bool SaveFlow(Stream stream) { if (this._flowBoxMode == FlowBoxMode.Display) { return false; } if (stream == null) { return false; } try { XmlDocument xmlDoc = this.SaveFlowXmlDoc(); if (xmlDoc != null) { xmlDoc.Save(stream); return true; } return false; } catch { return false; } } /// /// 保存流程(1.1) /// /// XML public string SaveFlowXml() { if (this._flowBoxMode == FlowBoxMode.Display) { return null; } XmlDocument xmlDoc = this.SaveFlowXmlDoc(); return xmlDoc.OuterXml; } /// /// 保存流程(1.1) /// /// XML public XmlDocument SaveFlowXmlDoc() { if (this._flowBoxMode == FlowBoxMode.Display) { return null; } return this.SaveFlowXmlDoc_1_1(); } /// /// 加载流程 /// /// 二进制 /// 是否成功 public bool LoadFlow(byte[] bytes) { if (bytes != null && 0 < bytes.Length) { using (MemoryStream memoryStream = new MemoryStream(bytes)) { memoryStream.Position = 0; return this.LoadFlow(memoryStream); } } return false; } /// /// 加载流程 /// /// 流 /// 是否成功 public bool LoadFlow(Stream stream) { //this.ClearFlow(); this._itemManager = new ItemManager(this, this.canvasBox); if (stream == null) { this._itemManager.RefreshItems(); return false; } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(stream); bool result = this.LoadFlowByVersion(xmlDoc); this._itemManager.RefreshItems(); return result; } catch { this._itemManager.RefreshItems(); return false; } } /// /// 加载流程 /// /// xml /// 是否成功 public bool LoadFlow(string xml) { //this.ClearFlow(); this._itemManager = new ItemManager(this, this.canvasBox); if (string.IsNullOrWhiteSpace(xml)) { this._itemManager.RefreshItems(); return false; } try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xml); bool result = this.LoadFlowByVersion(xmlDoc); this._itemManager.RefreshItems(); return result; } catch { this._itemManager.RefreshItems(); return false; } } #endregion 保存、读取 #endregion 公有方法 #region 内部方法 #endregion 内部方法 #region 受保护方法 #endregion 受保护方法 #region 私有方法 #region 事件相关 /// /// 获取节点双击的注册事件 /// /// private NodeDoubleClickEventHandler GetNodeDoubleClickEventHandler() { if (this._flowBoxMode < FlowBoxMode.LimitEdit) { return null; } return (NodeDoubleClickEventHandler)base.Events[FlowBox.EventNodeDoubleClick]; } /// /// 流程节点加载时事件 /// /// private FlowNodeLoadingEventHandler GetFlowNodeLoadingEventHandler() { return (FlowNodeLoadingEventHandler)base.Events[FlowBox.EventFlowNodeLoading]; } #endregion 事件相关 #region 流程校验 /// /// 设置前置节点 /// /// 需要设置的节点 /// 前置节点集合 private void SetPreNodes(FlowNode node, List preNodes) { preNodes = (preNodes == null) ? node.PreNodes : preNodes; foreach (FlowLine inLine in node.InLines) { if (inLine.AnchorBegin != AnchorKind.None) { FlowNode preNode = inLine.NodeBegin; if (preNode != null && !preNodes.Contains(preNode)) { preNodes.Add(preNode); if (preNode.CanSkip) { this.SetPreNodes(preNode, preNodes); } } } } } /// /// 设置后续节点 /// /// 需要设置的节点 /// 后续节点集合 private void SetNextNodes(FlowNode node, List nextNodes) { nextNodes = (nextNodes == null) ? node.NextNodes : nextNodes; foreach (FlowLine outLine in node.OutLines) { if (outLine.AnchorEnd != AnchorKind.None) { FlowNode nextNode = outLine.NodeEnd; if (nextNode != null && !nextNodes.Contains(nextNode)) { nextNodes.Add(nextNode); if (nextNode.CanSkip) { this.SetNextNodes(nextNode, nextNodes); } } } } } #endregion 流程校验 #region 保存、读取 /// /// 保存流程(1.1) /// /// XML private XmlDocument SaveFlowXmlDoc_1_1() { XmlDocument xmlDoc = new XmlDocument(); // 创建Xml声明部分,即 xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null)); // 根节点 XmlNode root = xmlDoc.CreateElement("FlowSetting"); // 版本 XmlAttribute version = xmlDoc.CreateAttribute("Version"); version.Value = "1.1"; root.Attributes.Append(version); // 编码 XmlAttribute managerCode = xmlDoc.CreateAttribute("ManagerCode"); managerCode.Value = this._itemManager.ManagerCode; root.Attributes.Append(managerCode); // 新项目ID //XmlNode newItemID = xmlDoc.CreateElement("NewItemID"); //newItemID.AppendChild(xmlDoc.CreateTextNode(this._itemManager.GetNewItemID().ToString())); //root.AppendChild(newItemID); XmlAttribute newItemID = xmlDoc.CreateAttribute("NewItemID"); newItemID.Value = this._itemManager.GetNewItemID().ToString(); root.Attributes.Append(newItemID); // 流程名称 XmlNode flowName = xmlDoc.CreateElement("FlowName"); flowName.AppendChild(xmlDoc.CreateCDataSection(this._flowName)); root.AppendChild(flowName); // 画布大小 XmlNode canvasSize = xmlDoc.CreateElement("CanvasSize"); canvasSize.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(this.CanvasSize))); root.AppendChild(canvasSize); //// 画布背景 //XmlNode backgroundImage = xmlDoc.CreateElement("BackgroundImage"); //backgroundImage.Value = Converter.ToXMLString(this.CanvasBox.CanvasBackgroundImage); //backgroundImage.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(this.CanvasBox.CanvasBackgroundImage))); //flowNode.AppendChild(backgroundImage); // FlowItems XmlNode flowItems = xmlDoc.CreateElement("FlowItems"); foreach (FlowItem item in this._itemManager.Items) { XmlNode flowItem = xmlDoc.CreateElement("FlowItem"); // ItemID XmlAttribute itemID = xmlDoc.CreateAttribute("ItemID"); itemID.Value = item.ItemID.ToString(); flowItem.Attributes.Append(itemID); // OnlyCode XmlAttribute itemCode = xmlDoc.CreateAttribute("ItemCode"); itemCode.Value = item.ItemCode; flowItem.Attributes.Append(itemCode); // ItemType XmlAttribute itemType = xmlDoc.CreateAttribute("ItemType"); itemType.Value = item.GetType().Name; flowItem.Attributes.Append(itemType); // ID XmlNode id = xmlDoc.CreateElement("ID"); id.AppendChild(xmlDoc.CreateTextNode(item.ID.ToString())); flowItem.AppendChild(id); // Code XmlNode code = xmlDoc.CreateElement("Code"); code.AppendChild(xmlDoc.CreateCDataSection(item.Code)); flowItem.AppendChild(code); // Name XmlNode name = xmlDoc.CreateElement("Name"); name.AppendChild(xmlDoc.CreateCDataSection(item.Name)); flowItem.AppendChild(name); // Remark XmlNode remark = xmlDoc.CreateElement("Remark"); remark.AppendChild(xmlDoc.CreateCDataSection(item.Remark)); flowItem.AppendChild(remark); // ShowName XmlNode showName = xmlDoc.CreateElement("ShowName"); showName.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.ShowName))); flowItem.AppendChild(showName); // Font XmlNode font = xmlDoc.CreateElement("Font"); font.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.Font))); flowItem.AppendChild(font); // FontColor XmlNode fontColor = xmlDoc.CreateElement("FontColor"); fontColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(item.FontColor))); flowItem.AppendChild(fontColor); // TagSerializable todo object XmlNode ts = xmlDoc.CreateElement("TS"); if (item.TagSerializable != null) { using (MemoryStream memoryStream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(memoryStream, item.TagSerializable); ts.AppendChild(xmlDoc.CreateTextNode(Convert.ToBase64String(memoryStream.ToArray()))); } } flowItem.AppendChild(ts); if (item is FlowNode) { FlowNode node = item as FlowNode; // Bounds XmlNode bounds = xmlDoc.CreateElement("Bounds"); bounds.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.Bounds))); flowItem.AppendChild(bounds); // BorderWidth XmlNode borderWidth = xmlDoc.CreateElement("BorderWidth"); borderWidth.AppendChild(xmlDoc.CreateTextNode(node.BorderWidth.ToString())); flowItem.AppendChild(borderWidth); // BorderColor XmlNode borderColor = xmlDoc.CreateElement("BorderColor"); borderColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.BorderColor))); flowItem.AppendChild(borderColor); // FillColor XmlNode fillColor = xmlDoc.CreateElement("FillColor"); if (node.FillColor.HasValue) { fillColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.FillColor))); } flowItem.AppendChild(fillColor); // CanSkip XmlNode canSkip = xmlDoc.CreateElement("CanSkip"); canSkip.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.CanSkip))); flowItem.AppendChild(canSkip); // NodeImageType XmlNode nodeImageType = xmlDoc.CreateElement("NodeImageType"); if (node.NodeImageType.HasValue) { nodeImageType.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.NodeImageType))); } flowItem.AppendChild(nodeImageType); // NodeImage XmlNode nodeImage = xmlDoc.CreateElement("NodeImage"); if (!node.NodeImageType.HasValue && node.NodeImage != null) { nodeImage.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(node.NodeImage))); } flowItem.AppendChild(nodeImage); } if (item is FlowLine) { FlowLine line = item as FlowLine; // PointBegin XmlNode pointBegin = xmlDoc.CreateElement("PointBegin"); pointBegin.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.PointBegin))); flowItem.AppendChild(pointBegin); // PointEnd XmlNode pointEnd = xmlDoc.CreateElement("PointEnd"); pointEnd.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.PointEnd))); flowItem.AppendChild(pointEnd); // LineColor XmlNode lineColor = xmlDoc.CreateElement("LineColor"); lineColor.AppendChild(xmlDoc.CreateTextNode(Converter.ToXMLString(line.LineColor))); flowItem.AppendChild(lineColor); // LineWidth XmlNode lineWidth = xmlDoc.CreateElement("LineWidth"); lineWidth.AppendChild(xmlDoc.CreateTextNode(line.LineWidth.ToString())); flowItem.AppendChild(lineWidth); // AnchorBegin XmlNode anchorBegin = xmlDoc.CreateElement("AnchorBegin"); if (line.NodeBegin == null) { line.AnchorBegin = AnchorKind.None; } else { anchorBegin.AppendChild(xmlDoc.CreateTextNode(line.NodeBegin.ItemCode)); } XmlAttribute kindBegin = xmlDoc.CreateAttribute("Kind"); kindBegin.Value = Converter.ToXMLString(line.AnchorBegin); anchorBegin.Attributes.Append(kindBegin); flowItem.AppendChild(anchorBegin); // AnchorEnd XmlNode anchorEnd = xmlDoc.CreateElement("AnchorEnd"); if (line.NodeEnd == null) { line.AnchorEnd = AnchorKind.None; } else { anchorEnd.AppendChild(xmlDoc.CreateTextNode(line.NodeEnd.ItemCode)); } XmlAttribute kindEnd = xmlDoc.CreateAttribute("Kind"); kindEnd.Value = Converter.ToXMLString(line.AnchorEnd); anchorEnd.Attributes.Append(kindEnd); flowItem.AppendChild(anchorEnd); } flowItems.AppendChild(flowItem); } root.AppendChild(flowItems); xmlDoc.AppendChild(root); return xmlDoc; } /// /// 根据文档版本加载流程 /// /// xml /// 是否成功 private bool LoadFlowByVersion(XmlDocument xmlDoc) { bool result = false; // 根节点 XmlNode root = xmlDoc.DocumentElement; if (root == null) { return result; } if ("WorkFlow" == root.Name) { this._loadVersion = new Version(1, 0); this.LoadFlow_1_0(root); result = true; } else if ("FlowSetting" == root.Name) { // 版本 string version = root.Attributes["Version"].Value; switch (version) { case "1.1": this._loadVersion = new Version(1, 1); this.LoadFlow_1_1(root); result = true; break; default: break; } } return result; } /// /// 加载流程(1.0) /// /// XML private void LoadFlow_1_0(XmlNode root) { int itemCount = 0; //获取结点列表 XmlNodeList xmlNodeChilds = root.SelectNodes("//arrNodeList//node"); foreach (XmlNode xmlNode in xmlNodeChilds) { itemCount++; XmlNodeList xnl = xmlNode.ChildNodes; int index = Convert.ToInt32(xmlNode.Attributes.Item(0).InnerText); int nodetype = Convert.ToInt32(xmlNode.Attributes.Item(1).InnerText); //itemCount = Math.Max(itemCount, index); FlowNode node = new FlowNode(this._itemManager, index, Guid.NewGuid().ToString()); node.NodeImageType = nodetype; node.Name = xnl.Item(0).InnerText; string fontname = xnl.Item(1).InnerText; int fontSize = Convert.ToInt32(xnl.Item(2).InnerText); node.Font = new System.Drawing.Font(fontname, fontSize); node.FontColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(3).InnerText)); node.BorderWidth = 0; node.BorderColor = Color.FromArgb(int.Parse(xnl.Item(4).InnerText)); node.FillColor = Color.FromArgb(int.Parse(xnl.Item(5).InnerText)); int height = Convert.ToInt32(xnl.Item(6).InnerText); int width = Convert.ToInt32(xnl.Item(7).InnerText); int x = Convert.ToInt32(xnl.Item(8).InnerText); int y = Convert.ToInt32(xnl.Item(9).InnerText); node.Bounds = new Rectangle(x, y, width, height); node.Remark = xnl.Item(17).InnerText; FlowNodeLoadingEventHandler flowNodeLoading = this.GetFlowNodeLoadingEventHandler(); if (flowNodeLoading != null) { flowNodeLoading(this, new NodeEventArgs(node)); } this._itemManager.Items.Add(node); this._itemManager.AllNodes.Add(node); } //获取线列表 XmlNodeList xmlLineChilds = root.SelectNodes("//arrLineList//line"); foreach (XmlNode xmlLine in xmlLineChilds) { XmlNodeList xnl = xmlLine.ChildNodes; int index = Convert.ToInt32(xmlLine.Attributes.Item(0).InnerText); int lineType = Convert.ToInt32(xmlLine.Attributes.Item(1).InnerText); FlowLine line = new FlowLine(this._itemManager, ++itemCount, Guid.NewGuid().ToString()); int x0 = Convert.ToInt32(xnl.Item(0).InnerText); int y0 = Convert.ToInt32(xnl.Item(1).InnerText); int x1 = Convert.ToInt32(xnl.Item(2).InnerText); int y1 = Convert.ToInt32(xnl.Item(3).InnerText); line.PointBegin = new Point(x0, y0); line.PointEnd = new Point(x1, y1); if (lineType == 1) { //line.X2 = Convert.ToInt32(xnl.Item(4).InnerText); //line.Y2 = Convert.ToInt32(xnl.Item(5).InnerText); //line.X3 = Convert.ToInt32(xnl.Item(6).InnerText); //line.Y3 = Convert.ToInt32(xnl.Item(7).InnerText); //line.LineNodeCount = Convert.ToInt32(xnl.Item(8).InnerText); if (xnl.Item(9).InnerText != "null") { int firstIndex = Convert.ToInt32(xnl.Item(9).InnerText); line.NodeBegin = this._itemManager.Items[firstIndex] as FlowNode; if (line.NodeBegin != null) { line.NodeBegin.OutLines.Add(line); int index1 = Convert.ToInt32(xnl.Item(11).InnerText); switch (index1) { case 0: line.AnchorBegin = AnchorKind.Top; line.NodeBegin.TopLines.Add(line); break; case 1: line.AnchorBegin = AnchorKind.Left; line.NodeBegin.LeftLines.Add(line); break; case 2: line.AnchorBegin = AnchorKind.Right; line.NodeBegin.RightLines.Add(line); break; case 3: line.AnchorBegin = AnchorKind.Bottom; line.NodeBegin.BottomLines.Add(line); break; default: break; } } } if (xnl.Item(10).InnerText != "null") { int secondIndex = Convert.ToInt32(xnl.Item(10).InnerText); line.NodeEnd = this._itemManager.Items[secondIndex] as FlowNode; if (line.NodeEnd != null) { line.NodeEnd.InLines.Add(line); int index2 = Convert.ToInt32(xnl.Item(12).InnerText); switch (index2) { case 0: line.AnchorEnd = AnchorKind.Top; line.NodeEnd.TopLines.Add(line); break; case 1: line.AnchorEnd = AnchorKind.Left; line.NodeEnd.LeftLines.Add(line); break; case 2: line.AnchorEnd = AnchorKind.Right; line.NodeEnd.RightLines.Add(line); break; case 3: line.AnchorEnd = AnchorKind.Bottom; line.NodeEnd.BottomLines.Add(line); break; default: break; } } } line.LineWidth = Convert.ToInt32(xnl.Item(13).InnerText); line.LineColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(14).InnerText)); line.Name = xnl.Item(15).InnerText; } else if (lineType == 0) { //line.LineNodeCount = Convert.ToInt32(xnl.Item(4).InnerText); if (xnl.Item(5).InnerText != "null") { int firstIndex = Convert.ToInt32(xnl.Item(5).InnerText); line.NodeBegin = this._itemManager.Items[firstIndex] as FlowNode; if (line.NodeBegin != null) { line.NodeBegin.OutLines.Add(line); int index3 = Convert.ToInt32(xnl.Item(7).InnerText); switch (index3) { case 0: line.AnchorBegin = AnchorKind.Top; line.NodeBegin.TopLines.Add(line); break; case 1: line.AnchorBegin = AnchorKind.Left; line.NodeBegin.LeftLines.Add(line); break; case 2: line.AnchorBegin = AnchorKind.Right; line.NodeBegin.RightLines.Add(line); break; case 3: line.AnchorBegin = AnchorKind.Bottom; line.NodeBegin.BottomLines.Add(line); break; default: break; } } } if (xnl.Item(6).InnerText != "null") { int secondIndex = Convert.ToInt32(xnl.Item(6).InnerText); line.NodeEnd = this._itemManager.Items[secondIndex] as FlowNode; if (line.NodeEnd != null) { line.NodeEnd.InLines.Add(line); int index4 = Convert.ToInt32(xnl.Item(8).InnerText); switch (index4) { case 0: line.AnchorEnd = AnchorKind.Top; line.NodeEnd.TopLines.Add(line); break; case 1: line.AnchorEnd = AnchorKind.Left; line.NodeEnd.LeftLines.Add(line); break; case 2: line.AnchorEnd = AnchorKind.Right; line.NodeEnd.RightLines.Add(line); break; case 3: line.AnchorEnd = AnchorKind.Bottom; line.NodeEnd.BottomLines.Add(line); break; default: break; } } } line.LineWidth = Convert.ToInt32(xnl.Item(9).InnerText); line.LineColor = System.Drawing.Color.FromArgb(int.Parse(xnl.Item(10).InnerText)); line.Name = xnl.Item(11).InnerText; } this._itemManager.Items.Add(line); } // 新项目ID this._itemManager.SetNewItemID(itemCount); // 画布大小 this.canvasBox.SetCanvasSize(Consts.CANVAS_SIZE_DEFAULT); } /// /// 加载流程(1.1) /// /// XML private void LoadFlow_1_1(XmlNode root) { //// 根节点 //XmlNode flowSetting = xmlDoc.SelectSingleNode("FlowSetting"); //// 版本 //string version = flowSetting.Attributes["Version"].Value; // 编码 this._itemManager.ManagerCode = root.Attributes["ManagerCode"].Value; // 新项目ID //this._itemManager.SetNewItemID(Convert.ToInt32(root.SelectSingleNode("NewItemID").InnerText)); this._itemManager.SetNewItemID(Convert.ToInt32(root.Attributes["NewItemID"].Value)); // 流程名称 this._flowName = root.SelectSingleNode("FlowName").InnerText; // 画布大小 this.canvasBox.SetCanvasSize(Converter.ToObject(root.SelectSingleNode("CanvasSize").InnerText)); //// 画布背景 //XmlNode backgroundImage = flowSetting.SelectSingleNode("BackgroundImage"); //this.canvasBox.CanvasControl.BackgroundImage = Converter.ToImage(backgroundImage.InnerText); // FlowItems XmlNode flowItems = root.SelectSingleNode("FlowItems"); foreach (XmlNode item in flowItems.ChildNodes) { int itemID = Convert.ToInt32(item.Attributes["ItemID"].Value); string itemCode = item.Attributes["ItemCode"].Value; string itemType = item.Attributes["ItemType"].Value; object ts = null; XmlNode tsXmlNode = item.SelectSingleNode("TS"); if (tsXmlNode != null && !string.IsNullOrWhiteSpace(tsXmlNode.InnerText)) { byte[] bytes = Convert.FromBase64String(tsXmlNode.InnerText); using (MemoryStream memoryStream = new MemoryStream(bytes)) { BinaryFormatter formatter = new BinaryFormatter(); ts = formatter.Deserialize(memoryStream); } } if (typeof(FlowNode).Name == itemType) { FlowNode node = new FlowNode(this._itemManager, itemID, itemCode); node.ID = Convert.ToInt32(item.SelectSingleNode("ID").InnerText); node.Code = item.SelectSingleNode("Code").InnerText; node.Name = item.SelectSingleNode("Name").InnerText; node.Remark = item.SelectSingleNode("Remark").InnerText; node.ShowName = Converter.ToObject(item.SelectSingleNode("ShowName").InnerText); node.Font = Converter.ToObject(item.SelectSingleNode("Font").InnerText); node.FontColor = Converter.ToObject(item.SelectSingleNode("FontColor").InnerText); node.TagSerializable = ts; node.Bounds = Converter.ToObject(item.SelectSingleNode("Bounds").InnerText); node.BorderWidth = Convert.ToInt32(item.SelectSingleNode("BorderWidth").InnerText); node.BorderColor = Converter.ToObject(item.SelectSingleNode("BorderColor").InnerText); node.FillColor = Converter.ToObject(item.SelectSingleNode("FillColor").InnerText); node.CanSkip = Converter.ToObject(item.SelectSingleNode("CanSkip").InnerText); node.NodeImageType = Converter.ToObject(item.SelectSingleNode("NodeImageType").InnerText); if (!node.NodeImageType.HasValue) { node.NodeImage = Converter.ToImage(item.SelectSingleNode("NodeImage").InnerText); } FlowNodeLoadingEventHandler flowNodeLoading = this.GetFlowNodeLoadingEventHandler(); if (flowNodeLoading != null) { flowNodeLoading(this, new NodeEventArgs(node)); } this._itemManager.Items.Add(node); this._itemManager.AllNodes.Add(node); continue; } if (typeof(FlowLine).Name == itemType) { FlowLine line = new FlowLine(this._itemManager, itemID, itemCode); line.ID = Convert.ToInt32(item.SelectSingleNode("ID").InnerText); line.Code = item.SelectSingleNode("Code").InnerText; line.Name = item.SelectSingleNode("Name").InnerText; line.Remark = item.SelectSingleNode("Remark").InnerText; line.ShowName = Converter.ToObject(item.SelectSingleNode("ShowName").InnerText); line.Font = Converter.ToObject(item.SelectSingleNode("Font").InnerText); line.FontColor = Converter.ToObject(item.SelectSingleNode("FontColor").InnerText); line.TagSerializable = ts; line.PointBegin = Converter.ToObject(item.SelectSingleNode("PointBegin").InnerText); line.PointEnd = Converter.ToObject(item.SelectSingleNode("PointEnd").InnerText); line.LineColor = Converter.ToObject(item.SelectSingleNode("LineColor").InnerText); line.LineWidth = Convert.ToInt32(item.SelectSingleNode("LineWidth").InnerText); XmlNode anchorBegin = item.SelectSingleNode("AnchorBegin"); line.AnchorBegin = Converter.ToObject(anchorBegin.Attributes["Kind"].Value); if (line.AnchorBegin != AnchorKind.None) { line.NodeCodeBegin = anchorBegin.InnerText; } XmlNode anchorEnd = item.SelectSingleNode("AnchorEnd"); line.AnchorEnd = Converter.ToObject(anchorEnd.Attributes["Kind"].Value); if (line.AnchorEnd != AnchorKind.None) { line.NodeCodeEnd = anchorEnd.InnerText; } this._itemManager.Items.Add(line); continue; } } // 连接 foreach (FlowItem item in this._itemManager.Items) { this.SetLineToNodeFromXml(item as FlowLine); } } /// /// 从xml加载流程后,把line链接到node上。 /// /// 线段 private void SetLineToNodeFromXml(FlowLine line) { if (line == null) { return; } bool hasC1 = false; bool hasC2 = false; if (line.AnchorBegin != AnchorKind.None || line.AnchorEnd != AnchorKind.None) { foreach (FlowItem item in this._itemManager.Items) { FlowNode node = item as FlowNode; if (node == null) { continue; } if (line.AnchorBegin != AnchorKind.None && node.ItemCode == line.NodeCodeBegin) { hasC1 = true; line.NodeBegin = node; node.OutLines.Add(line); switch (line.AnchorBegin) { case AnchorKind.Top: node.TopLines.Add(line); break; case AnchorKind.Left: node.LeftLines.Add(line); break; case AnchorKind.Right: node.RightLines.Add(line); break; case AnchorKind.Bottom: node.BottomLines.Add(line); break; default: break; } } if (line.AnchorEnd != AnchorKind.None && node.ItemCode == line.NodeCodeEnd) { hasC2 = true; line.NodeEnd = node; node.InLines.Add(line); switch (line.AnchorEnd) { case AnchorKind.Top: node.TopLines.Add(line); break; case AnchorKind.Left: node.LeftLines.Add(line); break; case AnchorKind.Right: node.RightLines.Add(line); break; case AnchorKind.Bottom: node.BottomLines.Add(line); break; default: break; } } } if (!hasC1) { line.AnchorBegin = AnchorKind.None; } if (!hasC2) { line.AnchorEnd = AnchorKind.None; } } } #endregion 保存、读取 #endregion 私有方法 #region 事件声明 /// /// 双击流程节点事件 /// public event NodeDoubleClickEventHandler NodeDoubleClick { add { base.Events.AddHandler(FlowBox.EventNodeDoubleClick, value); } remove { base.Events.RemoveHandler(FlowBox.EventNodeDoubleClick, value); } } /// /// 流程节点加载时事件 /// public event FlowNodeLoadingEventHandler FlowNodeLoading { add { base.Events.AddHandler(FlowBox.EventFlowNodeLoading, value); } remove { base.Events.RemoveHandler(FlowBox.EventFlowNodeLoading, value); } } #endregion 事件声明 #region 键盘事件 /// /// 键盘事件 /// /// /// private void keyControl_KeyDown(object sender, KeyEventArgs e) { if (this._flowBoxMode == FlowBoxMode.Display) { return; } switch(e.KeyCode) { case Keys.Escape: //this._itemManager.StopDrawingItem(); break; case Keys.Up: this._itemManager.MoveSelectedItems(0, -1); break; case Keys.Left: this._itemManager.MoveSelectedItems(-1, 0); break; case Keys.Right: this._itemManager.MoveSelectedItems(1, 0); break; case Keys.Down: this._itemManager.MoveSelectedItems(0, 1); break; default: return; } this._itemManager.RefreshItems(); } private void contextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e) { e.Cancel = true; } private void tsmiAllSelect_Click(object sender, EventArgs e) { this.SelectAllItem(); } private void tsmiDelete_Click(object sender, EventArgs e) { this.DeleteSelectedItem(); } #endregion 键盘事件 } }