问题
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
Look like this (like Windows explorer)
回答1:
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);
}
}
Depicts what it looks like before and after calling SetWindowTheme
回答2:
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:
回答3:
There are 3 methods I can think of:
Sunny already mentioned using
SetWindowTheme(TreeView.Handle, "explorer", null)
Using WPF if that is the option and adding TreeViewItem object
Overriding OnPaint methods, which is too complicated, considering you can do just 1, so 1 or 2 it is up to you to chose.
来源:https://stackoverflow.com/questions/13625420/how-to-change-my-treeview-icons-insted-of-like-a-windows-explorer-treeview-i