C#自定义箭头组件,效果如图:
实现的功能:
1) 箭头方向属性左、右、上、下;
2) 颜色渐变,且颜色任意调整;
3) 箭头大小位置任意调整;
4) 其他。
主要代码如下:
1 using System; 2 using System.Collections; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.Drawing.Drawing2D; 6 using System.Data; 7 using System.Windows.Forms; 8 using System.ComponentModel.Design; 9 10 namespace TestControls 11 { 12 #region enum 13 /// <summary> 14 /// 颜色填充方向 15 /// </summary> 16 public enum LinearGradientDirection 17 { 18 Vertical, 19 Horizontal 20 } 21 22 /// <summary> 23 /// 箭头方向 24 /// </summary> 25 public enum ArrowStyleType 26 { 27 None, 28 Left, 29 Right, 30 Top, 31 Bottom, 32 LeftRight, 33 TopBottom, 34 UpBow, 35 DownBow, 36 LeftBow, 37 RightBow, 38 } 39 #endregion 40 41 public partial class ArrowLine : System.Windows.Forms.Control 42 { 43 #region 变量 44 //private System.ComponentModel.Container components = null; 45 private PointF[] m_pnts = null; // 箭头点坐标 46 GraphicsPath m_gp = new GraphicsPath(); // 绘制路径 47 private Color m_ColorS = Color.WhiteSmoke; // 起始渐变色 48 private Color m_ColorE = Color.DarkGray; 49 private Color m_NormalStartColor = Color.WhiteSmoke; // 常规起始渐变色 50 private Color m_NormalEndColor = Color.DarkGray; 51 private LinearGradientDirection m_lgdirect = LinearGradientDirection.Horizontal; 52 private ArrowStyleType m_ArrowType = ArrowStyleType.None; // 箭头类型 53 private float m_ArrowLength = 8.0f; // 箭标长度 54 private float m_ArrowBodyWidth = 8.0f; // 箭身宽度 55 56 private float m_BowHeight = 4.0f; // 弓长度 57 private float m_BowWidth = 4.0f; // 弓宽度 58 private bool m_antiAlias = false; // 反走样绘制 59 60 private bool m_FrameEnabled = false; 61 private int m_pCount = 8; 62 63 private const int MINSIZE = 2; // 最小大小 64 #endregion 65 66 #region 属性 67 /// <summary> 68 /// 开始渐变颜色 69 /// </summary> 70 public Color NormalStartColor 71 { 72 get { return m_NormalStartColor; } 73 set { m_NormalStartColor = value; Refresh(); } 74 } 75 76 /// <summary> 77 ///结束渐变颜色 78 /// </summary> 79 public Color NormalEndColor 80 { 81 get { return m_NormalEndColor; } 82 set { m_NormalEndColor = value; Refresh(); } 83 } 84 85 /// <summary> 86 /// 渐变色方向 87 /// </summary> 88 public LinearGradientDirection ColorLinearDirection 89 { 90 get { return m_lgdirect; } 91 set { m_lgdirect = value; Refresh(); } 92 } 93 94 95 /// <summary> 96 /// 是否有立体框架 97 /// </summary> 98 public bool FrameEnabled 99 { 100 get { return m_FrameEnabled; } 101 set { m_FrameEnabled = value; Refresh(); } 102 } 103 104 /// <summary> 105 /// 箭头类型 106 /// </summary> 107 public ArrowStyleType ArrowStyle 108 { 109 get { return m_ArrowType; } 110 set 111 { 112 m_ArrowType = value; 113 Clear(); 114 Init(); 115 Refresh(); 116 } 117 } 118 119 /// <summary> 120 /// 箭标长度 121 /// </summary> 122 public float ArrowLength 123 { 124 get { return m_ArrowLength; } 125 set 126 { 127 m_ArrowLength = value; 128 // AdjustmentBodyWH(); 129 Clear(); 130 Init(); 131 Refresh(); 132 } 133 } 134 135 /// <summary> 136 /// 箭身宽度 137 /// </summary> 138 public float ArrowBodyWidth 139 { 140 get { return m_ArrowBodyWidth; } 141 set 142 { 143 m_ArrowBodyWidth = value; 144 //AdjustmentBodyWH(); 145 Clear(); 146 Init(); 147 Refresh(); 148 } 149 } 150 151 /// <summary> 152 /// 弓长度 153 /// </summary> 154 public float BowHeight 155 { 156 get { return m_BowHeight; } 157 set 158 { 159 m_BowHeight = value; 160 Clear(); 161 Init(); 162 Refresh(); 163 } 164 } 165 166 /// <summary> 167 /// 弓宽度 168 /// </summary> 169 public float BowWidth 170 { 171 get { return m_BowWidth; } 172 set 173 { 174 m_BowWidth = value; 175 Clear(); 176 Init(); 177 Refresh(); 178 } 179 } 180 181 /// <summary> 182 /// 反走样 183 /// </summary> 184 public bool AntiAlias 185 { 186 get { return m_antiAlias; } 187 set 188 { 189 m_antiAlias = value; 190 Clear(); 191 Init(); 192 Refresh(); 193 } 194 } 195 196 private bool m_LinearGradientUsingClient = true; //渐变色使用客户区 197 /// <summary> 198 /// 渐变色使用是否只使用控件客户区 199 /// </summary> 200 public bool LinearGradientUsingClient 201 { 202 get { return m_LinearGradientUsingClient; } 203 set 204 { 205 206 m_LinearGradientUsingClient = value; 207 { 208 Clear(); 209 Init(); 210 Refresh(); 211 } 212 } 213 } 214 215 private Rectangle m_LinearGradientRect; 216 /// <summary> 217 /// 渐变色使用区区域范围 218 /// </summary> 219 public Rectangle LinearGradientRect 220 { 221 get { return m_LinearGradientRect; } 222 set 223 { 224 225 m_LinearGradientRect = value; 226 { 227 Clear(); 228 Init(); 229 Refresh(); 230 } 231 } 232 } 233 #endregion 234 235 #region 构造函数 236 public ArrowLine() 237 { 238 InitializeComponent(); 239 Init(); 240 241 SetStyle(ControlStyles.UserPaint, true); 242 SetStyle(ControlStyles.ResizeRedraw, true); 243 SetStyle(ControlStyles.DoubleBuffer, true); 244 SetStyle(ControlStyles.UserPaint, true); 245 SetStyle(ControlStyles.AllPaintingInWmPaint, true); 246 SetStyle(ControlStyles.UserPaint, true); 247 SetStyle(ControlStyles.SupportsTransparentBackColor, true); 248 this.BackColor = Color.Transparent; 249 250 m_LinearGradientRect = this.ClientRectangle; 251 } 252 253 public ArrowLine(IContainer container) 254 { 255 container.Add(this); 256 InitializeComponent(); 257 } 258 #endregion 259 260 #region 继承函数 261 262 /// <summary> 263 /// Resize 264 /// </summary> 265 /// <param name="e"></param> 266 protected override void OnResize(EventArgs e) 267 { 268 Clear(); 269 Init(); 270 Refresh(); 271 } 272 273 /// <summary> 274 /// Paint 275 /// </summary> 276 /// <param name="e"></param> 277 protected override void OnPaint(PaintEventArgs e) 278 { 279 m_ColorS = NormalStartColor; 280 m_ColorE = NormalEndColor; 281 282 Rectangle rect = this.ClientRectangle; 283 if (m_LinearGradientUsingClient) 284 { 285 rect = this.ClientRectangle; 286 } 287 else 288 { 289 rect = this.RectangleToClient(m_LinearGradientRect); 290 } 291 292 293 LinearGradientBrush b = null; 294 if (ColorLinearDirection == LinearGradientDirection.Horizontal) 295 { 296 b = new LinearGradientBrush(rect, m_ColorS, m_ColorE, 0, false); 297 } 298 else 299 { 300 b = new LinearGradientBrush(rect, m_ColorS, m_ColorE, 90, false); 301 } 302 303 // 设计模式 304 if (this.DesignMode != true) 305 { 306 e.Graphics.SetClip(m_gp); 307 } 308 309 //反走样 310 if (m_antiAlias) 311 { 312 e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 313 } 314 else 315 { 316 e.Graphics.SmoothingMode = SmoothingMode.None; 317 } 318 319 e.Graphics.FillPath(b, m_gp); //填充路径 320 b.Dispose(); 321 322 //划框 323 if (m_FrameEnabled) 324 { 325 ColorArrowFrame(e); 326 } 327 } 328 329 #endregion 330 331 #region 方法 332 333 private void Clear() 334 { 335 m_pnts = null; 336 m_gp.Reset(); 337 } 338 339 private void ColorArrowFrame(PaintEventArgs e) 340 { 341 Pen p1 = null; 342 { 343 if (this.Width < this.Height) 344 { 345 for (int i = 0; i < m_pCount - 1; i++) 346 { 347 if (m_pnts[i].Y <= m_pnts[i + 1].Y) 348 { 349 p1 = new Pen(SystemColors.ControlLightLight, 1f); 350 } 351 else 352 { 353 p1 = new Pen(SystemColors.ControlDark, 1f); 354 } 355 e.Graphics.DrawLine(p1, m_pnts[i].X, m_pnts[i].Y, m_pnts[i + 1].X, m_pnts[i + 1].Y); 356 } 357 } 358 else 359 { 360 for (int i = 0; i < m_pCount - 1; i++) 361 { 362 if (m_pnts[i].Y > m_pnts[i + 1].Y) 363 { 364 p1 = new Pen(SystemColors.ControlLightLight, 1f); 365 } 366 else 367 { 368 p1 = new Pen(SystemColors.ControlDark, 1f); 369 } 370 e.Graphics.DrawLine(p1, m_pnts[i].X, m_pnts[i].Y, m_pnts[i + 1].X, m_pnts[i + 1].Y); 371 } 372 } 373 } 374 375 } 376 377 /// <summary> 378 /// Sequence to create the button 379 /// </summary> 380 private void Init() 381 { 382 MakeSquare(); 383 384 float dx = this.Width - 2; 385 float dy = this.Height - 2; 386 387 if (m_FrameEnabled == false) 388 { 389 dx = this.Width; 390 dy = this.Height; 391 } 392 393 // 产生箭头坐标 394 BuildInitialArrow(); 395 396 // 绘制 397 GraphicsPathFromPoints(m_pnts, m_gp); 398 399 } 400 401 private void MakeSquare() 402 { 403 this.SuspendLayout(); 404 if (this.Width < MINSIZE) 405 { 406 this.Size = new Size(MINSIZE, MINSIZE); 407 } 408 else 409 { 410 //if ( this.Size.Width < this.Size.Height ) 411 //{ 412 // this.Size = new Size ( this.Size.Width, this.Size.Width ); 413 //} 414 //else 415 //{ 416 // this.Size = new Size ( this.Size.Height, this.Size.Height ); 417 //} 418 } 419 this.ResumeLayout(); 420 } 421 422 /// <summary> 423 /// 创建箭头点 424 /// </summary> 425 private void BuildInitialArrow() 426 { 427 // AdjustmentBodyWH(); 428 429 float dx = this.Width - 2; 430 float dy = this.Height - 2; 431 432 if (m_FrameEnabled == false) 433 { 434 dx = this.Width; 435 dy = this.Height; 436 } 437 438 switch (m_ArrowType) 439 { 440 case ArrowStyleType.None: 441 m_pCount = 5; 442 m_pnts = new PointF[m_pCount]; 443 444 m_pnts[0] = new PointF(0, 0); 445 m_pnts[1] = new PointF(dx, 0); 446 m_pnts[2] = new PointF(dx, dy); 447 m_pnts[3] = new PointF(0, dy); 448 m_pnts[4] = new PointF(0, 0); 449 break; 450 case ArrowStyleType.Top: 451 m_pCount = 8; 452 m_pnts = new PointF[m_pCount]; 453 454 m_pnts[0] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy); 455 m_pnts[1] = new PointF((dx - m_ArrowBodyWidth) / 2f, m_ArrowLength); 456 m_pnts[2] = new PointF(0, m_ArrowLength); 457 m_pnts[3] = new PointF(dx / 2f, 0); 458 m_pnts[4] = new PointF(dx, m_ArrowLength); 459 m_pnts[5] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, m_ArrowLength); 460 m_pnts[6] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy); 461 m_pnts[7] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy); 462 break; 463 case ArrowStyleType.Left: 464 m_pCount = 8; 465 m_pnts = new PointF[m_pCount]; 466 m_pnts[0] = new PointF(dx, dy / 2f - m_ArrowBodyWidth / 2f); 467 m_pnts[1] = new PointF(m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f); 468 m_pnts[2] = new PointF(m_ArrowLength, 0); 469 m_pnts[3] = new PointF(0, dy / 2f); 470 m_pnts[4] = new PointF(m_ArrowLength, dy); 471 m_pnts[5] = new PointF(m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f); 472 m_pnts[6] = new PointF(dx, dy / 2f + m_ArrowBodyWidth / 2f); 473 m_pnts[7] = new PointF(dx, dy / 2f - m_ArrowBodyWidth / 2f); 474 break; 475 case ArrowStyleType.Right: 476 m_pCount = 8; 477 m_pnts = new PointF[m_pCount]; 478 m_pnts[0] = new PointF(0, dy / 2f - m_ArrowBodyWidth / 2f); 479 m_pnts[1] = new PointF(dx - m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f); 480 m_pnts[2] = new PointF(dx - m_ArrowLength, 0); 481 m_pnts[3] = new PointF(dx, dy / 2f); 482 m_pnts[4] = new PointF(dx - m_ArrowLength, dy); 483 m_pnts[5] = new PointF(dx - m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f); 484 m_pnts[6] = new PointF(0, dy / 2f + m_ArrowBodyWidth / 2f); 485 m_pnts[7] = new PointF(0, dy / 2f - m_ArrowBodyWidth / 2f); 486 break; 487 case ArrowStyleType.Bottom: 488 m_pCount = 8; 489 m_pnts = new PointF[m_pCount]; 490 m_pnts[0] = new PointF((dx - m_ArrowBodyWidth) / 2f, 0); 491 m_pnts[1] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy - m_ArrowLength); 492 m_pnts[2] = new PointF(0, dy - m_ArrowLength); 493 m_pnts[3] = new PointF(dx / 2f, dy); 494 m_pnts[4] = new PointF(dx, dy - m_ArrowLength); 495 m_pnts[5] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy - m_ArrowLength); 496 m_pnts[6] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, 0); 497 m_pnts[7] = new PointF((dx - m_ArrowBodyWidth) / 2f, 0); 498 break; 499 case ArrowStyleType.LeftRight: 500 m_pCount = 11; 501 m_pnts = new PointF[m_pCount]; 502 m_pnts[0] = new PointF(0, dy / 2f); 503 m_pnts[1] = new PointF(m_ArrowLength, 0); 504 m_pnts[2] = new PointF(m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f); 505 m_pnts[3] = new PointF(dx - m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f); 506 m_pnts[4] = new PointF(dx - m_ArrowLength, 0); 507 m_pnts[5] = new PointF(dx, dy / 2f); 508 m_pnts[6] = new PointF(dx - m_ArrowLength, dy); 509 m_pnts[7] = new PointF(dx - m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f); 510 m_pnts[8] = new PointF(m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f); 511 m_pnts[9] = new PointF(m_ArrowLength, dy); 512 m_pnts[10] = new PointF(0, dy / 2f); 513 break; 514 case ArrowStyleType.TopBottom: 515 m_pCount = 11; 516 m_pnts = new PointF[m_pCount]; 517 m_pnts[0] = new PointF(dx / 2f, dy); 518 m_pnts[1] = new PointF(0, dy - m_ArrowLength); 519 m_pnts[2] = new PointF(dx / 2f - m_ArrowBodyWidth / 2f, dy - m_ArrowLength); 520 m_pnts[3] = new PointF(dx / 2f - m_ArrowBodyWidth / 2f, m_ArrowLength); 521 m_pnts[4] = new PointF(0, m_ArrowLength); 522 m_pnts[5] = new PointF(dx / 2f, 0); 523 m_pnts[6] = new PointF(dx, m_ArrowLength); 524 m_pnts[7] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, m_ArrowLength); 525 m_pnts[8] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy - m_ArrowLength); 526 m_pnts[9] = new PointF(dx, dy - m_ArrowLength); 527 m_pnts[10] = new PointF(dx / 2f, dy); 528 break; 529 case ArrowStyleType.UpBow: 530 m_pCount = 9; 531 m_pnts = new PointF[m_pCount]; 532 m_pnts[0] = new PointF(0, 0); 533 m_pnts[1] = new PointF(0, dy); 534 m_pnts[2] = new PointF(dx, dy); 535 m_pnts[3] = new PointF(dx, 0); 536 m_pnts[4] = new PointF(dx - m_BowWidth, 0); 537 m_pnts[5] = new PointF(dx - m_BowWidth, dy - m_BowHeight); 538 m_pnts[6] = new PointF(m_BowWidth, dy - m_BowHeight); 539 m_pnts[7] = new PointF(m_BowWidth, 0); 540 m_pnts[8] = new PointF(0, 0); 541 break; 542 case ArrowStyleType.DownBow: 543 m_pCount = 9; 544 m_pnts = new PointF[m_pCount]; 545 m_pnts[0] = new PointF(0, dy); 546 m_pnts[1] = new PointF(0, 0); 547 m_pnts[2] = new PointF(dx, 0); 548 m_pnts[3] = new PointF(dx, dy); 549 m_pnts[4] = new PointF(dx - m_BowWidth, dy); 550 m_pnts[5] = new PointF(dx - m_BowWidth, m_BowHeight); 551 m_pnts[6] = new PointF(m_BowWidth, m_BowHeight); 552 m_pnts[7] = new PointF(m_BowWidth, dy); 553 m_pnts[8] = new PointF(0, dy); 554 break; 555 case ArrowStyleType.LeftBow: 556 m_pCount = 9; 557 m_pnts = new PointF[m_pCount]; 558 m_pnts[0] = new PointF(0, 0); 559 m_pnts[1] = new PointF(dx, 0); 560 m_pnts[2] = new PointF(dx, dy); 561 m_pnts[3] = new PointF(0, dy); 562 m_pnts[4] = new PointF(0, dy - m_BowHeight); 563 m_pnts[5] = new PointF(dx - m_BowWidth, dy - m_BowHeight); 564 m_pnts[6] = new PointF(dx - m_BowWidth, m_BowHeight); 565 m_pnts[7] = new PointF(0, m_BowHeight); 566 m_pnts[8] = new PointF(0, 0); 567 break; 568 case ArrowStyleType.RightBow: 569 m_pCount = 9; 570 m_pnts = new PointF[m_pCount]; 571 m_pnts[0] = new PointF(0, 0); 572 m_pnts[1] = new PointF(dx, 0); 573 m_pnts[2] = new PointF(dx, m_BowHeight); 574 m_pnts[3] = new PointF(m_BowWidth, m_BowHeight); 575 m_pnts[4] = new PointF(m_BowWidth, dy - m_BowHeight); 576 m_pnts[5] = new PointF(dx, dy - m_BowHeight); 577 m_pnts[6] = new PointF(dx, dy); 578 m_pnts[7] = new PointF(0, dy); 579 m_pnts[8] = new PointF(0, 0); 580 break; 581 582 default: 583 break; 584 } 585 } 586 587 588 private void GraphicsPathFromPoints(PointF[] pnts, GraphicsPath gp) 589 { 590 for (int i = 0; i < pnts.Length - 1; i++) 591 { 592 gp.AddLine(pnts[i].X, pnts[i].Y, pnts[i + 1].X, pnts[i + 1].Y); 593 } 594 } 595 596 //protected override void PostFilterProperties(IDictionary Properties) 597 //{ 598 // Properties.Remove("AllowDrop"); 599 // Properties.Remove("BackColor"); 600 // Properties.Remove("BackgroundImage"); 601 // Properties.Remove("ContextMenu"); 602 // Properties.Remove("FlatStyle"); 603 // Properties.Remove("Image"); 604 // Properties.Remove("ImageAlign"); 605 // Properties.Remove("ImageIndex"); 606 // Properties.Remove("ImageList"); 607 // Properties.Remove("TextAlign"); 608 // Properties.Remove("Text"); 609 // Properties.Remove("Enabled"); 610 //} 611 #endregion 612 } 613 }
测试程序代码下载地址:http://pan.baidu.com/share/link?shareid=326955656&uk=1126205289