效果圖:
1 using System; 2 using System.ComponentModel; 3 using System.Drawing; 4 using System.Drawing.Drawing2D; 5 using System.Windows.Forms; 6 7 namespace LeaderMap.Resource 8 { 9 /// <summary> 10 /// 基於樹視圖的任務控件 11 /// </summary> 12 public class CTreeTaskBox : TreeView 13 { 14 #region //construckor 15 /// <summary> 16 /// 17 /// </summary> 18 public CTreeTaskBox() 19 { 20 FullRowSelect = true; 21 ShowLines = true; 22 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 23 this.DrawMode = TreeViewDrawMode.OwnerDrawAll; 24 this.ItemHeight = 30; 25 this.ShowLines = true; 26 } 27 #endregion 28 #region //field & property 29 /// <summary> 30 /// 展開按扭的大小 31 /// </summary> 32 private Size ExpandButtonSize = new Size(16, 16); 33 private Color _ExpandButtonColor = Color.FromArgb(255, 255, 255); 34 /// <summary> 35 /// 展開按扭顏色 36 /// </summary> 37 [Description("展開按扭顏色"), Category("XOProperty")] 38 public Color ExpandButtonColor 39 { 40 get 41 { 42 return _ExpandButtonColor; 43 } 44 set 45 { 46 if (_ExpandButtonColor != value) 47 { 48 _ExpandButtonColor = value; 49 this.Invalidate(); 50 } 51 } 52 } 53 private Color _GroupBgColor = Color.FromArgb(95, 162, 211); 54 /// <summary> 55 /// 分組欄背景色 56 /// </summary> 57 [Description("分組欄背景色"), Category("XOProperty")] 58 public Color GroupBgColor 59 { 60 get 61 { 62 return _GroupBgColor; 63 } 64 set 65 { 66 if (_GroupBgColor != value) 67 { 68 _GroupBgColor = value; 69 this.Invalidate(); 70 71 } 72 } 73 } 74 private Color _GroupTitleColor = Color.FromArgb(0, 0, 0); 75 /// <summary> 76 /// 分組欄標題色 77 /// </summary> 78 [Description("分組欄標題色"), Category("XOProperty")] 79 public Color GroupTitleColor 80 { 81 get 82 { 83 return _GroupTitleColor; 84 } 85 set 86 { 87 if (_GroupTitleColor != value) 88 { 89 _GroupTitleColor = value; 90 this.Invalidate(); 91 } 92 } 93 } 94 private Color _OverForeColor = Color.DeepSkyBlue; 95 /// <summary> 96 /// 鼠標懸停色 97 /// </summary> 98 [Description("鼠標懸停色"), Category("XOProperty")] 99 public Color OverForeColor 100 { 101 get 102 { 103 return _OverForeColor; 104 } 105 set 106 { 107 if (_OverForeColor != value) 108 { 109 _OverForeColor = value; 110 this.Invalidate(); 111 } 112 } 113 } 114 /// <summary> 115 /// 節點高度 116 /// </summary> 117 public new int ItemHeight 118 { 119 get 120 { 121 return base.ItemHeight; 122 } 123 set 124 { 125 if (base.ItemHeight != value && value >= 20) 126 { 127 base.ItemHeight = value; 128 this.Invalidate(); 129 } 130 } 131 } 132 133 #endregion 134 #region //override 135 protected override void OnDrawNode(DrawTreeNodeEventArgs e) 136 { 137 //base.OnDrawNode(e); 138 DrawNodeItem(e); 139 } 140 protected override void WndProc(ref Message m) 141 { 142 143 if (m.Msg == 0x0201)//單擊 144 { 145 int wparam = m.LParam.ToInt32(); 146 Point point = new Point( 147 LOWORD(wparam), 148 HIWORD(wparam)); 149 //point = PointToClient(point); 150 TreeNode tn = this.GetNodeAt(point); 151 if (tn == null) 152 { 153 base.WndProc(ref m); 154 return; 155 } 156 if (tn.Level == 0) 157 { 158 if (tn.IsExpanded) 159 { 160 tn.Collapse(); 161 } 162 else 163 { 164 tn.Expand(); 165 } 166 m.Result = IntPtr.Zero; 167 return; 168 } 169 else 170 { 171 base.WndProc(ref m); 172 //tn.IsSelected = true; 173 //this.SelectedNode = tn; 174 } 175 this.SelectedNode = tn; 176 } 177 else if (m.Msg == 0x0203)//雙擊 178 { 179 int wparam = m.LParam.ToInt32(); 180 Point point = new Point( 181 LOWORD(wparam), 182 HIWORD(wparam)); 183 //point = PointToClient(point); 184 TreeNode tn = this.GetNodeAt(point); 185 if (tn == null) 186 { 187 base.WndProc(ref m); 188 return; 189 } 190 if (tn.Level == 0) 191 { 192 m.Result = IntPtr.Zero; 193 return; 194 } 195 else 196 { 197 base.WndProc(ref m); 198 } 199 this.SelectedNode = tn; 200 } 201 else if (m.Msg == 0x0200)//鼠標移動 202 { 203 try 204 { 205 int wparam = m.LParam.ToInt32(); 206 Point point = new Point( 207 LOWORD(wparam), 208 HIWORD(wparam)); 209 //point = PointToClient(point); 210 TreeNode tn = this.GetNodeAt(point); 211 if (tn == null) 212 { 213 // this.SelectedNode = null; 214 base.WndProc(ref m); 215 return; 216 } 217 //this.SelectedNode = tn; 218 } 219 catch { } 220 } 221 else if (m.Msg == 0x02A3)//鼠標移出 WM_MOUSELEAVE = $02A3; 222 { 223 // this.SelectedNode = null; 224 base.WndProc(ref m); 225 return; 226 } 227 else 228 { 229 base.WndProc(ref m); 230 } 231 //WM_LBUTTONDOWN = $0201 232 //WM_LBUTTONDBLCLK = $0203; 233 } 234 #endregion 235 236 #region //private method 237 /// <summary> 238 /// 自定義繪制節點 239 /// </summary> 240 /// <param name="e"></param> 241 private void DrawNodeItem(DrawTreeNodeEventArgs e) 242 { 243 TreeNode tn = e.Node; 244 if (tn.Level == 0) 245 { 246 using (Graphics g = e.Graphics) 247 { 248 //繪制分組的背景 249 RenderBackgroundInternalRate(g, 250 e.Bounds, 251 GroupBgColor, 252 GroupBgColor, 253 Color.FromArgb(200, 255, 255, 255), 254 0.45f, 255 true, 256 300); 257 //繪制展開按扭 258 g.FillEllipse(new SolidBrush(ExpandButtonColor), ExpandButtonBounds(e.Bounds)); 259 g.DrawEllipse(new Pen(Color.LightGray), ExpandButtonBounds(e.Bounds)); 260 Point p1; 261 Point p2; 262 Point p3; 263 if (tn.IsExpanded) 264 { 265 p1 = new Point(ExpandButtonBounds(e.Bounds).X + 3, ExpandButtonBounds(e.Bounds).Bottom - 4); 266 p2 = new Point(ExpandButtonBounds(e.Bounds).X + (ExpandButtonSize.Width) / 2, ExpandButtonBounds(e.Bounds).Top + 5); 267 p3 = new Point(ExpandButtonBounds(e.Bounds).Right - 3, ExpandButtonBounds(e.Bounds).Bottom - 4); 268 } 269 else 270 { 271 p1 = new Point(ExpandButtonBounds(e.Bounds).X + 3, ExpandButtonBounds(e.Bounds).Y + 4); 272 p2 = new Point(ExpandButtonBounds(e.Bounds).X + (ExpandButtonSize.Width) / 2, ExpandButtonBounds(e.Bounds).Bottom - 5); 273 p3 = new Point(ExpandButtonBounds(e.Bounds).Right - 3, ExpandButtonBounds(e.Bounds).Y + 4); 274 } 275 GraphicsPath gp = new GraphicsPath(); 276 gp.AddLine(p1, p2); 277 gp.AddLine(p2, p3); 278 g.DrawPath(new Pen(Color.FromArgb(255, 150, 0, 0), 2f), gp); 279 280 //繪制分組的文本 281 TextRenderer.DrawText(g, e.Node.Text, this.Font, GroupTitleBounds(e.Bounds), this.GroupTitleColor, 282 TextFormatFlags.Left | TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis); 283 } 284 } 285 else if (tn.Level == 1) 286 { 287 //e.DrawDefault = true; 288 289 using (Graphics g = e.Graphics) 290 { 291 if (tn.IsSelected) 292 { 293 TextRenderer.DrawText(g, e.Node.Text, new Font(this.Font.FontFamily.Name, this.Font.Size, FontStyle.Underline), e.Bounds, OverForeColor, 294 TextFormatFlags.Left | TextFormatFlags.VerticalCenter); 295 } 296 else 297 { 298 TextRenderer.DrawText(g, e.Node.Text, this.Font, e.Bounds, this.ForeColor, 299 TextFormatFlags.Left | TextFormatFlags.VerticalCenter); 300 } 301 } 302 } 303 } 304 /// <summary> 305 /// 展開按扭區域 一級菜單后面的展開按鈕 306 /// </summary> 307 /// <param name="childRect"></param> 308 /// <returns></returns> 309 private Rectangle ExpandButtonBounds(Rectangle childRect) 310 { 311 Rectangle lrect = new Rectangle(new Point(childRect.Right - ExpandButtonSize.Width * 3 / 2, (childRect.Height - ExpandButtonSize.Height) / 2 + childRect.Top), ExpandButtonSize); 312 return lrect; 313 } 314 /// <summary> 315 /// 取得分組標題繪制空間 一級菜單 316 /// </summary> 317 /// <param name="childRect"></param> 318 /// <returns></returns> 319 private Rectangle GroupTitleBounds(Rectangle childRect) 320 { 321 Rectangle lrect = childRect; 322 lrect.Width -= ExpandButtonSize.Width * 3 / 2 + 20; 323 lrect.Offset(20, 0); 324 return lrect; 325 } 326 #endregion 327 328 #region //draw 329 internal void RenderBackgroundInternal( 330 Graphics g, 331 Rectangle rect, 332 Color baseColor, 333 Color borderColor, 334 Color innerBorderColor, 335 float basePosition, 336 bool drawBorder, 337 LinearGradientMode mode) 338 { 339 if (drawBorder) 340 { 341 rect.Width--; 342 rect.Height--; 343 } 344 using (LinearGradientBrush brush = new LinearGradientBrush( 345 rect, Color.Transparent, Color.Transparent, mode)) 346 { 347 Color[] colors = new Color[4]; 348 colors[0] = GetColor(baseColor, 0, 35, 24, 9); 349 colors[1] = GetColor(baseColor, 0, 13, 8, 3); 350 colors[2] = baseColor; 351 colors[3] = GetColor(baseColor, 0, 68, 69, 54); 352 ColorBlend blend = new ColorBlend(); 353 blend.Positions = new float[] { 0.0f, basePosition, basePosition + 0.05f, 1.0f }; 354 blend.Colors = colors; 355 brush.InterpolationColors = blend; 356 g.FillRectangle(brush, rect); 357 } 358 if (baseColor.A > 80) 359 { 360 Rectangle rectTop = rect; 361 if (mode == LinearGradientMode.Vertical) 362 { 363 rectTop.Height = (int)(rectTop.Height * basePosition); 364 } 365 else 366 { 367 rectTop.Width = (int)(rect.Width * basePosition); 368 } 369 using (SolidBrush brushAlpha = 370 new SolidBrush(Color.FromArgb(80, 255, 255, 255))) 371 { 372 g.FillRectangle(brushAlpha, rectTop); 373 } 374 } 375 if (drawBorder) 376 { 377 using (Pen pen = new Pen(borderColor)) 378 { 379 g.DrawRectangle(pen, rect); 380 } 381 rect.Inflate(-1, -1); 382 using (Pen pen = new Pen(innerBorderColor)) 383 { 384 g.DrawRectangle(pen, rect); 385 } 386 } 387 } 388 internal void RenderBackgroundInternalRate( 389 Graphics g, 390 Rectangle rect, 391 Color baseColor, 392 Color borderColor, 393 Color innerBorderColor, 394 float basePosition, 395 bool drawBorder, float rate) 396 { 397 if (drawBorder) 398 { 399 rect.Width--; 400 rect.Height--; 401 } 402 using (LinearGradientBrush brush = new LinearGradientBrush( 403 rect, Color.Transparent, Color.Transparent, rate)) 404 { 405 Color[] colors = new Color[4]; 406 colors[0] = GetColor(baseColor, 0, 35, 24, 9); 407 colors[1] = GetColor(baseColor, 0, 13, 8, 3); 408 colors[2] = baseColor; 409 colors[3] = GetColor(baseColor, 0, 68, 69, 54); 410 ColorBlend blend = new ColorBlend(); 411 blend.Positions = new float[] { 0.0f, basePosition, basePosition + 0.05f, 1.0f }; 412 blend.Colors = colors; 413 brush.InterpolationColors = blend; 414 g.FillRectangle(brush, rect); 415 } 416 if (baseColor.A > 80) 417 { 418 Rectangle rectTop = rect; 419 if (true/*mode == LinearGradientMode.Vertical*/) 420 { 421 rectTop.Height = (int)(rectTop.Height * basePosition); 422 } 423 else 424 { 425 rectTop.Width = (int)(rect.Width * basePosition); 426 } 427 using (SolidBrush brushAlpha = 428 new SolidBrush(Color.FromArgb(80, 255, 255, 255))) 429 { 430 g.FillRectangle(brushAlpha, rectTop); 431 } 432 } 433 if (drawBorder) 434 { 435 using (Pen pen = new Pen(borderColor)) 436 { 437 g.DrawRectangle(pen, rect); 438 } 439 rect.Inflate(-1, -1); 440 using (Pen pen = new Pen(innerBorderColor)) 441 { 442 g.DrawRectangle(pen, rect); 443 } 444 } 445 } 446 447 private Color GetColor(Color colorBase, int a, int r, int g, int b) 448 { 449 int a0 = colorBase.A; 450 int r0 = colorBase.R; 451 int g0 = colorBase.G; 452 int b0 = colorBase.B; 453 if (a + a0 > 255) { a = 255; } else { a = a + a0; } 454 if (r + r0 > 255) { r = 255; } else { r = r + r0; } 455 if (g + g0 > 255) { g = 255; } else { g = g + g0; } 456 if (b + b0 > 255) { b = 255; } else { b = b + b0; } 457 return Color.FromArgb(a, r, g, b); 458 } 459 private Color GetColor2(Color colorBase, int a, int r, int g, int b) 460 { 461 int a0 = colorBase.A; 462 int r0 = colorBase.R; 463 int g0 = colorBase.G; 464 int b0 = colorBase.B; 465 if (a + a0 > 255) { a = 255; } else { a = a + a0; } 466 if (r0 - r < 0) { r = 0; } else { r = r0 - r; } 467 if (g0 - g < 0) { g = 0; } else { g = g0 - g; } 468 if (b0 - b < 0) { b = 0; } else { b = b0 - b; } 469 return Color.FromArgb(a, r, g, b); 470 } 471 #endregion 472 public static int LOWORD(int value) 473 { 474 return value & 0xFFFF; 475 } 476 public static int HIWORD(int value) 477 { 478 return value >> 16; 479 } 480 } 481 }
來源:
自定義繪制treeview,重繪treeview - 無名劍(游維3d虛擬現實及游戲開發) - 博客頻道 - CSDN.NET
http://blog.csdn.net/nnsword/article/details/5291949
稍作修改.