将一个树视图的 link 树视图节点画线到另一个树视图的树视图节点
Drawing line to link treeview node of one treeview to treeview node of another treeview
如何画一条线到 link 树视图节点到另一个树视图节点
link should be shown in from
在WinForms
中TreeViews
是特殊的。
他们没有 Paint
事件,因此无法利用它们。
(不过你可以子class他们,看下面的更新..!)
其次不能在其中嵌套透明控件。你可以嵌套它但它不会透明..)
所以在 TreeView
上绘图似乎是不可能的。但也许这不是你想要的..?
让我们画一条线在两个TreeViews
之间,连接两个TreeNodes
n1和n2。
让我们把电视放在 Panel panel1
上。
为了测试,我创建了两个 class 级别 Points p1 and p2
:
Point p1 = Point.Empty;
Point p2 = Point.Empty;
在 Panel's Paint
事件中我们画线:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Firebrick, p1, p2);
}
为了测试,我在 NodeMouseClick
事件中设置了 Points
:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
// for testing I search for a corresponding node:
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
// for testing I select the node:
treeView2.SelectedNode = n2;
// top left points in the node:
p1 = n1.Bounds.Location;
p2 = n2.Bounds.Location;
// add the offset of the treviews:
p1.Offset(treeView1.Left, treeView1.Top);
p2.Offset(treeView2.Left, treeView2.Top);
// trigger the paint event;
panel1.Invalidate();
}
注意上面的代码连接了节点的左上角
要连接各个线的外侧,您可以这样计算点:
p1 = new Point(treeView1.Right, n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.Top);
p2 = new Point(treeView2.Left, n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.Top);
更新: 非常感谢 Larstech 提供有关覆盖 WndProc 方法和捕获 WM_PAINT 的信息。我倾向于屏蔽 WndProc ;-)
使用这种技术确实可以绘制到 TreeView 上:
此屏幕截图使用 TreeView
subclass 并绘制三行:每台电视上一行,下方面板上一行。
这里是 TreeView
class:
class PTreeView : TreeView
{
public bool IsLeft { get; set; }
public int BorderWidth { get; private set; }
private float slope { get; set; }
private Point Pt { get; set; }
public PTreeView() { }
public void markNode(TreeNode node, float slope_)
{
if (this.IsLeft ) Pt =
new Point(node.Bounds.Right, node.Bounds.Top + node.Bounds.Height / 2);
else Pt = new Point(node.Bounds.Left, node.Bounds.Top + node.Bounds.Height / 2);
slope = slope_;
BorderWidth = (this.Width - this.ClientRectangle.Width) / 2;
}
internal const int WM_PAINT = 0xF;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
{
Graphics G = this.CreateGraphics();
G.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int px = IsLeft ? this.ClientRectangle.Width : 0;
int py = (int)(Pt.Y + slope * (Pt.X - px));
Point p0 = new Point(px, py);
G.DrawLine(Pens.Coral, Pt, p0);
}
}
}
它公开了一个 bool 来设置电视是在另一台电视的左边还是右边及其 BorderWidth
,以及一个方法 markNode
确定哪个节点应该与线路连接以及什么直线的斜率。
NodeMouseClick
扩展了一点:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
treeView2.SelectedNode = n2;
p1 = new Point(
treeView1.Left + n2.Bounds.Left + n1.Bounds.Width + treeView1.BorderWidth,
treeView1.Top + n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.BorderWidth);
p2 = new Point(
treeView2.Left + n2.Bounds.Left + treeView2.BorderWidth,
treeView2.Top + n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.BorderWidth);
float slope = -1f * (p2.Y - p1.Y) / (p2.X - p1.X);
treeView1.markNode(n1, slope);
treeView2.markNode(n2, slope);
panel1.Invalidate();
treeView1.Invalidate();
treeView2.Invalidate();
}
它现在计算斜率并在两个树视图上同时调用 markNode
和 Invalidate
..
Panel Paint 没有真正的变化:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawLine(Pens.Coral, p1, p2);
}
如何画一条线到 link 树视图节点到另一个树视图节点
link should be shown in from
在WinForms
中TreeViews
是特殊的。
他们没有
Paint
事件,因此无法利用它们。 (不过你可以子class他们,看下面的更新..!)其次不能在其中嵌套透明控件。你可以嵌套它但它不会透明..)
所以在 TreeView
上绘图似乎是不可能的。但也许这不是你想要的..?
让我们画一条线在两个TreeViews
之间,连接两个TreeNodes
n1和n2。
让我们把电视放在 Panel panel1
上。
为了测试,我创建了两个 class 级别 Points p1 and p2
:
Point p1 = Point.Empty;
Point p2 = Point.Empty;
在 Panel's Paint
事件中我们画线:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Firebrick, p1, p2);
}
为了测试,我在 NodeMouseClick
事件中设置了 Points
:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
// for testing I search for a corresponding node:
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
// for testing I select the node:
treeView2.SelectedNode = n2;
// top left points in the node:
p1 = n1.Bounds.Location;
p2 = n2.Bounds.Location;
// add the offset of the treviews:
p1.Offset(treeView1.Left, treeView1.Top);
p2.Offset(treeView2.Left, treeView2.Top);
// trigger the paint event;
panel1.Invalidate();
}
注意上面的代码连接了节点的左上角
要连接各个线的外侧,您可以这样计算点:
p1 = new Point(treeView1.Right, n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.Top);
p2 = new Point(treeView2.Left, n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.Top);
更新: 非常感谢 Larstech 提供有关覆盖 WndProc 方法和捕获 WM_PAINT 的信息。我倾向于屏蔽 WndProc ;-)
使用这种技术确实可以绘制到 TreeView 上:
此屏幕截图使用 TreeView
subclass 并绘制三行:每台电视上一行,下方面板上一行。
这里是 TreeView
class:
class PTreeView : TreeView
{
public bool IsLeft { get; set; }
public int BorderWidth { get; private set; }
private float slope { get; set; }
private Point Pt { get; set; }
public PTreeView() { }
public void markNode(TreeNode node, float slope_)
{
if (this.IsLeft ) Pt =
new Point(node.Bounds.Right, node.Bounds.Top + node.Bounds.Height / 2);
else Pt = new Point(node.Bounds.Left, node.Bounds.Top + node.Bounds.Height / 2);
slope = slope_;
BorderWidth = (this.Width - this.ClientRectangle.Width) / 2;
}
internal const int WM_PAINT = 0xF;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT)
{
Graphics G = this.CreateGraphics();
G.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
int px = IsLeft ? this.ClientRectangle.Width : 0;
int py = (int)(Pt.Y + slope * (Pt.X - px));
Point p0 = new Point(px, py);
G.DrawLine(Pens.Coral, Pt, p0);
}
}
}
它公开了一个 bool 来设置电视是在另一台电视的左边还是右边及其 BorderWidth
,以及一个方法 markNode
确定哪个节点应该与线路连接以及什么直线的斜率。
NodeMouseClick
扩展了一点:
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
TreeNode n1 = e.Node;
TreeNode n2 = treeView2.Nodes.Find(n1.Name, true).First();
treeView2.SelectedNode = n2;
p1 = new Point(
treeView1.Left + n2.Bounds.Left + n1.Bounds.Width + treeView1.BorderWidth,
treeView1.Top + n1.Bounds.Top + n1.Bounds.Height / 2 + treeView1.BorderWidth);
p2 = new Point(
treeView2.Left + n2.Bounds.Left + treeView2.BorderWidth,
treeView2.Top + n2.Bounds.Top + n2.Bounds.Height / 2 + treeView2.BorderWidth);
float slope = -1f * (p2.Y - p1.Y) / (p2.X - p1.X);
treeView1.markNode(n1, slope);
treeView2.markNode(n2, slope);
panel1.Invalidate();
treeView1.Invalidate();
treeView2.Invalidate();
}
它现在计算斜率并在两个树视图上同时调用 markNode
和 Invalidate
..
Panel Paint 没有真正的变化:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawLine(Pens.Coral, p1, p2);
}