模仿Word中组织结构图的特点生成流程图

//基本原理:   

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

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

//调用代码:   

Tree<string> tree = new Tree<string>(null, "董事会");
                tree.Add("北京公司");
                tree.Add("董事秘书室特殊机构");
                tree.Add("上海公司");   

                tree.Childs[0].Add("总经理办公室");
                tree.Childs[0].Add("财务部");
                tree.Childs[0].Add("销售部");   

                tree.Childs[2].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 }), 0);   

          return layers;
       }   

       void GetTreeLayers(List<List<Tree<T>>> layers, List<Tree<T>> childs, int level)
       {
           if (childs.Count == 0) return;
           if (layers.Count <= level) layers.Add(new List<Tree<T>>());   

          for (int i = 0; i < childs.Count; i++)
           {
               layers[level].Add(childs[i]);
               GetTreeLayers(layers, childs[i].Childs, level + 1);
           }
       }   

        /// <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 = 0;
           if (Parent != null) index = Parent.Childs.IndexOf(this);   

          if (Childs.Count == 0)
           {
               // 没有儿子,就向前靠
               if (left > 0) left += hInterval;
            }
         else
           {
               // 有儿子,就在儿子中间
               int centerX = (Childs[0].Rec.Left + Childs[Childs.Count - 1].Rec.Right) / 2;
               left = centerX - (int)_Size.Width / 2;   

              // 并且不能和前面的重复,如果重复,联同子孙和子孙的右边节点右移
              if (Parent != null && index > 0)
               {
                   int ex = (Parent.Childs[index - 1].Rec.Right + hInterval) - left;
                  if (index > 0 && ex > 0)
                  {
                      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 = 0; i < _Childs.Count; i++)
          {
              rec = _Childs[i].Rec;
               rec.Offset(ex, 0);
              _Childs[i].Rec = rec;
               _Childs[i].RightChilds(ex);
           }
     }   

      void Offset(int x, int y)
        {
            _Rec.Offset(x, y);
           for (int i = 0; i < _Childs.Count; i++)
               _Childs[i].Offset(x, y);
        }   

       public Bitmap DrawAsImage()
        {
           return DrawAsImage(Pens.Black, new Font("宋体", 10.5f), 26, 20, 5, 20, 26);
       }   

       public Bitmap DrawAsImage(Pen pen, Font font, int h, int horPadding,
           int horInterval, int verInterval, int borderWidth)
       {
           Bitmap bmp = new Bitmap(1, 1);
            Graphics g = Graphics.FromImage(bmp);
            // 把树扁平化
           List<List<Tree<T>>> layers = GetTreeLayers();   

         // 算出每个单元的大小
           MeatureAllSize(g, font, horPadding);
            g.Dispose();
           bmp.Dispose();   

           // 从最后一层开始排列
          int left = 0;
          for (int i = layers.Count - 1; i >= 0; i--)
          {
               for (int j = 0; 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 * 2;
           int maxWidth = 0;
            for (int i = layers.Count - 1; i >= 0; i--)
          {
               for (int j = 0; 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 = 0; i < layers.Count; i++)
          {
               for (int j = 0; 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 / 2, rec.Top,
                          rec.Left + rec.Width / 2, rec.Top - verInterval / 2);
                       g.DrawLine(pen, recParent.Left + recParent.Width / 2, recParent.Bottom,
                          recParent.Left + recParent.Width / 2, rec.Top - verInterval / 2);
                       g.DrawLine(pen, rec.Left + rec.Width / 2, rec.Top - verInterval / 2,
                           recParent.Left + recParent.Width / 2, rec.Top - verInterval / 2);
                  }
              }
          }   

          g.Flush();
          g.Dispose();   

          return bmp;
       }
   }
}   

时间: 2024-10-13 05:22:21

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

Word中使用VBA自动生成公式时的注意事项

Sub GenEQ()     If Selection.start <> Selection.End Then         Dim objRange As Range         Dim objEq As OMath              Set objRange = Selection.Range         '不能加入下面这行注释掉的代码,否则在日文版Word 2007和2010上将不能实现下面的灵活字体控制         'objRange.Text = Select

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

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

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

来自:在Word中如何自动生成参考文献引用 在写毕业论文时,参考文献动辄就有四五十篇,在文中对照参考文献逐一引用是一件十分痛苦的事情,而且一旦参考文献的顺序发生变化,文中的引用也要逐个修改,那么,我们如何自动生成参考文献引用呢? 方法/步骤 打开需要排版的论文: 我们使用一篇参考文献尚未编号的论文为例,从头讲解引用的自动生成过程. 我们首先对参考文献进行编号,编号的详细过程如图中所示: 然后,我们将光标放到需要插入参考文献引用的位置,在Word的“插入”模块中选择“交叉引用”: 在弹出的对话框中

Word中 简单宏的使用

 (注意:打开文档时按住 Shift 键可以阻止 AutoOpen 宏运行) 1:Word中能够自动运行的默认宏代码名称及触发条件如下 -------------------------------------------------------- 1.名称:AutoExec 条件:启动Word或加载全局模板 2.名称:AutoNew 条件:每次生成新文档时 3.名称:AutoOpen 条件:每次打开一个已有文档时 4.名称:AutoClose 条件:每次关闭文档时 5.名称:AutoExit

word中导出目录

word中导出目录是一个常见的问题.详细代码如下: public static void ExportMenu(int maxLevel, Document word) //利用标题样式生成目录 { //GoToTheBeginning(word); GotoBookMark("bmContent", word); object start = 0; object end = 0; Range myRange = word.Application.Selection.Range; //

java实现自动编号系统(类似于word中自动编号)

功能需求: 1,根据章节和当前标题数量,获得下一个编号,满足不同等级编号需求.如同word中的自动编号功能一样 2,可以实现在freemarker中直接调用生成方法,得到正确的编号 目标:即在freemarker代码中通过一个方法调用即可得到当前章节的编号 1 1.1 1.2 2 2.1 2.1.1 2.1.2 2.2 2.2.1 3 3.1 3.1.1 3.1.1.1 3.2 思路: 1,编号整体上是树形结构,因此要用树来管理整个列表 2,有一个方法可以根据最大值,获取下一个(比如:最大值3,

excel中vba将excel中数字和图表输出到word中

参考:https://wenku.baidu.com/view/6c60420ecc175527072208af.html 比如将选区变为图片保存到桌面: 1 Sub 将选区转为图片存到桌面() 2 Dim ans As Byte, Pic As String, Paths As String 3 On Error Resume Next 4 Paths = CreateObject("WScript.Shell").SpecialFolders("Desktop"

c# 操作word中在右下角插入图片

需求:需要对现有文档在右下角插入图片 /// <summary> /// 将图片插入到word中 /// </summary> /// <param name="wordPath">被操作的源word文档</param> /// <param name="picturePath">要插入的图片地址</param> /// <param name="toWordPath"

如何在Word中排出漂亮的代码

引言 学数学和计算机,当然还是用LaTeX排版技术文章更方便.但有时候还是迫不得已需要用Word写作,另外Word其实也有Word的好处,比如细节上的修改要比LaTeX方便. 从Matlab高亮代码复制到Word,中文会乱码开始,我就很想研究下如何在Word中展示漂亮的代码.今年寒假利用Vim,有些突破,10月3日的时候又有了比较大的进展,自己设计了一款Vim的代码高亮配色方案,然后利用Vim的:TOhtml命令生成html文件,再用浏览器打开html文件,复制里面的代码到Word,就能保留原始