欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(九)c#Winform自定义控件-树

程序员文章站 2023-04-04 20:14:49
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492 目录 ......

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

开源地址:

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

目录

准备工作

对原始树控件treeview进行扩展以更改样式

先了解一下我们需要哪些功能,控件ain可以更改整好颜色,行高,选中效果,分割线等

开始

添加组件,命名treeviewex 继承treeview

先看下属性

  1  private const int ws_vscroll = 2097152;
  2 
  3         private const int gwl_style = -16;
  4 
  5         private dictionary<string, string> _lsttips = new dictionary<string, string>();
  6 
  7         private font _tipfont = new font("arial unicode ms", 12f);
  8 
  9         private image _tipimage = resources.tips;
 10 
 11         private bool _isshowtip = false;
 12 
 13         private bool _isshowbycustommodel = true;
 14 
 15         private int _nodeheight = 50;
 16 
 17         private image _nodedownpic = resources.list_add;
 18 
 19         private image _nodeuppic = resources.list_subtract;
 20 
 21         private color _nodebackgroundcolor = color.fromargb(61, 60, 66);
 22 
 23         private color _nodeforecolor = color.white;
 24 
 25         private bool _nodeisshowsplitline = false;
 26 
 27         private color _nodesplitlinecolor = color.fromargb(54, 53, 58);
 28 
 29         private color m_nodeselectedcolor = color.fromargb(255, 121, 74);
 30 
 31         private color m_nodeselectedforecolor = color.white;
 32 
 33         private bool _parentnodecanselect = true;
 34 
 35         private sizef treefontsize = sizef.empty;
 36 
 37         private bool blnhasvbar = false;
 38 
 39         public dictionary<string, string> lsttips
 40         {
 41             get
 42             {
 43                 return this._lsttips;
 44             }
 45             set
 46             {
 47                 this._lsttips = value;
 48             }
 49         }
 50 
 51         [category("自定义属性"), description("角标文字字体")]
 52         public font tipfont
 53         {
 54             get
 55             {
 56                 return this._tipfont;
 57             }
 58             set
 59             {
 60                 this._tipfont = value;
 61             }
 62         }
 63 
 64         [category("自定义属性"), description("是否显示角标")]
 65         public image tipimage
 66         {
 67             get
 68             {
 69                 return this._tipimage;
 70             }
 71             set
 72             {
 73                 this._tipimage = value;
 74             }
 75         }
 76 
 77         [category("自定义属性"), description("是否显示角标")]
 78         public bool isshowtip
 79         {
 80             get
 81             {
 82                 return this._isshowtip;
 83             }
 84             set
 85             {
 86                 this._isshowtip = value;
 87             }
 88         }
 89 
 90         [category("自定义属性"), description("使用自定义模式")]
 91         public bool isshowbycustommodel
 92         {
 93             get
 94             {
 95                 return this._isshowbycustommodel;
 96             }
 97             set
 98             {
 99                 this._isshowbycustommodel = value;
100             }
101         }
102 
103         [category("自定义属性"), description("节点高度(isshowbycustommodel=true时生效)")]
104         public int nodeheight
105         {
106             get
107             {
108                 return this._nodeheight;
109             }
110             set
111             {
112                 this._nodeheight = value;
113                 base.itemheight = value;
114             }
115         }
116 
117         [category("自定义属性"), description("下翻图标(isshowbycustommodel=true时生效)")]
118         public image nodedownpic
119         {
120             get
121             {
122                 return this._nodedownpic;
123             }
124             set
125             {
126                 this._nodedownpic = value;
127             }
128         }
129 
130         [category("自定义属性"), description("上翻图标(isshowbycustommodel=true时生效)")]
131         public image nodeuppic
132         {
133             get
134             {
135                 return this._nodeuppic;
136             }
137             set
138             {
139                 this._nodeuppic = value;
140             }
141         }
142 
143         [category("自定义属性"), description("节点背景颜色(isshowbycustommodel=true时生效)")]
144         public color nodebackgroundcolor
145         {
146             get
147             {
148                 return this._nodebackgroundcolor;
149             }
150             set
151             {
152                 this._nodebackgroundcolor = value;
153             }
154         }
155 
156         [category("自定义属性"), description("节点字体颜色(isshowbycustommodel=true时生效)")]
157         public color nodeforecolor
158         {
159             get
160             {
161                 return this._nodeforecolor;
162             }
163             set
164             {
165                 this._nodeforecolor = value;
166             }
167         }
168 
169         [category("自定义属性"), description("节点是否显示分割线(isshowbycustommodel=true时生效)")]
170         public bool nodeisshowsplitline
171         {
172             get
173             {
174                 return this._nodeisshowsplitline;
175             }
176             set
177             {
178                 this._nodeisshowsplitline = value;
179             }
180         }
181 
182         [category("自定义属性"), description("节点分割线颜色(isshowbycustommodel=true时生效)")]
183         public color nodesplitlinecolor
184         {
185             get
186             {
187                 return this._nodesplitlinecolor;
188             }
189             set
190             {
191                 this._nodesplitlinecolor = value;
192             }
193         }
194 
195         [category("自定义属性"), description("选中节点背景颜色(isshowbycustommodel=true时生效)")]
196         public color nodeselectedcolor
197         {
198             get
199             {
200                 return this.m_nodeselectedcolor;
201             }
202             set
203             {
204                 this.m_nodeselectedcolor = value;
205             }
206         }
207 
208         [category("自定义属性"), description("选中节点字体颜色(isshowbycustommodel=true时生效)")]
209         public color nodeselectedforecolor
210         {
211             get
212             {
213                 return this.m_nodeselectedforecolor;
214             }
215             set
216             {
217                 this.m_nodeselectedforecolor = value;
218             }
219         }
220 
221         [category("自定义属性"), description("父节点是否可选中")]
222         public bool parentnodecanselect
223         {
224             get
225             {
226                 return this._parentnodecanselect;
227             }
228             set
229             {
230                 this._parentnodecanselect = value;
231             }
232         }

样式的更改主要通过节点的重绘,我们使用drawnode事件来完成

  1  base.drawnode += new drawtreenodeeventhandler(this.treeview_drawnode);
  2 
  3 private void treeview_drawnode(object sender, drawtreenodeeventargs e)
  4         {
  5             try
  6             {
  7                 if (e.node == null || !this._isshowbycustommodel || (e.node.bounds.width <= 0 && e.node.bounds.height <= 0 && e.node.bounds.x <= 0 && e.node.bounds.y <= 0))
  8                 {
  9                     e.drawdefault = true;
 10                 }
 11                 else
 12                 {
 13                     if (base.nodes.indexof(e.node) == 0)
 14                     {
 15                         this.blnhasvbar = this.isverticalscrollbarvisible();
 16                     }
 17                     font font = e.node.nodefont;
 18                     if (font == null)
 19                     {
 20                         font = ((treeview)sender).font;
 21                     }
 22                     if (this.treefontsize == sizef.empty)
 23                     {
 24                         this.treefontsize = this.getfontsize(font, e.graphics);
 25                     }
 26                     bool flag = false;
 27                     int num = 0;
 28                     if (base.imagelist != null && base.imagelist.images.count > 0 && e.node.imageindex >= 0 && e.node.imageindex < base.imagelist.images.count)
 29                     {
 30                         flag = true;
 31                         num = (e.bounds.height - base.imagelist.imagesize.height) / 2;
 32                     }
 33                     if ((e.state == treenodestates.selected || e.state == treenodestates.focused || e.state == (treenodestates.focused | treenodestates.selected)) && (this._parentnodecanselect || e.node.nodes.count <= 0))
 34                     {
 35                         e.graphics.fillrectangle(new solidbrush(this.m_nodeselectedcolor), new rectangle(new point(0, e.node.bounds.y), new size(base.width, e.node.bounds.height)));
 36                         e.graphics.drawstring(e.node.text, font, new solidbrush(this.m_nodeselectedforecolor), (float)e.bounds.x, (float)e.bounds.y + ((float)this._nodeheight - this.treefontsize.height) / 2f);
 37                     }
 38                     else
 39                     {
 40                         e.graphics.fillrectangle(new solidbrush(this._nodebackgroundcolor), new rectangle(new point(0, e.node.bounds.y), new size(base.width, e.node.bounds.height)));
 41                         e.graphics.drawstring(e.node.text, font, new solidbrush(this._nodeforecolor), (float)e.bounds.x, (float)e.bounds.y + ((float)this._nodeheight - this.treefontsize.height) / 2f);
 42                     }
 43                     if (flag)
 44                     {
 45                         int num2 = e.bounds.x - num - base.imagelist.imagesize.width;
 46                         if (num2 < 0)
 47                         {
 48                             num2 = 3;
 49                         }
 50                         e.graphics.drawimage(base.imagelist.images[e.node.imageindex], new rectangle(new point(num2, e.bounds.y + num), base.imagelist.imagesize));
 51                     }
 52                     if (this._nodeisshowsplitline)
 53                     {
 54                         e.graphics.drawline(new pen(this._nodesplitlinecolor, 1f), new point(0, e.bounds.y + this._nodeheight - 1), new point(base.width, e.bounds.y + this._nodeheight - 1));
 55                     }
 56                     bool flag2 = false;
 57                     if (e.node.nodes.count > 0)
 58                     {
 59                         if (e.node.isexpanded && this._nodeuppic != null)
 60                         {
 61                             e.graphics.drawimage(this._nodeuppic, new rectangle(base.width - (this.blnhasvbar ? 50 : 30), e.bounds.y + (this._nodeheight - 20) / 2, 20, 20));
 62                         }
 63                         else if (this._nodedownpic != null)
 64                         {
 65                             e.graphics.drawimage(this._nodedownpic, new rectangle(base.width - (this.blnhasvbar ? 50 : 30), e.bounds.y + (this._nodeheight - 20) / 2, 20, 20));
 66                         }
 67                         flag2 = true;
 68                     }
 69                     if (this._isshowtip && this._lsttips.containskey(e.node.name) && !string.isnullorwhitespace(this._lsttips[e.node.name]))
 70                     {
 71                         int num3 = base.width - (this.blnhasvbar ? 50 : 30) - (flag2 ? 20 : 0);
 72                         int num4 = e.bounds.y + (this._nodeheight - 20) / 2;
 73                         e.graphics.drawimage(this._tipimage, new rectangle(num3, num4, 20, 20));
 74                         sizef sizef = e.graphics.measurestring(this._lsttips[e.node.name], this._tipfont, 100, stringformat.generictypographic);
 75                         e.graphics.drawstring(this._lsttips[e.node.name], this._tipfont, new solidbrush(color.white), (float)(num3 + 10) - sizef.width / 2f - 3f, (float)(num4 + 10) - sizef.height / 2f);
 76                     }
 77                 }
 78             }
 79             catch (exception ex)
 80             {
 81                 throw ex;
 82             }
 83         }
 84 
 85         private sizef getfontsize(font font, graphics g = null)
 86         {
 87             sizef result;
 88             try
 89             {
 90                 bool flag = false;
 91                 if (g == null)
 92                 {
 93                     g = base.creategraphics();
 94                     flag = true;
 95                 }
 96                 sizef sizef = g.measurestring("a", font, 100, stringformat.generictypographic);
 97                 if (flag)
 98                 {
 99                     g.dispose();
100                 }
101                 result = sizef;
102             }
103             catch (exception ex)
104             {
105                 throw ex;
106             }
107             return result;
108         }
109 
110         [dllimport("user32", charset = charset.auto)]
111         private static extern int getwindowlong(intptr hwnd, int nindex);
112 
113         private bool isverticalscrollbarvisible()
114         {
115             return base.ishandlecreated && (treeviewex.getwindowlong(base.handle, -16) & 2097152) != 0;
116         }

我们还需要对选中节点时做一些处理

 1 private void treeviewex_nodemouseclick(object sender, treenodemouseclickeventargs e)
 2         {
 3             try
 4             {
 5                 if (e.node != null)
 6                 {
 7                     if (e.node.nodes.count > 0)
 8                     {
 9                         if (e.node.isexpanded)
10                         {
11                             e.node.collapse();
12                         }
13                         else
14                         {
15                             e.node.expand();
16                         }
17                     }
18                     if (base.selectednode != null)
19                     {
20                         if (base.selectednode == e.node && e.node.isexpanded)
21                         {
22                             if (!this._parentnodecanselect)
23                             {
24                                 if (e.node.nodes.count > 0)
25                                 {
26                                     base.selectednode = e.node.nodes[0];
27                                 }
28                             }
29                         }
30                     }
31                 }
32             }
33             catch (exception ex)
34             {
35                 throw ex;
36             }
37         }

选中后也需要根据属性做相应的操作

 1  private void treeviewex_afterselect(object sender, treevieweventargs e)
 2         {
 3             try
 4             {
 5                 if (e.node != null)
 6                 {
 7                     if (!this._parentnodecanselect)
 8                     {
 9                         if (e.node.nodes.count > 0)
10                         {
11                             e.node.expand();
12                             base.selectednode = e.node.nodes[0];
13                         }
14                     }
15                 }
16             }
17             catch (exception ex)
18             {
19                 throw ex;
20             }
21         }

主要的东西就这些了,我们看下完成的代码吧

  1 // 版权所有  黄正辉  交流群:568015492   qq:623128629
  2 // 文件名称:treeviewex.cs
  3 // 创建日期:2019-08-15 16:00:55
  4 // 功能描述:treeview
  5 // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
  6 
  7 using system;
  8 using system.collections.generic;
  9 using system.componentmodel;
 10 using system.diagnostics;
 11 using system.drawing;
 12 using system.linq;
 13 using system.runtime.interopservices;
 14 using system.text;
 15 using system.windows.forms;
 16 using hzh_controls.properties;
 17 
 18 namespace hzh_controls.controls
 19 {
 20     public partial class treeviewex : treeview
 21     {
 22 
 23         private const int ws_vscroll = 2097152;
 24 
 25         private const int gwl_style = -16;
 26 
 27         private dictionary<string, string> _lsttips = new dictionary<string, string>();
 28 
 29         private font _tipfont = new font("arial unicode ms", 12f);
 30 
 31         private image _tipimage = resources.tips;
 32 
 33         private bool _isshowtip = false;
 34 
 35         private bool _isshowbycustommodel = true;
 36 
 37         private int _nodeheight = 50;
 38 
 39         private image _nodedownpic = resources.list_add;
 40 
 41         private image _nodeuppic = resources.list_subtract;
 42 
 43         private color _nodebackgroundcolor = color.fromargb(61, 60, 66);
 44 
 45         private color _nodeforecolor = color.white;
 46 
 47         private bool _nodeisshowsplitline = false;
 48 
 49         private color _nodesplitlinecolor = color.fromargb(54, 53, 58);
 50 
 51         private color m_nodeselectedcolor = color.fromargb(255, 121, 74);
 52 
 53         private color m_nodeselectedforecolor = color.white;
 54 
 55         private bool _parentnodecanselect = true;
 56 
 57         private sizef treefontsize = sizef.empty;
 58 
 59         private bool blnhasvbar = false;
 60 
 61         public dictionary<string, string> lsttips
 62         {
 63             get
 64             {
 65                 return this._lsttips;
 66             }
 67             set
 68             {
 69                 this._lsttips = value;
 70             }
 71         }
 72 
 73         [category("自定义属性"), description("角标文字字体")]
 74         public font tipfont
 75         {
 76             get
 77             {
 78                 return this._tipfont;
 79             }
 80             set
 81             {
 82                 this._tipfont = value;
 83             }
 84         }
 85 
 86         [category("自定义属性"), description("是否显示角标")]
 87         public image tipimage
 88         {
 89             get
 90             {
 91                 return this._tipimage;
 92             }
 93             set
 94             {
 95                 this._tipimage = value;
 96             }
 97         }
 98 
 99         [category("自定义属性"), description("是否显示角标")]
100         public bool isshowtip
101         {
102             get
103             {
104                 return this._isshowtip;
105             }
106             set
107             {
108                 this._isshowtip = value;
109             }
110         }
111 
112         [category("自定义属性"), description("使用自定义模式")]
113         public bool isshowbycustommodel
114         {
115             get
116             {
117                 return this._isshowbycustommodel;
118             }
119             set
120             {
121                 this._isshowbycustommodel = value;
122             }
123         }
124 
125         [category("自定义属性"), description("节点高度(isshowbycustommodel=true时生效)")]
126         public int nodeheight
127         {
128             get
129             {
130                 return this._nodeheight;
131             }
132             set
133             {
134                 this._nodeheight = value;
135                 base.itemheight = value;
136             }
137         }
138 
139         [category("自定义属性"), description("下翻图标(isshowbycustommodel=true时生效)")]
140         public image nodedownpic
141         {
142             get
143             {
144                 return this._nodedownpic;
145             }
146             set
147             {
148                 this._nodedownpic = value;
149             }
150         }
151 
152         [category("自定义属性"), description("上翻图标(isshowbycustommodel=true时生效)")]
153         public image nodeuppic
154         {
155             get
156             {
157                 return this._nodeuppic;
158             }
159             set
160             {
161                 this._nodeuppic = value;
162             }
163         }
164 
165         [category("自定义属性"), description("节点背景颜色(isshowbycustommodel=true时生效)")]
166         public color nodebackgroundcolor
167         {
168             get
169             {
170                 return this._nodebackgroundcolor;
171             }
172             set
173             {
174                 this._nodebackgroundcolor = value;
175             }
176         }
177 
178         [category("自定义属性"), description("节点字体颜色(isshowbycustommodel=true时生效)")]
179         public color nodeforecolor
180         {
181             get
182             {
183                 return this._nodeforecolor;
184             }
185             set
186             {
187                 this._nodeforecolor = value;
188             }
189         }
190 
191         [category("自定义属性"), description("节点是否显示分割线(isshowbycustommodel=true时生效)")]
192         public bool nodeisshowsplitline
193         {
194             get
195             {
196                 return this._nodeisshowsplitline;
197             }
198             set
199             {
200                 this._nodeisshowsplitline = value;
201             }
202         }
203 
204         [category("自定义属性"), description("节点分割线颜色(isshowbycustommodel=true时生效)")]
205         public color nodesplitlinecolor
206         {
207             get
208             {
209                 return this._nodesplitlinecolor;
210             }
211             set
212             {
213                 this._nodesplitlinecolor = value;
214             }
215         }
216 
217         [category("自定义属性"), description("选中节点背景颜色(isshowbycustommodel=true时生效)")]
218         public color nodeselectedcolor
219         {
220             get
221             {
222                 return this.m_nodeselectedcolor;
223             }
224             set
225             {
226                 this.m_nodeselectedcolor = value;
227             }
228         }
229 
230         [category("自定义属性"), description("选中节点字体颜色(isshowbycustommodel=true时生效)")]
231         public color nodeselectedforecolor
232         {
233             get
234             {
235                 return this.m_nodeselectedforecolor;
236             }
237             set
238             {
239                 this.m_nodeselectedforecolor = value;
240             }
241         }
242 
243         [category("自定义属性"), description("父节点是否可选中")]
244         public bool parentnodecanselect
245         {
246             get
247             {
248                 return this._parentnodecanselect;
249             }
250             set
251             {
252                 this._parentnodecanselect = value;
253             }
254         }
255         public treeviewex()
256         {
257             base.hideselection = false;
258             base.drawmode = treeviewdrawmode.ownerdrawall;
259             base.drawnode += new drawtreenodeeventhandler(this.treeview_drawnode);
260             base.nodemouseclick += new treenodemouseclickeventhandler(this.treeviewex_nodemouseclick);
261             base.sizechanged += new eventhandler(this.treeviewex_sizechanged);
262             base.afterselect += new treevieweventhandler(this.treeviewex_afterselect);
263             base.fullrowselect = true;
264             base.showlines = false;
265             base.showplusminus = false;
266             base.showrootlines = false;
267             this.backcolor = color.fromargb(61, 60, 66);
268             doublebuffered = true;
269         }
270         protected override void wndproc(ref message m)
271         {
272 
273             if (m.msg == 0x0014) // 禁掉清除背景消息wm_erasebkgnd
274 
275                 return;
276 
277             base.wndproc(ref m);
278 
279         }
280         private void treeviewex_afterselect(object sender, treevieweventargs e)
281         {
282             try
283             {
284                 if (e.node != null)
285                 {
286                     if (!this._parentnodecanselect)
287                     {
288                         if (e.node.nodes.count > 0)
289                         {
290                             e.node.expand();
291                             base.selectednode = e.node.nodes[0];
292                         }
293                     }
294                 }
295             }
296             catch (exception ex)
297             {
298                 throw ex;
299             }
300         }
301 
302         private void treeviewex_sizechanged(object sender, eventargs e)
303         {
304             this.refresh();
305         }
306 
307         private void treeviewex_nodemouseclick(object sender, treenodemouseclickeventargs e)
308         {
309             try
310             {
311                 if (e.node != null)
312                 {
313                     if (e.node.nodes.count > 0)
314                     {
315                         if (e.node.isexpanded)
316                         {
317                             e.node.collapse();
318                         }
319                         else
320                         {
321                             e.node.expand();
322                         }
323                     }
324                     if (base.selectednode != null)
325                     {
326                         if (base.selectednode == e.node && e.node.isexpanded)
327                         {
328                             if (!this._parentnodecanselect)
329                             {
330                                 if (e.node.nodes.count > 0)
331                                 {
332                                     base.selectednode = e.node.nodes[0];
333                                 }
334                             }
335                         }
336                     }
337                 }
338             }
339             catch (exception ex)
340             {
341                 throw ex;
342             }
343         }
344 
345         private void treeview_drawnode(object sender, drawtreenodeeventargs e)
346         {
347             try
348             {
349                 if (e.node == null || !this._isshowbycustommodel || (e.node.bounds.width <= 0 && e.node.bounds.height <= 0 && e.node.bounds.x <= 0 && e.node.bounds.y <= 0))
350                 {
351                     e.drawdefault = true;
352                 }
353                 else
354                 {
355                     if (base.nodes.indexof(e.node) == 0)
356                     {
357                         this.blnhasvbar = this.isverticalscrollbarvisible();
358                     }
359                     font font = e.node.nodefont;
360                     if (font == null)
361                     {
362                         font = ((treeview)sender).font;
363                     }
364                     if (this.treefontsize == sizef.empty)
365                     {
366                         this.treefontsize = this.getfontsize(font, e.graphics);
367                     }
368                     bool flag = false;
369                     int num = 0;
370                     if (base.imagelist != null && base.imagelist.images.count > 0 && e.node.imageindex >= 0 && e.node.imageindex < base.imagelist.images.count)
371                     {
372                         flag = true;
373                         num = (e.bounds.height - base.imagelist.imagesize.height) / 2;
374                     }
375                     if ((e.state == treenodestates.selected || e.state == treenodestates.focused || e.state == (treenodestates.focused | treenodestates.selected)) && (this._parentnodecanselect || e.node.nodes.count <= 0))
376                     {
377                         e.graphics.fillrectangle(new solidbrush(this.m_nodeselectedcolor), new rectangle(new point(0, e.node.bounds.y), new size(base.width, e.node.bounds.height)));
378                         e.graphics.drawstring(e.node.text, font, new solidbrush(this.m_nodeselectedforecolor), (float)e.bounds.x, (float)e.bounds.y + ((float)this._nodeheight - this.treefontsize.height) / 2f);
379                     }
380                     else
381                     {
382                         e.graphics.fillrectangle(new solidbrush(this._nodebackgroundcolor), new rectangle(new point(0, e.node.bounds.y), new size(base.width, e.node.bounds.height)));
383                         e.graphics.drawstring(e.node.text, font, new solidbrush(this._nodeforecolor), (float)e.bounds.x, (float)e.bounds.y + ((float)this._nodeheight - this.treefontsize.height) / 2f);
384                     }
385                     if (flag)
386                     {
387                         int num2 = e.bounds.x - num - base.imagelist.imagesize.width;
388                         if (num2 < 0)
389                         {
390                             num2 = 3;
391                         }
392                         e.graphics.drawimage(base.imagelist.images[e.node.imageindex], new rectangle(new point(num2, e.bounds.y + num), base.imagelist.imagesize));
393                     }
394                     if (this._nodeisshowsplitline)
395                     {
396                         e.graphics.drawline(new pen(this._nodesplitlinecolor, 1f), new point(0, e.bounds.y + this._nodeheight - 1), new point(base.width, e.bounds.y + this._nodeheight - 1));
397                     }
398                     bool flag2 = false;
399                     if (e.node.nodes.count > 0)
400                     {
401                         if (e.node.isexpanded && this._nodeuppic != null)
402                         {
403                             e.graphics.drawimage(this._nodeuppic, new rectangle(base.width - (this.blnhasvbar ? 50 : 30), e.bounds.y + (this._nodeheight - 20) / 2, 20, 20));
404                         }
405                         else if (this._nodedownpic != null)
406                         {
407                             e.graphics.drawimage(this._nodedownpic, new rectangle(base.width - (this.blnhasvbar ? 50 : 30), e.bounds.y + (this._nodeheight - 20) / 2, 20, 20));
408                         }
409                         flag2 = true;
410                     }
411                     if (this._isshowtip && this._lsttips.containskey(e.node.name) && !string.isnullorwhitespace(this._lsttips[e.node.name]))
412                     {
413                         int num3 = base.width - (this.blnhasvbar ? 50 : 30) - (flag2 ? 20 : 0);
414                         int num4 = e.bounds.y + (this._nodeheight - 20) / 2;
415                         e.graphics.drawimage(this._tipimage, new rectangle(num3, num4, 20, 20));
416                         sizef sizef = e.graphics.measurestring(this._lsttips[e.node.name], this._tipfont, 100, stringformat.generictypographic);
417                         e.graphics.drawstring(this._lsttips[e.node.name], this._tipfont, new solidbrush(color.white), (float)(num3 + 10) - sizef.width / 2f - 3f, (float)(num4 + 10) - sizef.height / 2f);
418                     }
419                 }
420             }
421             catch (exception ex)
422             {
423                 throw ex;
424             }
425         }
426 
427         private sizef getfontsize(font font, graphics g = null)
428         {
429             sizef result;
430             try
431             {
432                 bool flag = false;
433                 if (g == null)
434                 {
435                     g = base.creategraphics();
436                     flag = true;
437                 }
438                 sizef sizef = g.measurestring("a", font, 100, stringformat.generictypographic);
439                 if (flag)
440                 {
441                     g.dispose();
442                 }
443                 result = sizef;
444             }
445             catch (exception ex)
446             {
447                 throw ex;
448             }
449             return result;
450         }
451 
452         [dllimport("user32", charset = charset.auto)]
453         private static extern int getwindowlong(intptr hwnd, int nindex);
454 
455         private bool isverticalscrollbarvisible()
456         {
457             return base.ishandlecreated && (treeviewex.getwindowlong(base.handle, -16) & 2097152) != 0;
458         }
459     }
460 }

用处及效果

用处:觉得原始的treeview太难看了,想换一种好看点的风格

效果:

(九)c#Winform自定义控件-树

调用示例

 for (int i = 0; i < 3; i++)
            {
                treenode tn = new treenode("  父节点" + i);
                for (int j = 0; j < 3; j++)
                {
                    tn.nodes.add("    子节点" + j);
                }
                this.treeviewex1.nodes.add(tn);
            }

 

 

最后的话

如果你喜欢的话,请到  点个星 星吧