重写带边框的圆角矩形label控件,效果如下图
实现如下:
public enum Direction
{
Top,
Left,
Right,
Bottom
}
public static class GraphicsPathExtension
{
/// <summary>
/// 创建正多边形
/// </summary>
public static GraphicsPath CreateRegularPolygon(this Graphics g, float x, float y, float r, int num)
{
var path = new GraphicsPath();
var p1 = new PointF(x, y - r);
for (var i = 1; i < num; i++)
{
var d = PI / 2 - PI * 2 / num * i;
var p2 = new PointF(x + (float)(r * Cos(d)), y - (float)(r * Sin(d)));
path.AddLine(p1, p2);
p1 = p2;
}
return path;
}
/// <summary>
/// 创建一个箭头指向特定方向的等边三角形,且与指定矩形的中心重合
/// </summary>
public static GraphicsPath CreateTrianglePath(this Graphics g, RectangleF rect, float f, Direction direction)
{
float width = rect.Width < rect.Height ? rect.Width : rect.Height;
PointF p1 = new PointF(rect.X + rect.Width / 2, rect.Y + rect.Height / 2),
p2 = new PointF(rect.X + rect.Width / 2, rect.Y + rect.Height / 2),
p3 = new PointF(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
float d = width * f;
float sqrt = (float)Sqrt(3);
if (direction == Direction.Left)
{
p1.X -= 2 * d;
p2.X += d;
p2.Y += d * sqrt;
p3.X += d;
p3.Y -= d * sqrt;
}
else if (direction == Direction.Right)
{
p1.X += 2 * d;
p2.X -= d;
p2.Y += d * sqrt;
p3.X -= d;
p3.Y += d * sqrt;
}
else if (direction == Direction.Top)
{
p1.Y -= 2 * d;
p2.X -= d * sqrt;
p2.Y += d;
p3.X += d * sqrt;
p3.Y += d;
}
else
{
p1.Y += 2 * d;
p2.X -= d * sqrt;
p2.Y -= d;
p3.X += d * sqrt;
p3.Y -= d;
}
var path = new GraphicsPath();
path.AddLines(new[] { p1, p2, p3 });
return path;
}
/// <summary>
/// 创建圆角矩形路径
/// </summary>
public static GraphicsPath CreateRoundedRectanglePath(this Graphics g, Rectangle rect, int cornerRadius)
{
var roundedRect = new GraphicsPath();
if (cornerRadius > 0)
{
roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);
}
roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y);
if (cornerRadius > 0)
{
roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);
}
roundedRect.AddLine(rect.Right, Min(rect.Y + cornerRadius * 2, rect.Y + rect.Height / 2), rect.Right, Max(rect.Y + rect.Height - cornerRadius * 2, rect.Y + rect.Height / 2));
if (cornerRadius > 0)
{
roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);
}
roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom);
if (cornerRadius > 0)
{
roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);
}
roundedRect.AddLine(rect.X, Max(rect.Bottom - cornerRadius * 2, rect.Y + rect.Height / 2), rect.X, Min(rect.Y + cornerRadius * 2, rect.Y + rect.Height / 2));
roundedRect.CloseFigure();
return roundedRect;
}
/// <summary>
/// 创建圆角矩形路径(r1:左上,r2:右上,r3:右下,r4:左下)
/// </summary>
public static GraphicsPath CreateRoundedRectanglePath(this Graphics g, Rectangle rect, int r1, int r2, int r3, int r4)
{
var roundedRect = new GraphicsPath();
if (r1 > 0)
{
roundedRect.AddArc(rect.X, rect.Y, r1 * 2, r1 * 2, 180, 90);
}
roundedRect.AddLine(rect.X + r1, rect.Y, rect.Right - r2 * 2, rect.Y);
if (r2 > 0)
{
roundedRect.AddArc(rect.X + rect.Width - r2 * 2, rect.Y, r2 * 2, r2 * 2, 270, 90);
}
roundedRect.AddLine(rect.Right, Min(rect.Y + r2 * 2, rect.Y + rect.Height / 2), rect.Right, Max(rect.Y + rect.Height - r3 * 2, rect.Y + rect.Height / 2));
if (r3 > 0)
{
roundedRect.AddArc(rect.X + rect.Width - r3 * 2, rect.Y + rect.Height - r3 * 2, r3 * 2, r3 * 2, 0, 90);
}
roundedRect.AddLine(rect.Right - r3 * 2, rect.Bottom, rect.X + r3 * 2, rect.Bottom);
if (r4 > 0)
{
roundedRect.AddArc(rect.X, rect.Bottom - r4 * 2, r4 * 2, r4 * 2, 90, 90);
}
roundedRect.AddLine(rect.X, Max(rect.Bottom - r4 * 2, rect.Y + rect.Height / 2), rect.X, Min(rect.Y + r1 * 2, rect.Y + rect.Height / 2));
roundedRect.CloseFigure();
return roundedRect;
}
}
/// <summary>
/// 带边框的label
/// </summary>
public class UcLabel : Label
{
#region 数据属性
/// <summary>
/// 边框的宽度
/// </summary>
[Category("Border")]
public int BorderWidth { get { return borderWidth; } set { borderWidth = value; Invalidate(); } }
private int borderWidth = 1;
/// <summary>
/// 边框颜色
/// </summary>
[Category("Border")]
public Color BorderColor { get { return borderColor; } set { borderColor = value; Invalidate(); } }
private Color borderColor = Color.FromArgb(95, 132, 205);
/// <summary>
/// 边框样式
/// </summary>
[Category("Border")]
public DashStyle BorderDashStyle { get { return borderDashStyle; } set { borderDashStyle = value; Invalidate(); } }
private DashStyle borderDashStyle = DashStyle.Solid;
/// <summary>
/// 是否显示边框
/// </summary>
[Category("Border")]
public bool ShowBorder
{
get
{
return showBorder;
}
set
{
showBorder = value;
if (showBorder)
{
BorderStyle = BorderStyle.None;
}
Invalidate();
}
}
private bool showBorder = false;
/// <summary>
/// 圆角
/// </summary>
[Category("Border")]
public int Radius
{
get { return radius; }
set { radius = value < 0 ? 0 : value; Invalidate(); }
}
private int radius = 0;
#endregion
#region 构造函数
public UcLabel()
{
}
#endregion
#region 重绘
/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (showBorder)
{
if (showBorder)
{
Graphics graphics = e.Graphics;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.CompositingQuality = CompositingQuality.HighQuality;
var pen = new Pen(borderColor, borderWidth);
pen.DashStyle = borderDashStyle;
var rect = new Rectangle(0, 0, Width - borderWidth, Height - borderWidth);
if (radius > 0)
{
var path = graphics.CreateRoundedRectanglePath(rect, Radius);
graphics.DrawPath(pen, path);
}
else
{
graphics.DrawRectangle(pen, rect);
}
}
}
}
#endregion
}