none
TreeNode mouseover effect? RRS feed

  • Question

  • I was wondering how to do a treenode mouseover effect for treeviews, like the hottracking one, but with a background instead.

    How would I create this:

    Friday, September 16, 2011 12:09 AM

Answers

  • Hi,

    Try this:

      public class SharxXTreeView : TreeView
        {
            public SharxXTreeView()
                :base()
            {
                this.HotTracking = true;
                this.DrawMode = TreeViewDrawMode.OwnerDrawText;
                this.DrawNode += new DrawTreeNodeEventHandler(SharxXTreeView_DrawNode);
            }
    
            void SharxXTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
            {   
                if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
                {
                    // get node font and node fore color
                    Font nodeFont = GetTreeNodeFont(e.Node);
                    Color nodeForeColor = GetTreeNodeForeColor(e.Node, e.State);
    
                    // fill node background
                    using (SolidBrush brush = new SolidBrush(Color.Red))
                    {
                        e.Graphics.FillRectangle(brush, e.Bounds);
                    }
    
                    // draw node text
                    TextRenderer.DrawText(e.Graphics, e.Node.Text, nodeFont, e.Bounds, nodeForeColor, TextFormatFlags.Left | TextFormatFlags.Top);
    
                    // draw selected node border
                    if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
                    {
                        using (Pen pen = new Pen(nodeForeColor))
                        {
                            pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
                            Rectangle penBounds = e.Bounds;
                            penBounds.Width -= 1;
                            penBounds.Height -= 1;
                            e.Graphics.DrawRectangle(pen, penBounds);
                        }
                    }
                }
                else
                {
                    e.DrawDefault = true;
                }
            }
    
            private Font GetTreeNodeFont(TreeNode node)
            {
                Font nodeFont = node.NodeFont;
                if (nodeFont == null)
                {
                    nodeFont = this.Font;
                }
                return nodeFont;
            }
    
            private Color GetTreeNodeForeColor(TreeNode node, TreeNodeStates nodeState)
            {
                Color nodeForeColor = Color.Empty;
    
                if ((nodeState & TreeNodeStates.Selected) == TreeNodeStates.Selected)
                {
                    nodeForeColor = Color.FromKnownColor(KnownColor.HighlightText);
                }
                else
                {
                    nodeForeColor = node.ForeColor;
                    if (nodeForeColor == Color.Empty)
                    {
                        nodeForeColor = this.ForeColor;
                    }
                }
    
                return nodeForeColor;
            }
        }
    


    And read this:

    http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.drawnode.aspx

     

    • Marked as answer by Hopkin Tuesday, September 20, 2011 1:15 AM
    Sunday, September 18, 2011 5:44 AM

All replies

  • http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.hottracking.aspx

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    Friday, September 16, 2011 1:37 AM
    Moderator
  • As far as I know, HotTracking does not allow one to customize it, so I don't think it will work.

    Friday, September 16, 2011 2:25 AM
  • i believe HotTracking is implemented using then native control style. the treeview does nothing particular with NM_CUSTOMDRAW, you can probably override WndProc to change the item's background based on the TreeNodeStates.Hot state when drawing.

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    Friday, September 16, 2011 2:35 AM
    Moderator
  • I'm sorry, but i'm unfamiliar as to how to do this.
    Friday, September 16, 2011 3:32 AM
  • Hi,

    - Set TreeView.HotTracking to true,

    - Set TreeView.DrawMode to OwnerDrawText,

    - Attach TreeView.DrawNode event,

    - Check node state (TreeNodeStates.Hot) and repaint node.

     

    Example:

    using System;
    using System.Collections.Generic;
    using System.Windows.Forms;
    using System.Drawing;
    
    namespace SharxXTreeView
    {
        static class Program
        {
            [STAThread]
            static void Main()
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new SharxXTestForm());
            }
        }
    
        public class SharxXTestForm : Form
        {
            private SharxXTreeView treeView;
    
            public SharxXTestForm()
            {
                InitializeComponent();
            }
    
            private void InitializeComponent()
            {
                this.Size = new Size(200, 400);
    
                treeView = new SharxXTreeView();
                treeView.Dock = DockStyle.Fill;
                treeView.Parent = this;
            }
    
            protected override void OnShown(EventArgs e)
            {
                base.OnShown(e);
    
                for (int i = 1; i <= 10; i++)
                { 
                    TreeNode treeNode = treeView.Nodes.Add(string.Format("Test {0}", i));
                    
                    for (int j = 1; j <= 5; j++)
                    { 
                        treeNode.Nodes.Add(string.Format("Test {0}-{1}", i, j));
                    }
                }
            }
        }
    
        public class SharxXTreeView : TreeView
        {
            public SharxXTreeView()
                :base()
            {
                this.HotTracking = true;
                this.DrawMode = TreeViewDrawMode.OwnerDrawText;
                this.DrawNode += new DrawTreeNodeEventHandler(SharxXTreeView_DrawNode);
            }
    
            void SharxXTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
            {
                if (e.State == TreeNodeStates.Hot)
                {
                    using (SolidBrush brush = new SolidBrush(Color.Red))
                    {
                        e.Graphics.FillRectangle(brush, e.Node.Bounds);
                    }
                    TextRenderer.DrawText(e.Graphics, e.Node.Text, this.Font, e.Node.Bounds, e.Node.ForeColor);
                }
                else
                {
                    e.DrawDefault = true;
                }
            }   
        }
    
    


     

    • Marked as answer by Hopkin Saturday, September 17, 2011 11:42 PM
    • Unmarked as answer by Hopkin Saturday, September 17, 2011 11:48 PM
    Saturday, September 17, 2011 8:35 AM
  • It's almost exactly what I was looking for, however the node text becomes misaligned when the effect is active?

    The expand node button is in the same position, but the text appears to "bulge" out.

    Is there a way to fix this?

    Saturday, September 17, 2011 11:50 PM
  • Hi,

    Try this:

      public class SharxXTreeView : TreeView
        {
            public SharxXTreeView()
                :base()
            {
                this.HotTracking = true;
                this.DrawMode = TreeViewDrawMode.OwnerDrawText;
                this.DrawNode += new DrawTreeNodeEventHandler(SharxXTreeView_DrawNode);
            }
    
            void SharxXTreeView_DrawNode(object sender, DrawTreeNodeEventArgs e)
            {   
                if ((e.State & TreeNodeStates.Hot) == TreeNodeStates.Hot)
                {
                    // get node font and node fore color
                    Font nodeFont = GetTreeNodeFont(e.Node);
                    Color nodeForeColor = GetTreeNodeForeColor(e.Node, e.State);
    
                    // fill node background
                    using (SolidBrush brush = new SolidBrush(Color.Red))
                    {
                        e.Graphics.FillRectangle(brush, e.Bounds);
                    }
    
                    // draw node text
                    TextRenderer.DrawText(e.Graphics, e.Node.Text, nodeFont, e.Bounds, nodeForeColor, TextFormatFlags.Left | TextFormatFlags.Top);
    
                    // draw selected node border
                    if ((e.State & TreeNodeStates.Selected) == TreeNodeStates.Selected)
                    {
                        using (Pen pen = new Pen(nodeForeColor))
                        {
                            pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
                            Rectangle penBounds = e.Bounds;
                            penBounds.Width -= 1;
                            penBounds.Height -= 1;
                            e.Graphics.DrawRectangle(pen, penBounds);
                        }
                    }
                }
                else
                {
                    e.DrawDefault = true;
                }
            }
    
            private Font GetTreeNodeFont(TreeNode node)
            {
                Font nodeFont = node.NodeFont;
                if (nodeFont == null)
                {
                    nodeFont = this.Font;
                }
                return nodeFont;
            }
    
            private Color GetTreeNodeForeColor(TreeNode node, TreeNodeStates nodeState)
            {
                Color nodeForeColor = Color.Empty;
    
                if ((nodeState & TreeNodeStates.Selected) == TreeNodeStates.Selected)
                {
                    nodeForeColor = Color.FromKnownColor(KnownColor.HighlightText);
                }
                else
                {
                    nodeForeColor = node.ForeColor;
                    if (nodeForeColor == Color.Empty)
                    {
                        nodeForeColor = this.ForeColor;
                    }
                }
    
                return nodeForeColor;
            }
        }
    


    And read this:

    http://msdn.microsoft.com/en-us/library/system.windows.forms.treeview.drawnode.aspx

     

    • Marked as answer by Hopkin Tuesday, September 20, 2011 1:15 AM
    Sunday, September 18, 2011 5:44 AM
  • Your solution is perfect I think, Adnan!

    Good codes!

     

    @Hopkin,

    Base on my test, I think the last post from Adnan can solve your requirement, so can we close this thread with mark Adnan's post as the final solution?


    Mike [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, September 19, 2011 8:53 AM
    Moderator
  • This solution has a obvious side effect, the HotTracking can only work on the exact area which means when you mouse over at the same level of the tree node but not over the node text area, the event will not trigger.

    Every answer may help a lot, thanks guys
    Frank

    Thursday, October 29, 2015 11:41 AM