效果:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
using System.ComponentModel.Design;
namespace TestControls
{
#region enum
/// <summary>
/// 颜色填充方向
/// </summary>
public enum LinearGradientDirection
{
Vertical,
Horizontal
}
/// <summary>
/// 箭头方向
/// </summary>
public enum ArrowStyleType
{
None,
Left,
Right,
Top,
Bottom,
LeftRight,
TopBottom,
UpBow,
DownBow,
LeftBow,
RightBow,
}
#endregion
public partial class ArrowLine : System.Windows.Forms.Control
{
#region 变量
//private System.ComponentModel.Container components = null;
private PointF[] m_pnts = null; // 箭头点坐标
GraphicsPath m_gp = new GraphicsPath(); // 绘制路径
private Color m_ColorS = Color.WhiteSmoke; // 起始渐变色
private Color m_ColorE = Color.DarkGray;
private Color m_NormalStartColor = Color.WhiteSmoke; // 常规起始渐变色
private Color m_NormalEndColor = Color.DarkGray;
private LinearGradientDirection m_lgdirect = LinearGradientDirection.Horizontal;
private ArrowStyleType m_ArrowType = ArrowStyleType.None; // 箭头类型
private float m_ArrowLength = 8.0f; // 箭标长度
private float m_ArrowBodyWidth = 8.0f; // 箭身宽度
private float m_BowHeight = 4.0f; // 弓长度
private float m_BowWidth = 4.0f; // 弓宽度
private bool m_antiAlias = false; // 反走样绘制
private bool m_FrameEnabled = false;
private int m_pCount = 8;
private const int MINSIZE = 2; // 最小大小
#endregion
#region 属性
/// <summary>
/// 开始渐变颜色
/// </summary>
public Color NormalStartColor
{
get { return m_NormalStartColor; }
set { m_NormalStartColor = value; Refresh(); }
}
/// <summary>
///结束渐变颜色
/// </summary>
public Color NormalEndColor
{
get { return m_NormalEndColor; }
set { m_NormalEndColor = value; Refresh(); }
}
/// <summary>
/// 渐变色方向
/// </summary>
public LinearGradientDirection ColorLinearDirection
{
get { return m_lgdirect; }
set { m_lgdirect = value; Refresh(); }
}
/// <summary>
/// 是否有立体框架
/// </summary>
public bool FrameEnabled
{
get { return m_FrameEnabled; }
set { m_FrameEnabled = value; Refresh(); }
}
/// <summary>
/// 箭头类型
/// </summary>
public ArrowStyleType ArrowStyle
{
get { return m_ArrowType; }
set
{
m_ArrowType = value;
Clear();
Init();
Refresh();
}
}
/// <summary>
/// 箭标长度
/// </summary>
public float ArrowLength
{
get { return m_ArrowLength; }
set
{
m_ArrowLength = value;
// AdjustmentBodyWH();
Clear();
Init();
Refresh();
}
}
/// <summary>
/// 箭身宽度
/// </summary>
public float ArrowBodyWidth
{
get { return m_ArrowBodyWidth; }
set
{
m_ArrowBodyWidth = value;
//AdjustmentBodyWH();
Clear();
Init();
Refresh();
}
}
/// <summary>
/// 弓长度
/// </summary>
public float BowHeight
{
get { return m_BowHeight; }
set
{
m_BowHeight = value;
Clear();
Init();
Refresh();
}
}
/// <summary>
/// 弓宽度
/// </summary>
public float BowWidth
{
get { return m_BowWidth; }
set
{
m_BowWidth = value;
Clear();
Init();
Refresh();
}
}
/// <summary>
/// 反走样
/// </summary>
public bool AntiAlias
{
get { return m_antiAlias; }
set
{
m_antiAlias = value;
Clear();
Init();
Refresh();
}
}
private bool m_LinearGradientUsingClient = true; //渐变色使用客户区
/// <summary>
/// 渐变色使用是否只使用控件客户区
/// </summary>
public bool LinearGradientUsingClient
{
get { return m_LinearGradientUsingClient; }
set
{
m_LinearGradientUsingClient = value;
{
Clear();
Init();
Refresh();
}
}
}
private Rectangle m_LinearGradientRect;
/// <summary>
/// 渐变色使用区区域范围
/// </summary>
public Rectangle LinearGradientRect
{
get { return m_LinearGradientRect; }
set
{
m_LinearGradientRect = value;
{
Clear();
Init();
Refresh();
}
}
}
#endregion
#region 构造函数
public ArrowLine()
{
InitializeComponent();
Init();
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
m_LinearGradientRect = this.ClientRectangle;
}
public ArrowLine(IContainer container)
{
container.Add(this);
InitializeComponent();
}
#endregion
#region 继承函数
/// <summary>
/// Resize
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
Clear();
Init();
Refresh();
}
/// <summary>
/// Paint
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
m_ColorS = NormalStartColor;
m_ColorE = NormalEndColor;
Rectangle rect = this.ClientRectangle;
if (m_LinearGradientUsingClient)
{
rect = this.ClientRectangle;
}
else
{
rect = this.RectangleToClient(m_LinearGradientRect);
}
LinearGradientBrush b = null;
if (ColorLinearDirection == LinearGradientDirection.Horizontal)
{
b = new LinearGradientBrush(rect, m_ColorS, m_ColorE, 0, false);
}
else
{
b = new LinearGradientBrush(rect, m_ColorS, m_ColorE, 90, false);
}
// 设计模式
if (this.DesignMode != true)
{
e.Graphics.SetClip(m_gp);
}
//反走样
if (m_antiAlias)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
}
else
{
e.Graphics.SmoothingMode = SmoothingMode.None;
}
e.Graphics.FillPath(b, m_gp); //填充路径
b.Dispose();
//划框
if (m_FrameEnabled)
{
ColorArrowFrame(e);
}
}
#endregion
#region 方法
private void Clear()
{
m_pnts = null;
m_gp.Reset();
}
private void ColorArrowFrame(PaintEventArgs e)
{
Pen p1 = null;
{
if (this.Width < this.Height)
{
for (int i = 0; i < m_pCount - 1; i++)
{
if (m_pnts[i].Y <= m_pnts[i + 1].Y)
{
p1 = new Pen(SystemColors.ControlLightLight, 1f);
}
else
{
p1 = new Pen(SystemColors.ControlDark, 1f);
}
e.Graphics.DrawLine(p1, m_pnts[i].X, m_pnts[i].Y, m_pnts[i + 1].X, m_pnts[i + 1].Y);
}
}
else
{
for (int i = 0; i < m_pCount - 1; i++)
{
if (m_pnts[i].Y > m_pnts[i + 1].Y)
{
p1 = new Pen(SystemColors.ControlLightLight, 1f);
}
else
{
p1 = new Pen(SystemColors.ControlDark, 1f);
}
e.Graphics.DrawLine(p1, m_pnts[i].X, m_pnts[i].Y, m_pnts[i + 1].X, m_pnts[i + 1].Y);
}
}
}
}
/// <summary>
/// Sequence to create the button
/// </summary>
private void Init()
{
MakeSquare();
float dx = this.Width - 2;
float dy = this.Height - 2;
if (m_FrameEnabled == false)
{
dx = this.Width;
dy = this.Height;
}
// 产生箭头坐标
BuildInitialArrow();
// 绘制
GraphicsPathFromPoints(m_pnts, m_gp);
}
private void MakeSquare()
{
this.SuspendLayout();
if (this.Width < MINSIZE)
{
this.Size = new Size(MINSIZE, MINSIZE);
}
else
{
//if ( this.Size.Width < this.Size.Height )
//{
// this.Size = new Size ( this.Size.Width, this.Size.Width );
//}
//else
//{
// this.Size = new Size ( this.Size.Height, this.Size.Height );
//}
}
this.ResumeLayout();
}
/// <summary>
/// 创建箭头点
/// </summary>
private void BuildInitialArrow()
{
// AdjustmentBodyWH();
float dx = this.Width - 2;
float dy = this.Height - 2;
if (m_FrameEnabled == false)
{
dx = this.Width;
dy = this.Height;
}
switch (m_ArrowType)
{
case ArrowStyleType.None:
m_pCount = 5;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, 0);
m_pnts[1] = new PointF(dx, 0);
m_pnts[2] = new PointF(dx, dy);
m_pnts[3] = new PointF(0, dy);
m_pnts[4] = new PointF(0, 0);
break;
case ArrowStyleType.Top:
m_pCount = 8;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy);
m_pnts[1] = new PointF((dx - m_ArrowBodyWidth) / 2f, m_ArrowLength);
m_pnts[2] = new PointF(0, m_ArrowLength);
m_pnts[3] = new PointF(dx / 2f, 0);
m_pnts[4] = new PointF(dx, m_ArrowLength);
m_pnts[5] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, m_ArrowLength);
m_pnts[6] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy);
m_pnts[7] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy);
break;
case ArrowStyleType.Left:
m_pCount = 8;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(dx, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[1] = new PointF(m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[2] = new PointF(m_ArrowLength, 0);
m_pnts[3] = new PointF(0, dy / 2f);
m_pnts[4] = new PointF(m_ArrowLength, dy);
m_pnts[5] = new PointF(m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[6] = new PointF(dx, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[7] = new PointF(dx, dy / 2f - m_ArrowBodyWidth / 2f);
break;
case ArrowStyleType.Right:
m_pCount = 8;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[1] = new PointF(dx - m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[2] = new PointF(dx - m_ArrowLength, 0);
m_pnts[3] = new PointF(dx, dy / 2f);
m_pnts[4] = new PointF(dx - m_ArrowLength, dy);
m_pnts[5] = new PointF(dx - m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[6] = new PointF(0, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[7] = new PointF(0, dy / 2f - m_ArrowBodyWidth / 2f);
break;
case ArrowStyleType.Bottom:
m_pCount = 8;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF((dx - m_ArrowBodyWidth) / 2f, 0);
m_pnts[1] = new PointF((dx - m_ArrowBodyWidth) / 2f, dy - m_ArrowLength);
m_pnts[2] = new PointF(0, dy - m_ArrowLength);
m_pnts[3] = new PointF(dx / 2f, dy);
m_pnts[4] = new PointF(dx, dy - m_ArrowLength);
m_pnts[5] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy - m_ArrowLength);
m_pnts[6] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, 0);
m_pnts[7] = new PointF((dx - m_ArrowBodyWidth) / 2f, 0);
break;
case ArrowStyleType.LeftRight:
m_pCount = 11;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, dy / 2f);
m_pnts[1] = new PointF(m_ArrowLength, 0);
m_pnts[2] = new PointF(m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[3] = new PointF(dx - m_ArrowLength, dy / 2f - m_ArrowBodyWidth / 2f);
m_pnts[4] = new PointF(dx - m_ArrowLength, 0);
m_pnts[5] = new PointF(dx, dy / 2f);
m_pnts[6] = new PointF(dx - m_ArrowLength, dy);
m_pnts[7] = new PointF(dx - m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[8] = new PointF(m_ArrowLength, dy / 2f + m_ArrowBodyWidth / 2f);
m_pnts[9] = new PointF(m_ArrowLength, dy);
m_pnts[10] = new PointF(0, dy / 2f);
break;
case ArrowStyleType.TopBottom:
m_pCount = 11;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(dx / 2f, dy);
m_pnts[1] = new PointF(0, dy - m_ArrowLength);
m_pnts[2] = new PointF(dx / 2f - m_ArrowBodyWidth / 2f, dy - m_ArrowLength);
m_pnts[3] = new PointF(dx / 2f - m_ArrowBodyWidth / 2f, m_ArrowLength);
m_pnts[4] = new PointF(0, m_ArrowLength);
m_pnts[5] = new PointF(dx / 2f, 0);
m_pnts[6] = new PointF(dx, m_ArrowLength);
m_pnts[7] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, m_ArrowLength);
m_pnts[8] = new PointF(dx / 2f + m_ArrowBodyWidth / 2f, dy - m_ArrowLength);
m_pnts[9] = new PointF(dx, dy - m_ArrowLength);
m_pnts[10] = new PointF(dx / 2f, dy);
break;
case ArrowStyleType.UpBow:
m_pCount = 9;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, 0);
m_pnts[1] = new PointF(0, dy);
m_pnts[2] = new PointF(dx, dy);
m_pnts[3] = new PointF(dx, 0);
m_pnts[4] = new PointF(dx - m_BowWidth, 0);
m_pnts[5] = new PointF(dx - m_BowWidth, dy - m_BowHeight);
m_pnts[6] = new PointF(m_BowWidth, dy - m_BowHeight);
m_pnts[7] = new PointF(m_BowWidth, 0);
m_pnts[8] = new PointF(0, 0);
break;
case ArrowStyleType.DownBow:
m_pCount = 9;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, dy);
m_pnts[1] = new PointF(0, 0);
m_pnts[2] = new PointF(dx, 0);
m_pnts[3] = new PointF(dx, dy);
m_pnts[4] = new PointF(dx - m_BowWidth, dy);
m_pnts[5] = new PointF(dx - m_BowWidth, m_BowHeight);
m_pnts[6] = new PointF(m_BowWidth, m_BowHeight);
m_pnts[7] = new PointF(m_BowWidth, dy);
m_pnts[8] = new PointF(0, dy);
break;
case ArrowStyleType.LeftBow:
m_pCount = 9;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, 0);
m_pnts[1] = new PointF(dx, 0);
m_pnts[2] = new PointF(dx, dy);
m_pnts[3] = new PointF(0, dy);
m_pnts[4] = new PointF(0, dy - m_BowHeight);
m_pnts[5] = new PointF(dx - m_BowWidth, dy - m_BowHeight);
m_pnts[6] = new PointF(dx - m_BowWidth, m_BowHeight);
m_pnts[7] = new PointF(0, m_BowHeight);
m_pnts[8] = new PointF(0, 0);
break;
case ArrowStyleType.RightBow:
m_pCount = 9;
m_pnts = new PointF[m_pCount];
m_pnts[0] = new PointF(0, 0);
m_pnts[1] = new PointF(dx, 0);
m_pnts[2] = new PointF(dx, m_BowHeight);
m_pnts[3] = new PointF(m_BowWidth, m_BowHeight);
m_pnts[4] = new PointF(m_BowWidth, dy - m_BowHeight);
m_pnts[5] = new PointF(dx, dy - m_BowHeight);
m_pnts[6] = new PointF(dx, dy);
m_pnts[7] = new PointF(0, dy);
m_pnts[8] = new PointF(0, 0);
break;
default:
break;
}
}
private void GraphicsPathFromPoints(PointF[] pnts, GraphicsPath gp)
{
for (int i = 0; i < pnts.Length - 1; i++)
{
gp.AddLine(pnts[i].X, pnts[i].Y, pnts[i + 1].X, pnts[i + 1].Y);
}
}
//protected override void PostFilterProperties(IDictionary Properties)
//{
// Properties.Remove("AllowDrop");
// Properties.Remove("BackColor");
// Properties.Remove("BackgroundImage");
// Properties.Remove("ContextMenu");
// Properties.Remove("FlatStyle");
// Properties.Remove("Image");
// Properties.Remove("ImageAlign");
// Properties.Remove("ImageIndex");
// Properties.Remove("ImageList");
// Properties.Remove("TextAlign");
// Properties.Remove("Text");
// Properties.Remove("Enabled");
//}
#endregion
}
}