WinForm自制水晶按钮

1.代码结构

 

2.实现代码

 

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
        }
    }
}

 

3.运行效果

转载于:https://www.cnblogs.com/LifeDecidesHappiness/p/11210336.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值