参考链接:https://www.cnblogs.com/xe2011/p/3817402.html
尽可能接近WINDOWS 8的资源管理器效果(这里只模仿它的效果,处理文件功能不包括在内)
- TREEVIEW可以增加空白并且空白处不能单击
- 重绘三角箭头
- 重绘选中时的边框和填充色
- 重绘失去焦点时选中时的边框和填充色
- 重绘光标所在处的节点背景 MOUSE Hover
- 闪烁的问题处理 当TREEVIEW大小改变时闪烁很严重
- 做到自定义控件
- 图片背景
- 光标的在不同位置的相关改变
WINDOWS 8的资源管理器是不显示水平滚动条
相关参考
重画节点的+-号 http://stackoverflow.com/questions/20125131/treeview-change-plus-minus-icon
画节点上的ImageList的图标 http://zhuad627.blog.163.com/blog/static/94780512011618103157479/
画节点文字后面的 TAG http://www.cnblogs.com/scottckt/archive/2007/12/18/1005084.html
http://www.cnblogs.com/xm_cpppp/p/3622434.html
选中的节点颜色
边框颜色 102,167,232
填充颜色 209,232,255
TREEVIEW失去焦点
边框颜色 222,222,222
填充颜色 247,247,247
光标所在的节点的
边框颜色 112,192,231
填充颜色 229,243,251

光标的在不同位置的相关改变
12 TreeViewEx.cs 源码
文件下载:http://files.cnblogs.com/files/xe2011/CSharpExploreTreeView2016-11-23_165057.zip
编译环境是vs2015 文件已经解决了控件闪烁问题
完整的文件的源码:http://www.cnblogs.com/xe2011/p/3859801.html
using System.Drawing;using System.Runtime.InteropServices;namespace System.Windows.Forms{public class API{private const int WS_HSCROLL = 0x100000;private const int WS_VSCROLL = 0x200000;private const int GWL_STYLE = (-16);[DllImport("User32.dll")]public static extern IntPtr LoadCursor(IntPtr hInstance, CursorType cursor);[DllImport("user32.dll")]public static extern int GetWindowLong(IntPtr hwnd, int nIndex);[DllImport("user32.dll")]public static extern bool ShowScrollBar(IntPtr hWnd, int wBar, bool bShow);public const int WM_PRINTCLIENT = 0x0318;public const int PRF_CLIENT = 0x00000004;[DllImport("user32.dll")]public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);/// <summary>/// 显示系统光标小手/// 像Win7非经典主题的小手光标/// </summary>public static Cursor Hand{get{IntPtr h = LoadCursor(IntPtr.Zero, CursorType.IDC_HAND);return new Cursor(h);}}public static bool IsWinXP{get{OperatingSystem OS = Environment.OSVersion;return (OS.Platform == PlatformID.Win32NT) &&((OS.Version.Major > 5) || ((OS.Version.Major == 5) && (OS.Version.Minor == 1)));}}public static bool IsWinVista{get{OperatingSystem OS = Environment.OSVersion;return (OS.Platform == PlatformID.Win32NT) && (OS.Version.Major >= 6);}}/// <summary>/// 判断是否出现垂直滚动条/// </summary>/// <param name="ctrl">待测控件</param>/// <returns>出现垂直滚动条返回true,否则为false</returns>public static bool IsVerticalScrollBarVisible(Control ctrl){if (!ctrl.IsHandleCreated)return false;return (GetWindowLong(ctrl.Handle, GWL_STYLE) & WS_VSCROLL) != 0;}/// <summary>/// 判断是否出现水平滚动条/// </summary>/// <param name="ctrl">待测控件</param>/// <returns>出现水平滚动条返回true,否则为false</returns>public static bool IsHorizontalScrollBarVisible(Control ctrl){if (!ctrl.IsHandleCreated)return false;return (GetWindowLong(ctrl.Handle, GWL_STYLE) & WS_HSCROLL) != 0;}}public enum CursorType : uint{IDC_ARROW = 32512U,IDC_IBEAM = 32513U,IDC_WAIT = 32514U,IDC_CROSS = 32515U,IDC_UPARROW = 32516U,IDC_SIZE = 32640U,IDC_ICON = 32641U,IDC_SIZENWSE = 32642U,IDC_SIZENESW = 32643U,IDC_SIZEWE = 32644U,IDC_SIZENS = 32645U,IDC_SIZEALL = 32646U,IDC_NO = 32648U,//小手IDC_HAND = 32649U,IDC_APPSTARTING = 32650U,IDC_HELP = 32651U}public class TreeViewEx : TreeView{#region 双缓存重绘private const int WM_VSCROLL = 0x0115;private const int WM_HSCROLL = 0x0114;//private const int WM_MOUSEWHEEL = 0x020A;private const int TV_FIRST = 0x1100;private const int TVM_SETBKCOLOR = TV_FIRST + 29;private const int TVM_SETEXTENDEDSTYLE = TV_FIRST + 44;private const int TVS_EX_DOUBLEBUFFER = 0x0004;private void UpdateExtendedStyles(){int Style = 0;if (DoubleBuffered)Style |= TVS_EX_DOUBLEBUFFER;if (Style != 0)API.SendMessage(Handle, TVM_SETEXTENDEDSTYLE, (IntPtr)TVS_EX_DOUBLEBUFFER, (IntPtr)Style);}protected override void OnHandleCreated(EventArgs e){base.OnHandleCreated(e);UpdateExtendedStyles();if (!API.IsWinXP)API.SendMessage(Handle, TVM_SETBKCOLOR, IntPtr.Zero, (IntPtr)ColorTranslator.ToWin32(BackColor));}protected override void OnPaint(PaintEventArgs e){if (GetStyle(ControlStyles.UserPaint)){Message m = new Message();m.HWnd = Handle;m.Msg = API.WM_PRINTCLIENT;m.WParam = e.Graphics.GetHdc();m.LParam = (IntPtr)API.PRF_CLIENT;DefWndProc(ref m);e.Graphics.ReleaseHdc(m.WParam);}base.OnPaint(e);}#endregionpublic TreeViewEx(){treeView1 = this;treeView1.HotTracking = true;treeView1.HideSelection = false;treeView1.SelectedImageIndex = treeView1.ImageIndex;this.treeView1.BackColor = System.Drawing.Color.White;this.treeView1.BorderStyle = System.Windows.Forms.BorderStyle.None;this.treeView1.Font = new System.Drawing.Font("微软雅黑", 9.7F);this.treeView1.FullRowSelect = true;treeView1.DrawMode = TreeViewDrawMode.OwnerDrawAll;//treeView1.Nodes[1].Expand();//treeView1.Nodes[5].Expand();//treeView1.SelectedNode = treeView1.Nodes[1];this.treeView1.DrawNode += new System.Windows.Forms.DrawTreeNodeEventHandler(this.treeView1_DrawNode);this.treeView1.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.treeView1_BeforeSelect);this.treeView1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.treeView1_KeyDown);}#region DrawNodepublic ImageList arrowImageList{get{return arrowImageList1;}set{arrowImageList1 = value;}}/*1节点被选中 ,TreeView有焦点*/private SolidBrush brush1 = new SolidBrush(Color.FromArgb(209, 232, 255));//填充颜色private Pen pen1 = new Pen(Color.FromArgb(102, 167, 232), 1);//边框颜色/*2节点被选中 ,TreeView没有焦点*/private SolidBrush brush2 = new SolidBrush(Color.FromArgb(247, 247, 247));private Pen pen2 = new Pen(Color.FromArgb(222, 222, 222), 1);/*3 MouseMove的时候 画光标所在的节点的背景*/private SolidBrush brush3 = new SolidBrush(Color.FromArgb(229, 243, 251));private Pen pen3 = new Pen(Color.FromArgb(112, 192, 231), 1);private void treeView1_DrawNode(object sender, DrawTreeNodeEventArgs e){#region 1 选中的节点背景=========================================Rectangle nodeRect = new Rectangle(1,e.Bounds.Top,e.Bounds.Width - 3,e.Bounds.Height - 1);if (e.Node.IsSelected){//TreeView有焦点的时候 画选中的节点if (treeView1.Focused){e.Graphics.FillRectangle(brush1, nodeRect);e.Graphics.DrawRectangle(pen1, nodeRect);/*测试 画聚焦的边框*///ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, Color.Black, SystemColors.Highlight);}/*TreeView失去焦点的时候 */else{e.Graphics.FillRectangle(brush2, nodeRect);e.Graphics.DrawRectangle(pen2, nodeRect);}}else if ((e.State & TreeNodeStates.Hot) != 0 && e.Node.Text != "")//|| currentMouseMoveNode == e.Node){e.Graphics.FillRectangle(brush3, nodeRect);e.Graphics.DrawRectangle(pen3, nodeRect);}else{e.Graphics.FillRectangle(Brushes.White, e.Bounds);}#endregion#region 2 +-号绘制=========================================Rectangle plusRect = new Rectangle(e.Node.Bounds.Left - 32, nodeRect.Top + 7, 9, 9); // +-号的大小 是9 * 9if (e.Node.IsExpanded)e.Graphics.DrawImage(arrowImageList.Images[1], plusRect);else if (e.Node.IsExpanded == false && e.Node.Nodes.Count > 0)e.Graphics.DrawImage(arrowImageList.Images[0], plusRect);/*测试用 画出+-号出现的矩形*///if (e.Node.Nodes.Count > 0)// e.Graphics.DrawRectangle(new Pen(Color.Red), plusRect);#endregion#region 3 画节点文本=========================================Rectangle nodeTextRect = new Rectangle(e.Node.Bounds.Left,e.Node.Bounds.Top + 2,e.Node.Bounds.Width + 2,e.Node.Bounds.Height);nodeTextRect.Width += 4;nodeTextRect.Height -= 4;e.Graphics.DrawString(e.Node.Text,e.Node.TreeView.Font,new SolidBrush(Color.Black),nodeTextRect);//画子节点个数 (111)if (e.Node.GetNodeCount(true) > 0){e.Graphics.DrawString(string.Format("({0})", e.Node.GetNodeCount(true)),new Font("Arial", 8),Brushes.Gray,nodeTextRect.Right - 4,nodeTextRect.Top + 2);}///*测试用,画文字出现的矩形*///if (e.Node.Text != "")// e.Graphics.DrawRectangle(new Pen(Color.Blue), nodeTextRect);#endregion#region 4 画IImageList 中的图标===================================================================int currt_X = e.Node.Bounds.X;if (treeView1.ImageList != null && treeView1.ImageList.Images.Count > 0){//图标大小16*16Rectangle imagebox = new Rectangle(e.Node.Bounds.X - 3 - 16,e.Node.Bounds.Y + 3,16,//IMAGELIST IMAGE WIDTH16);//HEIGHTint index = e.Node.ImageIndex;string imagekey = e.Node.ImageKey;if (imagekey != "" && treeView1.ImageList.Images.ContainsKey(imagekey))e.Graphics.DrawImage(treeView1.ImageList.Images[imagekey], imagebox);else{if (e.Node.ImageIndex < 0)index = 0;else if (index > treeView1.ImageList.Images.Count - 1)index = 0;e.Graphics.DrawImage(treeView1.ImageList.Images[index], imagebox);}currt_X -= 19;/*测试 画IMAGELIST的矩形*///if (e.Node.ImageIndex > 0)// e.Graphics.DrawRectangle(new Pen(Color.Black, 1), imagebox);}#endregion///*测试 画所有的边框*///nodeRect = new Rectangle(1,// e.Bounds.Top + 1,// e.Bounds.Width - 3,// e.Bounds.Height - 2);//e.Graphics.DrawRectangle(new Pen(Color.Gray), nodeRect);}#endregionprivate void treeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e){if (e.Node != null){//禁止选中空白项if (e.Node.Text == ""){//响应上下键if (ArrowKeyUp){if (e.Node.PrevNode != null && e.Node.PrevNode.Text != "")treeView1.SelectedNode = e.Node.PrevNode;}if (ArrowKeyDown){if (e.Node.NextNode != null && e.Node.NextNode.Text != "")treeView1.SelectedNode = e.Node.NextNode;}e.Cancel = true;}}}private void treeView1_KeyDown(object sender, KeyEventArgs e){ArrowKeyUp = (e.KeyCode == Keys.Up);if (e.KeyCode == Keys.Down){Text = "Down";}ArrowKeyDown = (e.KeyCode == Keys.Down);if (e.KeyCode == Keys.Up){Text = "UP";}}private bool ArrowKeyUp = false;private bool ArrowKeyDown = false;private System.Windows.Forms.ImageList arrowImageList1;private TreeView treeView1;}}
