How to change my treeView icons insted of +,- like a windows explorer treeview in c#.net win forms

12.8k Views Asked by At

How can I change the expand/collapse images from the plus ( + ) and minus ( - ) images that appear when ShowPlusMinus and/or ShowRootLines are true.

To help visualize, I would like to make the following TreeView treeview plus/minus +/-

Look like this (like Windows explorer)

treeview arrows

3

There are 3 best solutions below

1
On

When you want to customize your treeview control, Microsoft provides a property named "TreeViewDrawMode" on the treeview control, it's value is a enum which has 3 values:Normal, OwnerDrawText, OwnerDrawAll, in your situation, you must use OwnerDrawAll. after you set that property as OwnerDrawAll, when the treeview's nodes are showing, a event named "DrawNode" will be triggered, so you can process your drawing there. when you draw it by yourself, usually you need to draw 3 things: expand/collapse icon, node icon, node text. my sample is below: //define the icon file path string minusPath = Application.StartupPath + Path.DirectorySeparatorChar + "minus.png"; string plusPath = Application.StartupPath + Path.DirectorySeparatorChar + "plus.png"; string nodePath = Application.StartupPath + Path.DirectorySeparatorChar + "directory.png";

    public FrmTreeView()
    {
        InitializeComponent();
        //setting to customer draw
        this.treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll;
        this.treeView1.DrawNode += new DrawTreeNodeEventHandler(treeView1_DrawNode);
    }

    void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e)
    {
        Rectangle nodeRect = e.Node.Bounds;
        /*--------- 1. draw expand/collapse icon ---------*/
        Point ptExpand = new Point(nodeRect.Location.X - 20, nodeRect.Location.Y + 2);
        Image expandImg = null;
        if (e.Node.IsExpanded || e.Node.Nodes.Count < 1)
            expandImg = Image.FromFile(minusPath);
        else
            expandImg = Image.FromFile(plusPath);
        Graphics g = Graphics.FromImage(expandImg);
        IntPtr imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(expandImg, ptExpand);

        /*--------- 2. draw node icon ---------*/
        Point ptNodeIcon = new Point(nodeRect.Location.X - 4, nodeRect.Location.Y + 2);
        Image nodeImg = Image.FromFile(nodePath);
        g = Graphics.FromImage(nodeImg);
        imgPtr = g.GetHdc();
        g.ReleaseHdc();
        e.Graphics.DrawImage(nodeImg, ptNodeIcon);
        /*--------- 3. draw node text ---------*/
        Font nodeFont = e.Node.NodeFont;
        if (nodeFont == null)
            nodeFont = ((TreeView)sender).Font;
        Brush textBrush = SystemBrushes.WindowText;
        //to highlight the text when selected
        if ((e.State & TreeNodeStates.Focused) != 0)
            textBrush = SystemBrushes.HotTrack;
        //Inflate to not be cut
        Rectangle textRect = nodeRect;
        //need to extend node rect
        textRect.Width += 40;
        e.Graphics.DrawString(e.Node.Text, nodeFont, textBrush, Rectangle.Inflate(textRect, -12, 0));
     }

the result of my test is like this: picture of result

3
On

Expanding on Ivan Ičin's solution :

[DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);

public static void SetTreeViewTheme(IntPtr treeHandle) {
     SetWindowTheme(treeHandle, "explorer", null);
}

To use, add a TreeView to your form, and in Form_Load :

SetTreeViewTheme( treeView1.Handle );

Alternatively, you can extend the TreeView object

public class MyTreeView : TreeView
{

    [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
    private static extern int SetWindowTheme(IntPtr hwnd, string pszSubAppName, string pszSubIdList);

    public MyTreeView() {
        SetWindowTheme(this.Handle, "explorer", null);
    }
}

before and after treeview Depicts what it looks like before and after calling SetWindowTheme

0
On

There are 3 methods I can think of:

  1. Sunny already mentioned using SetWindowTheme(TreeView.Handle, "explorer", null)

  2. Using WPF if that is the option and adding TreeViewItem object

  3. Overriding OnPaint methods, which is too complicated, considering you can do just 1, so 1 or 2 it is up to you to chose.