Hi I have written a Treeview control using DrawMode (OwnerDrawAll) Event OnNodeMouseDoubleClick , OnAfterExpand and OnAfterCollapse these work fine without any problems BUT (OnNodeMouseHover) that Ive written does not work
Any suggestions as to what i can do when using Drawmode (OwnerDrawAll) and still get (OnNodeMouseHover) to work properly? | | for loop Friday, September 04, 2009 10:32 AM | Hi for loop,
I have tested the code you provided and found out the main issue is that the Text property of the TreeNode is not set. In your code snippet, the text drawn on the node is the id, so we need to set the text of the node to its id. We need to make sure the NodeFont property of the TreeNode to be the font we used to draw the text and the Text property to be the text drawn on the node. This is because when we handle some events the argument of which contains the bounds of the TreeNode, itwould measure the bounds before the events are fired. The bounds includes two regions: image and text. The text region is measured by the NodeFont property and the Text property, just like the code below: Size s = TextRenderer.MeasureText(this.Text, this.NodeFont);
The OnNodeMouseHover event would use the bounds to decide if the mouse is on the TreeNode or not, so we need to set the NodeFont and Text properties properly.
This is the code snippet which contains the properties and methods those need to be modified: Group Class: private void InitializeGroup(string id, Image expandedImage, Image collapsedImage)
{
this.id = id;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
this.expandedImage = expandedImage;
this.collapsedImage = collapsedImage;
this.SetNewgroupInfo();
this.SetOldgroupInfo();
}
public string ID
{
get
{
return id;
}
set
{
OnIdChanging(this.GetGroupEventArguments());
if (value != id)
{
id = value;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
SetNewgroupInfo();
OnIdChanged(this.GetGroupEventArguments());
SetOldgroupInfo();
}
}
}
User class: private void InitializeUser(string id, string status, string statusText, string statusLink, System.Drawing.Color idColor, Image statusIcon)
{
this.id = id;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
this.idColor = idColor;
this.status = status;
this.statusText = statusText;
this.statusLink = statusLink;
this.group = this.Parent == null ? null : (TreeViewDemo.Group)this.Parent;
this.statusImage = statusIcon;
this.SetNewuserInfo();
this.SetOlduserInfo();
}
public string ID
{
get
{
return id;
}
set
{
OnIdChanging(this.GetUserEventArguments());
if (value != id)
{
id = value;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
SetNewuserInfo();
OnIDChanged(this.GetUserEventArguments());
SetOlduserInfo();
}
}
}
Let me know if this does not help or I did not explain clearly. Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. - Marked As Answer byfor loop Tuesday, September 15, 2009 6:04 AM
-
| | Aland Li Monday, September 14, 2009 3:27 AM | plz help me.... | | for loop Friday, September 04, 2009 9:09 PM | Hi for loop,
Based on your description, do you mean the OnNodeMouseHover event is not fired or the code in that method does not work fine? Could you please provide a code snippet?
Regards, Aland Li Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. | | Aland Li Monday, September 07, 2009 8:16 AM | Hi Aland Li thx for reply the code does not even load within the method
protected override void OnNodeMouseHover(TreeNodeMouseHoverEventArgs e)
{
base.OnNodeMouseHover(e);
if (e.Node is Group)
System.Windows.Forms.MessageBox.Show(e.Node.Text);
else
System.Windows.Forms.MessageBox.Show(e.Node.Text);
}
| | for loop Monday, September 07, 2009 3:08 PM | Hi for loop,
Thanks for your reply. I have tested the code snippet below and it works fine. Could you please provide the complete code snippet to help us reproduce the issue? Thanks.
public partial class TreeViewOwnerDraw : Form
{
private TreeView myTreeView;
// Create a Font object for the node tags.
Font tagFont = new Font("Helvetica", 8, FontStyle.Bold);
public TreeViewOwnerDraw()
{
// Create and initialize the TreeView control.
myTreeView = new TreeView();
myTreeView.Dock = DockStyle.Fill;
myTreeView.BackColor = Color.Tan;
myTreeView.CheckBoxes = true;
// Add nodes to the TreeView control.
TreeNode node;
for (int x = 1; x < 4; ++x)
{
// Add a root node to the TreeView control.
node = myTreeView.Nodes.Add(String.Format("Task {0}", x));
for (int y = 1; y < 4; ++y)
{
// Add a child node to the root node.
node.Nodes.Add(String.Format("Subtask {0}", y));
}
}
myTreeView.ExpandAll();
// Add tags containing alert messages to a few nodes
// and set the node background color to highlight them.
myTreeView.Nodes[1].Nodes[0].Tag = "urgent!";
myTreeView.Nodes[1].Nodes[0].BackColor = Color.Yellow;
myTreeView.SelectedNode = myTreeView.Nodes[1].Nodes[0];
myTreeView.Nodes[2].Nodes[1].Tag = "urgent!";
myTreeView.Nodes[2].Nodes[1].BackColor = Color.Yellow;
// Configure the TreeView control for owner-draw and add
// a handler for the DrawNode event.
myTreeView.DrawMode = TreeViewDrawMode.OwnerDrawText;
myTreeView.DrawNode +=
new DrawTreeNodeEventHandler(myTreeView_DrawNode);
// Add a handler for the MouseDown event so that a node can be
// selected by clicking the tag text as well as the node text.
myTreeView.MouseDown += new MouseEventHandler(myTreeView_MouseDown);
myTreeView.NodeMouseHover += new TreeNodeMouseHoverEventHandler(myTreeView_NodeMouseHover);
// Initialize the form and add the TreeView control to it.
this.ClientSize = new Size(292, 273);
this.Controls.Add(myTreeView);
}
void myTreeView_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
{
Console.WriteLine(e.Node.Text);
}
// Clean up any resources being used.
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
tagFont.Dispose();
}
base.Dispose(disposing);
}
// Draws a node.
private void myTreeView_DrawNode(
object sender, DrawTreeNodeEventArgs e)
{
// Draw the background and node text for a selected node.
if ((e.State & TreeNodeStates.Selected) != 0)
{
// Draw the background of the selected node. The NodeBounds
// method makes the highlight rectangle large enough to
// include the text of a node tag, if one is present.
e.Graphics.FillRectangle(Brushes.Green, NodeBounds(e.Node));
// Retrieve the node font. If the node font has not been set,
// use the TreeView font.
Font nodeFont = e.Node.NodeFont;
if (nodeFont == null) nodeFont = ((TreeView)sender).Font;
// Draw the node text.
e.Graphics.DrawString(e.Node.Text, nodeFont, Brushes.White,
Rectangle.Inflate(e.Bounds, 2, 0));
}
// Use the default background and node text.
else
{
e.DrawDefault = true;
}
// If a node tag is present, draw its string representation
// to the right of the label text.
if (e.Node.Tag != null)
{
e.Graphics.DrawString(e.Node.Tag.ToString(), tagFont,
Brushes.Yellow, e.Bounds.Right + 2, e.Bounds.Top);
}
// If the node has focus, draw the focus rectangle large, making
// it large enough to include the text of the node tag, if present.
if ((e.State & TreeNodeStates.Focused) != 0)
{
using (Pen focusPen = new Pen(Color.Black))
{
focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
Rectangle focusBounds = NodeBounds(e.Node);
focusBounds.Size = new Size(focusBounds.Width - 1,
focusBounds.Height - 1);
e.Graphics.DrawRectangle(focusPen, focusBounds);
}
}
}
// Selects a node that is clicked on its label or tag text.
private void myTreeView_MouseDown(object sender, MouseEventArgs e)
{
TreeNode clickedNode = myTreeView.GetNodeAt(e.X, e.Y);
if (NodeBounds(clickedNode).Contains(e.X, e.Y))
{
myTreeView.SelectedNode = clickedNode;
}
}
// Returns the bounds of the specified node, including the region
// occupied by the node label and any node tag displayed.
private Rectangle NodeBounds(TreeNode node)
{
// Set the return value to the normal node bounds.
Rectangle bounds = node.Bounds;
if (node.Tag != null)
{
// Retrieve a Graphics object from the TreeView handle
// and use it to calculate the display width of the tag.
Graphics g = myTreeView.CreateGraphics();
int tagWidth = (int)g.MeasureString
(node.Tag.ToString(), tagFont).Width + 6;
// Adjust the node bounds using the calculated value.
bounds.Offset(tagWidth / 2, 0);
bounds = Rectangle.Inflate(bounds, tagWidth / 2, 0);
g.Dispose();
}
return bounds;
}
}
Regards, Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. | | Aland Li Tuesday, September 08, 2009 2:24 AM | Hi for loop,
Thanks for your reply. Could you provide the code snippet about these classes: Group, User and this method: DrawUser.
Regards, Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. | | Aland Li Thursday, September 10, 2009 8:32 AM | Hi for loop, Thanks for your reply. I add the code to my project, but there are still some types which cannot be found. Could you package the code to a small project and email to me? This is my email: alala666888@hotmail.com. Regards, Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. | | Aland Li Friday, September 11, 2009 2:37 AM | Hi for loop,
I have tested the code you provided and found out the main issue is that the Text property of the TreeNode is not set. In your code snippet, the text drawn on the node is the id, so we need to set the text of the node to its id. We need to make sure the NodeFont property of the TreeNode to be the font we used to draw the text and the Text property to be the text drawn on the node. This is because when we handle some events the argument of which contains the bounds of the TreeNode, itwould measure the bounds before the events are fired. The bounds includes two regions: image and text. The text region is measured by the NodeFont property and the Text property, just like the code below: Size s = TextRenderer.MeasureText(this.Text, this.NodeFont);
The OnNodeMouseHover event would use the bounds to decide if the mouse is on the TreeNode or not, so we need to set the NodeFont and Text properties properly.
This is the code snippet which contains the properties and methods those need to be modified: Group Class: private void InitializeGroup(string id, Image expandedImage, Image collapsedImage)
{
this.id = id;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
this.expandedImage = expandedImage;
this.collapsedImage = collapsedImage;
this.SetNewgroupInfo();
this.SetOldgroupInfo();
}
public string ID
{
get
{
return id;
}
set
{
OnIdChanging(this.GetGroupEventArguments());
if (value != id)
{
id = value;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
SetNewgroupInfo();
OnIdChanged(this.GetGroupEventArguments());
SetOldgroupInfo();
}
}
}
User class: private void InitializeUser(string id, string status, string statusText, string statusLink, System.Drawing.Color idColor, Image statusIcon)
{
this.id = id;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
this.idColor = idColor;
this.status = status;
this.statusText = statusText;
this.statusLink = statusLink;
this.group = this.Parent == null ? null : (TreeViewDemo.Group)this.Parent;
this.statusImage = statusIcon;
this.SetNewuserInfo();
this.SetOlduserInfo();
}
public string ID
{
get
{
return id;
}
set
{
OnIdChanging(this.GetUserEventArguments());
if (value != id)
{
id = value;
//begin: set the text. This can make the tree node be able to decide its region(bounds)
this.Text = id;
//end.
SetNewuserInfo();
OnIDChanged(this.GetUserEventArguments());
SetOlduserInfo();
}
}
}
Let me know if this does not help or I did not explain clearly. Aland Li
Please mark the replies as answers if they help and unmark if they don't. This can be beneficial to other community members reading the thread. - Marked As Answer byfor loop Tuesday, September 15, 2009 6:04 AM
-
| | Aland Li Monday, September 14, 2009 3:27 AM | WOW thx Aland Li
worked nice :) | | for loop Tuesday, September 15, 2009 5:57 AM |
|