For testing I set the Points in the NodeMouseClick event:
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();
}
Note that the above code connects the upper left points of the nodes.
To connect the outsides of the respective lines you could calculate the points like this:
Update: Big thanks to Larstech for his info about overriding the WndProc method and catching WM_PAINT. I tend to block out WndProc ;-)
Using this technique it is indeed possible to draw onto a TreeView:
This screenshot uses a TreeViewsubclass and paints three lines: One on each TV and one on the Panel below.
Here is the 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);
}
}
}
It exposes a bool to set if the TV is left or right of the other one and its BorderWidth, and a method markNode that determines which node should be connected with the lines and what slope the line has.
In
WinForms
TreeViews
are special.For one they don't have a
Paint
event, so it is not possible to draw on them. (You can subclass them though, see the update below..!)Secondly you can't nest a transparent control in them. You can nest it but it won't be transparent..)
So drawing onto the
TreeView
seems to be imposible. But maybe it is not what you want anyway..?Let's instead draw a line between two
TreeViews
, connection twoTreeNodes
n1 and n2.Let's place the TVs onto a
Panel panel1
.For testing I create two class level
Points p1 and p2
:In the
Panel's Paint
event we draw the line:For testing I set the
Points
in theNodeMouseClick
event:Note that the above code connects the upper left points of the nodes.
To connect the outsides of the respective lines you could calculate the points like this:
Update: Big thanks to Larstech for his info about overriding the WndProc method and catching WM_PAINT. I tend to block out WndProc ;-)
Using this technique it is indeed possible to draw onto a TreeView:
This screenshot uses a
TreeView
subclass and paints three lines: One on each TV and one on the Panel below.Here is the
TreeView
class:It exposes a bool to set if the TV is left or right of the other one and its
BorderWidth
, and a methodmarkNode
that determines which node should be connected with the lines and what slope the line has.The
NodeMouseClick
has been expanded a little:It now calculates the slope and calls both
markNode
andInvalidate
on both treeviews..No real changes in the Panel Paint: