using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace WinFormBeautyButtonDemo
{
/// <summary>
/// WinForm自制水晶按钮(很漂亮)
/// LDH @ 2019-7-18
/// </summary>
public sealed partial class BeautyButton : Button
{
/// <summary>
/// 定义一个位图
/// </summary>
private Bitmap _btnbmp;
/// <summary>
/// 定义一个矩形
/// </summary>
private Rectangle _btnrc;
private MouseActionType _mouseActionType;
public BeautyButton()
{
InitializeComponent();
_mouseActionType = MouseActionType.None;
SetStyle(ControlStyles.AllPaintingInWmPaint | // 禁止擦除背景
ControlStyles.DoubleBuffer | // 双缓冲
ControlStyles.UserPaint, true);
// 下面这些可以不设置,也可以自己定义
Font = new Font("微软雅黑", 12, FontStyle.Bold);
BackColor = Color.DarkTurquoise;
Size = new Size(112, 48);
}
/// <summary>
/// 按钮形状
/// </summary>
/// <param name="rc">按钮的坐标和大小</param>
/// <param name="r">按钮圆弧的半径</param>
/// <returns>返回按钮形状</returns>
private GraphicsPath GetGraphicsPath(Rectangle rc, int r)
{
int x = rc.X, y = rc.Y, w = rc.Width, h = rc.Height;
var path = new GraphicsPath();
path.AddArc(x, y, r, r, 180, 90); // 左上角圆弧
path.AddArc(x + w - r, y, r, r, 270, 90); // 右上角圆弧
path.AddArc(x + w - r, y + h - r, r, r, 0, 90); // 右下角圆弧
path.AddArc(x, y + h - r, r, r, 90, 90); // 左下角圆弧
path.CloseFigure(); // 闭合
return path;
}
protected override void OnPaint(PaintEventArgs pe)
{
// base.OnPaint(pe);
var g = pe.Graphics; // 创建画布
g.Clear(SystemColors.ButtonFace); // 重置背景颜色,可以自定义
var clr = BackColor;
var btnOff = 0; // 按钮边距
var shadowOff = 0; // 阴影边距
switch (_mouseActionType)
{
case MouseActionType.None:
break;
case MouseActionType.Hover:
clr = Color.LightGray;
break;
case MouseActionType.Click:
shadowOff = 4;
clr = Color.LightGray;
btnOff = 2;
break;
}
g.SmoothingMode = SmoothingMode.AntiAlias; // 消除锯齿
// 创建按钮本身的图形
var rc1 = new Rectangle(btnOff, btnOff, ClientSize.Width - 8 - btnOff, ClientSize.Height - 8 - btnOff);
var path1 = GetGraphicsPath(rc1, 20);
var br1 = new LinearGradientBrush(new Point(0, 0), new Point(0, rc1.Height + 6), clr, Color.White);
// 创建按钮阴影
var rc2 = rc1;
rc2.Offset(shadowOff, shadowOff);
var path2 = GetGraphicsPath(rc2, 20);
var br2 = new PathGradientBrush(path2)
{
CenterColor = Color.Black, SurroundColors = new[] {SystemColors.ButtonFace}
};
// 为了更逼真,我们将渐变结束颜色设定为窗体前景色,可以根据窗口的前景颜色适当调整
// 创建按钮顶部白色渐变
var rc3 = rc1;
rc3.Inflate(-5, -5);
rc3.Height = 15;
var path3 = GetGraphicsPath(rc3, 20);
var br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White),
LinearGradientMode.Vertical);
// 绘制图形
g.FillPath(br2, path2); // 绘制阴影
g.FillPath(br1, path1); // 绘制按钮
g.FillPath(br3, path3); // 绘制顶部白色泡泡
// 设定内存位图对象,进行二级缓存绘图操作
_btnrc = new Rectangle(rc1.Location, rc1.Size);
_btnbmp = new Bitmap(_btnrc.Width, _btnrc.Height);
var gBmp = Graphics.FromImage(_btnbmp);
gBmp.SmoothingMode = SmoothingMode.AntiAlias;
gBmp.FillPath(br1, path1);
gBmp.FillPath(br3, path3);
// 将region赋值给button
var rgn = new Region(path1);
rgn.Union(path2);
Region = rgn;
// 绘制按钮的文本
var path4 = new GraphicsPath();
var path1Bounds = path1.GetBounds();
var rcText = new Rectangle((int) path1Bounds.X + btnOff, (int) path1Bounds.Y + btnOff,
(int) path1Bounds.Width,
(int) path1Bounds.Height);
var strFormat = new StringFormat
{
Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center
};
// 横竖都居中
path4.AddString(Text, Font.FontFamily, (int) Font.Style, Font.Size, rcText, strFormat);
var txtPen = new Pen(ForeColor, 1);
g.DrawPath(txtPen, path4);
gBmp.DrawPath(txtPen, path4);
}
protected override void OnMouseDown(MouseEventArgs eventArgs)
{
if (eventArgs.Button == MouseButtons.Left)
{
_mouseActionType = MouseActionType.Click;
Invalidate();
}
base.OnMouseDown(eventArgs);
}
protected override void OnMouseUp(MouseEventArgs eventArgs)
{
_mouseActionType = MouseActionType.Hover;
Invalidate();
base.OnMouseUp(eventArgs);
}
protected override void OnMouseHover(EventArgs e)
{
_mouseActionType = MouseActionType.Hover;
Invalidate();
base.OnMouseHover(e);
}
protected override void OnMouseEnter(EventArgs e)
{
_mouseActionType = MouseActionType.Hover;
Invalidate();
base.OnMouseEnter(e);
}
/// <summary>
/// 鼠标离开事件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseLeave(EventArgs e)
{
_mouseActionType = MouseActionType.None;
Invalidate();
base.OnMouseLeave(e);
}
private enum MouseActionType
{
None,
Hover,
Click
}
}
}