(九)c#Winform自定义控件-树
程序员文章站
2022-05-29 10:27:06
前提 入行已经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太难看了,想换一种好看点的风格
效果:
调用示例
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); }
最后的话
如果你喜欢的话,请到 点个星 星吧