1. //基本原理:
  2.  
  3. // 1. 从下往上计算位置
  4.  
  5. // 2. 模仿Word中组织结构图的特点
  6.  
  7. //调用代码:
  8.  
  9. Tree<string> tree = new Tree<string>(null, "董事会");
  10. tree.Add("北京公司");
  11. tree.Add("董事秘书室特殊机构");
  12. tree.Add("上海公司");
  13.  
  14. tree.Childs[].Add("总经理办公室");
  15. tree.Childs[].Add("财务部");
  16. tree.Childs[].Add("销售部");
  17.  
  18. tree.Childs[].Add("上海销售部");
  19.  
  20. Bitmap bmp = tree.DrawAsImage();
  21.  
  22. //实现代码:
  23.  
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Text;
  27. using System.Drawing;
  28.  
  29. namespace Test
  30.  
  31. {
  32. /// <summary>
  33. /// 用来输出组织结构图的类
  34. /// </summary>
  35. /// <typeparam name="T"></typeparam>
  36. public class Tree<T>
  37. {
  38. Tree<T> _Parent = null;
  39. T _Content;
  40. List<Tree<T>> _Childs = new List<Tree<T>>();
  41. SizeF _Size;
  42. Rectangle _Rec;
  43.  
  44. public Tree(Tree<T> parent, T content)
  45. {
  46. _Parent = parent;
  47. _Content = content;
  48. }
  49.  
  50. public Tree<T> Add(T content)
  51. {
  52. Tree<T> tree = new Tree<T>(this, content);
  53. _Childs.Add(tree);
  54. return tree;
  55. }
  56.  
  57. public Tree<T> Parent { get { return _Parent; } }
  58.  
  59. public T Content { get { return _Content; } }
  60.  
  61. public List<Tree<T>> Childs { get { return _Childs; } }
  62.  
  63. public SizeF Size { get { return _Size; } set { _Size = value; } }
  64.  
  65. public Rectangle Rec { get { return _Rec; } set { _Rec = value; } }
  66.  
  67. void MeatureAllSize(Graphics g, Font font, int addWidth)
  68. {
  69. _Size = g.MeasureString(_Content.ToString(), font);
  70. _Size.Width += addWidth;
  71. foreach (Tree<T> tree in Childs)
  72. tree.MeatureAllSize(g, font, addWidth);
  73. }
  74.  
  75. List<List<Tree<T>>> GetTreeLayers()
  76. {
  77. List<List<Tree<T>>> layers = new List<List<Tree<T>>>();
  78. GetTreeLayers(layers, new List<Tree<T>>(new Tree<T>[] { this }), );
  79.  
  80. return layers;
  81. }
  82.  
  83. void GetTreeLayers(List<List<Tree<T>>> layers, List<Tree<T>> childs, int level)
  84. {
  85. if (childs.Count == ) return;
  86. if (layers.Count <= level) layers.Add(new List<Tree<T>>());
  87.  
  88. for (int i = ; i < childs.Count; i++)
  89. {
  90. layers[level].Add(childs[i]);
  91. GetTreeLayers(layers, childs[i].Childs, level + );
  92. }
  93. }
  94.  
  95. /// <summary>
  96. /// 设置显示区域(从最后一层最左开始)
  97. /// </summary>
  98. /// <param name="level"></param>
  99. /// <param name="height"></param>
  100. /// <param name="interval"></param>
  101. /// <param name="left"></param>
  102. void SetRectangle(int level, int height, int hInterval, int vInterval, int left)
  103. {
  104. int index = ;
  105. if (Parent != null) index = Parent.Childs.IndexOf(this);
  106.  
  107. if (Childs.Count == )
  108. {
  109. // 没有儿子,就向前靠
  110. if (left > ) left += hInterval;
  111. }
  112. else
  113. {
  114. // 有儿子,就在儿子中间
  115. int centerX = (Childs[].Rec.Left + Childs[Childs.Count - ].Rec.Right) / ;
  116. left = centerX - (int)_Size.Width / ;
  117.  
  118. // 并且不能和前面的重复,如果重复,联同子孙和子孙的右边节点右移
  119. if (Parent != null && index > )
  120. {
  121. int ex = (Parent.Childs[index - ].Rec.Right + hInterval) - left;
  122. if (index > && ex > )
  123. {
  124. for (int i = index; i < Parent.Childs.Count; i++)
  125. Parent.Childs[i].RightChilds(ex);
  126. left += ex;
  127. }
  128. }
  129. }
  130. _Rec = new Rectangle(left, (height + vInterval) * level, (int)_Size.Width, height);
  131. }
  132.  
  133. /// <summary>
  134. /// 所有子孙向右平移
  135. /// </summary>
  136. /// <param name="ex"></param>
  137. void RightChilds(int ex)
  138. {
  139. Rectangle rec;
  140. for (int i = ; i < _Childs.Count; i++)
  141. {
  142. rec = _Childs[i].Rec;
  143. rec.Offset(ex, );
  144. _Childs[i].Rec = rec;
  145. _Childs[i].RightChilds(ex);
  146. }
  147. }
  148.  
  149. void Offset(int x, int y)
  150. {
  151. _Rec.Offset(x, y);
  152. for (int i = ; i < _Childs.Count; i++)
  153. _Childs[i].Offset(x, y);
  154. }
  155.  
  156. public Bitmap DrawAsImage()
  157. {
  158. return DrawAsImage(Pens.Black, new Font("宋体", 10.5f), , , , , );
  159. }
  160.  
  161. public Bitmap DrawAsImage(Pen pen, Font font, int h, int horPadding,
  162. int horInterval, int verInterval, int borderWidth)
  163. {
  164. Bitmap bmp = new Bitmap(, );
  165. Graphics g = Graphics.FromImage(bmp);
  166. // 把树扁平化
  167. List<List<Tree<T>>> layers = GetTreeLayers();
  168.  
  169. // 算出每个单元的大小
  170. MeatureAllSize(g, font, horPadding);
  171. g.Dispose();
  172. bmp.Dispose();
  173.  
  174. // 从最后一层开始排列
  175. int left = ;
  176. for (int i = layers.Count - ; i >= ; i--)
  177. {
  178. for (int j = ; j < layers[i].Count; j++)
  179. {
  180. layers[i][j].SetRectangle(i, h, horInterval, verInterval, left);
  181. left = layers[i][j].Rec.Right;
  182. }
  183. }
  184.  
  185. Offset(borderWidth, borderWidth);
  186.  
  187. // 获取画布需要的大小
  188. int maxHeight = (h + verInterval) * layers.Count - verInterval + borderWidth * ;
  189. int maxWidth = ;
  190. for (int i = layers.Count - ; i >= ; i--)
  191. {
  192. for (int j = ; j < layers[i].Count; j++)
  193. {
  194. if (layers[i][j].Rec.Right > maxWidth)
  195. maxWidth = layers[i][j].Rec.Right;
  196. }
  197. }
  198. maxWidth += borderWidth; // 边宽
  199.  
  200. // 画
  201. bmp = new Bitmap(maxWidth, maxHeight);
  202. g = Graphics.FromImage(bmp);
  203. g.Clear(Color.White);
  204. StringFormat format = (StringFormat)StringFormat.GenericDefault.Clone();
  205. format.Alignment = StringAlignment.Center;
  206. format.LineAlignment = StringAlignment.Center;
  207.  
  208. Rectangle rec, recParent;
  209. for (int i = ; i < layers.Count; i++)
  210. {
  211. for (int j = ; j < layers[i].Count; j++)
  212. {
  213. // 画字
  214. rec = (Rectangle)layers[i][j].Rec;
  215. g.DrawRectangle(pen, rec);
  216. g.DrawString(layers[i][j].Content.ToString(), font, new SolidBrush(pen.Color),
  217. rec, format);
  218. // 画到父亲的线
  219. if (layers[i][j].Parent != null)
  220. {
  221. recParent = layers[i][j].Parent.Rec;
  222. g.DrawLine(pen, rec.Left + rec.Width / , rec.Top,
  223. rec.Left + rec.Width / , rec.Top - verInterval / );
  224. g.DrawLine(pen, recParent.Left + recParent.Width / , recParent.Bottom,
  225. recParent.Left + recParent.Width / , rec.Top - verInterval / );
  226. g.DrawLine(pen, rec.Left + rec.Width / , rec.Top - verInterval / ,
  227. recParent.Left + recParent.Width / , rec.Top - verInterval / );
  228. }
  229. }
  230. }
  231.  
  232. g.Flush();
  233. g.Dispose();
  234.  
  235. return bmp;
  236. }
  237. }
  238. }

模仿Word中组织结构图的特点生成流程图的更多相关文章

  1. WPS:在Word中插入Visio绘制的流程图

    在Word菜单栏 插入->对象 如果Visio绘图已经保存为了文件,可以选择由文件创建

  2. WORD中怎样自己主动生成文件夹?

    步骤: 1.输入当做标题的文字 2.将文字设置为标题样式 3.光标放在要加入�文件夹的位置 4.选择插入->引用->索引和文件夹->文件夹->确定

  3. js生成word中图片处理

    首先功能是要求前台导出word,但是前后台是分离的,图片存在后台,所以就存在跨域问题. 导出文字都是没有问题的(jquery.wordexport.js),但是导出图片就存在问题了: 图片是以链接形式 ...

  4. 在Word中如何自动生成参考文献引用

    来自:在Word中如何自动生成参考文献引用 在写毕业论文时,参考文献动辄就有四五十篇,在文中对照参考文献逐一引用是一件十分痛苦的事情,而且一旦参考文献的顺序发生变化,文中的引用也要逐个修改,那么,我们 ...

  5. 使用POI替换word中的特定字符/文字改进版

    package com.xfzx.test.POI.main; import java.io.File; import java.io.FileInputStream; import java.io. ...

  6. 在word中批量制作条形码

    条码打印软件可以批量生成条形码然后直接打印,但是有些客户不需要直接打印,而是想将生成的条形码在word中进行排版,发给自己的客户或者下属部门来打印.那么如何实现在word中批量制作条形码呢? 操作很简 ...

  7. C# 操作Word 中的OLE——插入、编辑、读取 OLE

    概述 OLE,Object Linking and Embedding,即对象连接与嵌入.我们在设计程序时,OLE可以用来创建复合文档,把文字.声音.图像.表格.应用程序等类型的信息组合在一起,在Wo ...

  8. Microsoft Office Word 中的公式自动编号

    先插入公式,#,插入题注(交叉引用),生成了标号.此时整个公式是题注样式.在公式和标号之间插入一个样式分隔符. ____________________________________________ ...

  9. Word中一条删除不掉的单或双横线的解决办法

    Word中一条删除不掉的单或双横线 有时你或许会遇到这样一种情况:在word中,有一条单或双横线怎么都删除不了,并且具有这样的特点: 在上面输入文字,横线会自动下调一行,如果文章过页,每页的尾部会有一 ...

随机推荐

  1. CarDAQ-Plus

    Overview CarDAQ-Plus is the most validated and accepted J2534 device in the world. It has been on th ...

  2. 通过RDB还原用户误删除的邮件

    1.在任意一台邮箱服务器上新建RDB数据库目录:C:\rdb01 2.使用Windows Server Backup还原已备份的邮件数据(mbdb02)库到 C:\rdb01 目录下 3.创建RDB数 ...

  3. jquery,extjs中的extend用法小结

    在jquery中,extend其实在做插件时还是用的比较多的,今天同时小结jquery和ext js中 的extend用法,先来看jquery中的. 1)  extend(dest,src1,src2 ...

  4. MVC4数据注释与验证 2

    Using Validation Annotations Required必须项验证属性 [Required] public string FirstName { get; set; } [Requi ...

  5. IE9-10 option BUG

    IE 9-10下如果option元素没有定义value而在设置innerText时没有把两边的空白去掉,那么 取el.text,浏览器会进行trim, 并且伪造一个value值,此值会在刚才trim的 ...

  6. <QtEndian> - Endian Conversion Functions

    The <QtEndian> header provides functions to convert between little and big endian representati ...

  7. mysql性能优化(二)

    ###> mysql中有一个explain 命令可以用来分析select 语句的运行效果,例如explain可以获得select语句使用的索引情况.排序的情况等等.除此以外,explain 的e ...

  8. hive和hbase整合的原因和原理

    为什么要进行hive和hbase的整合? hive是高延迟.结构化和面向分析的: hbase是低延迟.非结构化和面向编程的. Hive集成Hbase就是为了使用hbase的一些特性.或者说是中和它们的 ...

  9. Unity3D 使用 UI 的 Grid Layout Group 组件。

    1.首先创建一个容器,用于存放列表项的内容. 这里使用 Panel 来做为容器. 这里要注意! “Grid Layout Group”是要增加在容器的游戏对象里. 同时,只有容器对象的子对象才有排列效 ...

  10. Android进阶笔记17:3种JSON解析工具(org.json、fastjson、gson)

    一. 目前解析json有三种工具:org.json(Java常用的解析),fastjson(阿里巴巴工程师开发的),Gson(Google官网出的),其中解析速度最快的是Gson. 3种json工具下 ...