//基本原理:   

 // 1. 从下往上计算位置   

 // 2. 模仿Word中组织结构图的特点   

//调用代码:   

Tree<string> tree = new Tree<string>(null, "董事会");
tree.Add("北京公司");
tree.Add("董事秘书室特殊机构");
tree.Add("上海公司"); tree.Childs[].Add("总经理办公室");
tree.Childs[].Add("财务部");
tree.Childs[].Add("销售部"); tree.Childs[].Add("上海销售部"); Bitmap bmp = tree.DrawAsImage(); //实现代码: using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing; namespace Test {
/// <summary>
/// 用来输出组织结构图的类
/// </summary>
/// <typeparam name="T"></typeparam>
public class Tree<T>
{
Tree<T> _Parent = null;
T _Content;
List<Tree<T>> _Childs = new List<Tree<T>>();
SizeF _Size;
Rectangle _Rec; public Tree(Tree<T> parent, T content)
{
_Parent = parent;
_Content = content;
} public Tree<T> Add(T content)
{
Tree<T> tree = new Tree<T>(this, content);
_Childs.Add(tree);
return tree;
} public Tree<T> Parent { get { return _Parent; } } public T Content { get { return _Content; } } public List<Tree<T>> Childs { get { return _Childs; } } public SizeF Size { get { return _Size; } set { _Size = value; } } public Rectangle Rec { get { return _Rec; } set { _Rec = value; } } void MeatureAllSize(Graphics g, Font font, int addWidth)
{
_Size = g.MeasureString(_Content.ToString(), font);
_Size.Width += addWidth;
foreach (Tree<T> tree in Childs)
tree.MeatureAllSize(g, font, addWidth);
} List<List<Tree<T>>> GetTreeLayers()
{
List<List<Tree<T>>> layers = new List<List<Tree<T>>>();
GetTreeLayers(layers, new List<Tree<T>>(new Tree<T>[] { this }), ); return layers;
} void GetTreeLayers(List<List<Tree<T>>> layers, List<Tree<T>> childs, int level)
{
if (childs.Count == ) return;
if (layers.Count <= level) layers.Add(new List<Tree<T>>()); for (int i = ; i < childs.Count; i++)
{
layers[level].Add(childs[i]);
GetTreeLayers(layers, childs[i].Childs, level + );
}
} /// <summary>
/// 设置显示区域(从最后一层最左开始)
/// </summary>
/// <param name="level"></param>
/// <param name="height"></param>
/// <param name="interval"></param>
/// <param name="left"></param>
void SetRectangle(int level, int height, int hInterval, int vInterval, int left)
{
int index = ;
if (Parent != null) index = Parent.Childs.IndexOf(this); if (Childs.Count == )
{
// 没有儿子,就向前靠
if (left > ) left += hInterval;
}
else
{
// 有儿子,就在儿子中间
int centerX = (Childs[].Rec.Left + Childs[Childs.Count - ].Rec.Right) / ;
left = centerX - (int)_Size.Width / ; // 并且不能和前面的重复,如果重复,联同子孙和子孙的右边节点右移
if (Parent != null && index > )
{
int ex = (Parent.Childs[index - ].Rec.Right + hInterval) - left;
if (index > && ex > )
{
for (int i = index; i < Parent.Childs.Count; i++)
Parent.Childs[i].RightChilds(ex);
left += ex;
}
}
}
_Rec = new Rectangle(left, (height + vInterval) * level, (int)_Size.Width, height);
} /// <summary>
/// 所有子孙向右平移
/// </summary>
/// <param name="ex"></param>
void RightChilds(int ex)
{
Rectangle rec;
for (int i = ; i < _Childs.Count; i++)
{
rec = _Childs[i].Rec;
rec.Offset(ex, );
_Childs[i].Rec = rec;
_Childs[i].RightChilds(ex);
}
} void Offset(int x, int y)
{
_Rec.Offset(x, y);
for (int i = ; i < _Childs.Count; i++)
_Childs[i].Offset(x, y);
} public Bitmap DrawAsImage()
{
return DrawAsImage(Pens.Black, new Font("宋体", 10.5f), , , , , );
} public Bitmap DrawAsImage(Pen pen, Font font, int h, int horPadding,
int horInterval, int verInterval, int borderWidth)
{
Bitmap bmp = new Bitmap(, );
Graphics g = Graphics.FromImage(bmp);
// 把树扁平化
List<List<Tree<T>>> layers = GetTreeLayers(); // 算出每个单元的大小
MeatureAllSize(g, font, horPadding);
g.Dispose();
bmp.Dispose(); // 从最后一层开始排列
int left = ;
for (int i = layers.Count - ; i >= ; i--)
{
for (int j = ; j < layers[i].Count; j++)
{
layers[i][j].SetRectangle(i, h, horInterval, verInterval, left);
left = layers[i][j].Rec.Right;
}
} Offset(borderWidth, borderWidth); // 获取画布需要的大小
int maxHeight = (h + verInterval) * layers.Count - verInterval + borderWidth * ;
int maxWidth = ;
for (int i = layers.Count - ; i >= ; i--)
{
for (int j = ; j < layers[i].Count; j++)
{
if (layers[i][j].Rec.Right > maxWidth)
maxWidth = layers[i][j].Rec.Right;
}
}
maxWidth += borderWidth; // 边宽 // 画
bmp = new Bitmap(maxWidth, maxHeight);
g = Graphics.FromImage(bmp);
g.Clear(Color.White);
StringFormat format = (StringFormat)StringFormat.GenericDefault.Clone();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center; Rectangle rec, recParent;
for (int i = ; i < layers.Count; i++)
{
for (int j = ; j < layers[i].Count; j++)
{
// 画字
rec = (Rectangle)layers[i][j].Rec;
g.DrawRectangle(pen, rec);
g.DrawString(layers[i][j].Content.ToString(), font, new SolidBrush(pen.Color),
rec, format);
// 画到父亲的线
if (layers[i][j].Parent != null)
{
recParent = layers[i][j].Parent.Rec;
g.DrawLine(pen, rec.Left + rec.Width / , rec.Top,
rec.Left + rec.Width / , rec.Top - verInterval / );
g.DrawLine(pen, recParent.Left + recParent.Width / , recParent.Bottom,
recParent.Left + recParent.Width / , rec.Top - verInterval / );
g.DrawLine(pen, rec.Left + rec.Width / , rec.Top - verInterval / ,
recParent.Left + recParent.Width / , rec.Top - verInterval / );
}
}
} g.Flush();
g.Dispose(); return bmp;
}
}
}

模仿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. C#利用GDI+绘制旋转文字等效果

    C#中利用GDI+绘制旋转文本的文字,网上有很多资料,基本都使用矩阵旋转的方式实现.但基本都只提及按点旋转,若要实现在矩形范围内旋转文本,资料较少.经过琢磨,可以将矩形内旋转转化为按点旋转,不过需要经 ...

  2. Linux makefile 教程 很具体,且易懂

    近期在学习Linux下的C编程,买了一本叫<Linux环境下的C编程指南>读到makefile就越看越迷糊,可能是我的理解能不行. 于是google到了下面这篇文章.通俗易懂.然后把它贴出 ...

  3. php获取当前url完整地址

    //获取当前访问的完整url地址 function getCurUrl() { $url = 'http://'; if (isset($_SERVER['HTTPS']) && $_ ...

  4. sublime添加ctags实现代码跳转

    本次操作是在sublime text 2下进行. 1.先到http://sublime.wbond.net/Package%20Control.sublime-package下载Package Con ...

  5. 史上最详细版!java文件打包成exe,在未配置安装JDK和未配置的电脑上运行--转载

    原文地址:http://funine.iteye.com/blog/2220359 (本文所有素材将在文章最后附上) 准备工具exe4j, converticon.com(用于制做.ico格式的图片) ...

  6. mysql 查看表记录新增、修改的时间

    ALTER TABLE `tableName` ADD `updateAt` TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP; ALTER TABLE kd_up ...

  7. 亚马逊副总裁谈Marketplace平台的个性化服务

    说到个性化,亚马逊无疑是挖掘与利用数据为消费者打造个性化网购体验的先驱之一.而现在,几乎所有的公司和网站都在利用更加个性化的推荐算法为用户提供更好的购物和浏览体验. 亚马逊近年来尤其重视将其个性化特性 ...

  8. c++11 Chrono时间库

    c++11 Chrono时间库 http://en.cppreference.com/mwiki/index.php?title=Special%3ASearch&search=chrono ...

  9. CentOS6.5 64bit 运行Mono程序

    前几日和一技术友聊天,认为转Java好,java可以在Linux下运行,貌似c#不可以哦,就做了个尝试,运行控制台程序和窗口程序(界面编程,Linux下Java好像也比较烦吧) 现在贴环境: 参考:C ...

  10. emWin使用外部SRAM的方法

    我用的是stm32,加了1MB的外部SRAM,在使用emWin的时候,将一部分内存分配给emWin使用.其实方法很简单,传入SRAM数据总线地址即可,数据位宽我采用16bit,因为使用的SRAM是16 ...