//
基本原理:
//
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;
}
}
}
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

