winfrom 水晶按钮

闲来无事,从网上找了不少自定义控件,然后整理了一下,做了一个水晶按钮

    /// <summary>
    /// 表示 Windows 的按钮控
    /// </summary>
    [Description("表示 Windows 的按钮控件"), DefaultEvent("Click"), ToolboxBitmap(typeof (System.Windows.Forms.Button))]
    public class Button : Control
    {
        public Button()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.Selectable, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.UserPaint, true);
            _fadeIn.Interval = 30;
            _fadeOut.Interval = 30;
            _fadeIn.Tick += FadeIn_Tick;
            _fadeOut.Tick += FadeOut_Tick;
        }

        /// <summary>
        /// 淡出
        /// </summary>
        private void FadeOut_Tick(object sender, EventArgs e)
        {
            if (ButtonStyle == Style.Flat)
            {
                _glowAlpha = 0;
            }
            if (_glowAlpha - 30 <= 0)
            {
                _glowAlpha = 0;
                _fadeOut.Stop();
            }
            else
            {
                _glowAlpha -= 30;
            }
            Invalidate();
        }

        /// <summary>
        /// 淡入
        /// </summary>
        private void FadeIn_Tick(object sender, EventArgs e)
        {
            if (ButtonStyle == Style.Flat)
            {
                _glowAlpha = 0;
            }
            if (_glowAlpha + 30 >= 255)
            {
                _glowAlpha = 255;
                _fadeIn.Stop();
            }
            else
            {
                _glowAlpha += 30;
            }
            Invalidate();
        }

        private readonly Color[] _colorArray =
        {
            Color.White, Color.FromArgb(172, 168, 153), Color.White,
            Color.FromArgb(236, 233, 216)
        };

        private float _radius = 3;
        private Style _mButtonStyle = Style.Default;
        private State _mButtonState = State.None;
        private readonly Timer _fadeIn = new Timer();
        private readonly Timer _fadeOut = new Timer();
        private int _glowAlpha;
        private ContentAlignment _mTextAlign = ContentAlignment.MiddleCenter;
        private ContentAlignment _mImageAlign = ContentAlignment.BottomCenter;
        private Size _mImageSize = new Size(24, 24);
        private Image _mImage;
        private Image _backImage;

        /// <summary>
        /// 高亮颜色
        /// </summary>
        [Category("Appearance"), Description("高亮颜色"), DefaultValue(typeof(Color), "White"), Browsable(true)]
        public Color LightColor
        {
            set
            {
                _colorArray[0] = value;
                Invalidate();
            }
            get { return _colorArray[0]; }
        }

        /// <summary>
        /// 底色
        /// </summary>
        [Category("Appearance"), Description("底色"), DefaultValue(typeof(Color), "172, 168, 153"), Browsable(true)]
        public Color PrimaryColor
        {
            set
            {
                _colorArray[1] = value;
                Invalidate();
            }
            get { return _colorArray[1]; }
        }

        /// <summary>
        /// 亮点颜色
        /// </summary>
        [Category("Appearance"), Description("亮点颜色"), DefaultValue(typeof(Color), "White"), Browsable(true)]
        public Color GlowColor
        {
            set
            {
                _colorArray[2] = value;
                Invalidate();
            }
            get { return _colorArray[2]; }
        }

        /// <summary>
        /// 基本色
        /// </summary>
        [Category("Appearance"), Description("基本色"), DefaultValue(typeof(Color), "236, 233, 216"), Browsable(true)]
        public Color BaseColor
        {
            set
            {
                _colorArray[3] = value;
                Invalidate();
            }
            get { return _colorArray[3]; }
        }

        /// <summary>
        /// 角的度数
        /// </summary>
        [Category("Appearance"), Description("角的度数"), DefaultValue(typeof (float), "8"), Browsable(true)]
        public float CornerRadius
        {
            set
            {
                _radius = value;
                Invalidate();
            }
            get { return _radius; }
        }

        /// <summary>
        /// 角的度数
        /// </summary>
        [Category("Appearance"), Description("角的度数"), DefaultValue(typeof (Style), "Default"), Browsable(true)]
        public Style ButtonStyle
        {
            get { return _mButtonStyle; }
            set
            {
                _mButtonStyle = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 按钮文本的对其方式
        /// </summary>
        [Category("Text"), Description("按钮文本的对其方式"), DefaultValue(typeof (Style), "MiddleCenter"), Browsable(true)]
        public ContentAlignment TextAlign
        {
            get { return _mTextAlign; }
            set
            {
                _mTextAlign = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 图片的对齐方式
        /// </summary>
        [Category("图像"), Description("图片的对齐方式"), DefaultValue(typeof (ContentAlignment), "MiddleLeft"),
         Browsable(true)]
        public ContentAlignment ImageAlign
        {
            set
            {
                _mImageAlign = value;
                Invalidate();
            }
            get { return _mImageAlign; }
        }

        /// <summary>
        /// 图片的高度和宽度
        /// </summary>
        [Category("图像"), Description("图片的高度和宽度"), DefaultValue(typeof(ContentAlignment), "24,24"), Browsable(true)]
        public Size ImageSize
        {
            set
            {
                _mImageSize = value;
                Invalidate();
            }
            get { return _mImageSize; }
        }

        /// <summary>
        /// 图片
        /// </summary>
        [Category("图像"), Description("图片"), DefaultValue(null), Browsable(true)]
        public Image Image
        {
            set
            {
                _mImage = value;
                Invalidate();
            }
            get { return _mImage; }
        }

        [Category("Appearance"), Description("背景图"), DefaultValue(null), Browsable(true)]
        public Image BackImage
        {
            set
            {
                _backImage = value;
                Invalidate();
            }
            get { return _backImage; }
        }

        /// <summary>
        /// 获取绘制区域路径
        /// </summary>
        /// <param name="r">区域</param>
        /// <param name="r1">角1度数</param>
        /// <param name="r2">角2度数</param>
        /// <param name="r3">角3度数</param>
        /// <param name="r4">角4度数</param>
        /// <returns></returns>
        private GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
        {
            float x = r.X, y = r.Y, w = r.Width, h = r.Height;
            var gp = new GraphicsPath();
            gp.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
            gp.AddLine(x + r1, y, x + w - r2, y);
            gp.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
            gp.AddLine(x + w, y + r2, x + w, y + h - r3);
            gp.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
            gp.AddLine(x + w - r3, y + h, x + r4, y + h);
            gp.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
            gp.AddLine(x, y + h - r4, x, y + r1);
            return gp;
        }

        /// <summary>
        /// 获取绘制文本的方式
        /// </summary>
        /// <returns></returns>
        private StringFormat StringFormatAlignment()
        {
            var sf = new StringFormat();
            switch (TextAlign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.TopCenter:
                case ContentAlignment.TopRight:
                    sf.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleRight:
                    sf.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomRight:
                    sf.LineAlignment = StringAlignment.Far;
                    break;
            }
            switch (TextAlign)
            {
                case ContentAlignment.TopLeft:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.BottomLeft:
                    sf.Alignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopCenter:
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.BottomCenter:
                    sf.Alignment = StringAlignment.Center;
                    break;
                case ContentAlignment.TopRight:
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                    sf.Alignment = StringAlignment.Far;
                    break;
            }
            return sf;
        }

        /// <summary>
        /// 绘制外部
        /// </summary>
        /// <param name="g"></param>
        private void DrawOuterStroke(Graphics g)
        {
            if (ButtonStyle == Style.Flat && _mButtonState == State.None)
            {
                return;
            }
            Rectangle r = ClientRectangle;
            r.Width -= 1;
            r.Height -= 1;
            using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
            {
                using (var p = new Pen(PrimaryColor))
                {
                    g.DrawPath(p, rr);
                }
            }
        }

        /// <summary>
        /// 绘制内部
        /// </summary>
        /// <param name="g"></param>
        private void DrawInnerStroke(Graphics g)
        {
            if (ButtonStyle == Style.Flat && _mButtonState == State.None)
            {
                return;
            }
            Rectangle r = ClientRectangle;
            r.X++;
            r.Y++;
            r.Width -= 3;
            r.Height -= 3;
            using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
            {
                using (var p = new Pen(LightColor))
                {
                    g.DrawPath(p, rr);
                }
            }
        }

        /// <summary>
        /// 绘制背景
        /// </summary>
        /// <param name="g"></param>
        private void DrawBackground(Graphics g)
        {
            if (ButtonStyle == Style.Flat && _mButtonState == State.None)
            {
                return;
            }
            int alpha = (_mButtonState == State.Pressed) ? 204 : 127;
            Rectangle r = ClientRectangle;
            r.Width--;
            r.Height--;
            using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
            {
                using (var sb = new SolidBrush(BaseColor))
                {
                    g.FillPath(sb, rr);
                }
                SetClip(g);
                if (BackImage != null)
                {
                    g.DrawImage(BackImage, ClientRectangle);
                }
                g.ResetClip();
                using (var sb = new SolidBrush(Color.FromArgb(alpha, PrimaryColor)))
                {
                    g.FillPath(sb, rr);
                }
            }
        }

        /// <summary>
        /// 绘制高亮
        /// </summary>
        /// <param name="g"></param>
        private void DrawHighlight(Graphics g)
        {
            if (ButtonStyle == Style.Flat && _mButtonState == State.None)
            {
                return;
            }
            int alpha = (_mButtonState == State.Pressed) ? 60 : 150;
            var rect = new Rectangle(0, 0, Width, Height/2);
            using (GraphicsPath r = RoundRect(rect, CornerRadius, CornerRadius, 0, 0))
            {
                using (var lg = new LinearGradientBrush(r.GetBounds(),
                    Color.FromArgb(alpha, LightColor),
                    Color.FromArgb(alpha/3, LightColor),
                    LinearGradientMode.Vertical))
                {
                    g.FillPath(lg, r);
                }
            }
        }

        /// <summary>
        /// 绘制亮点
        /// </summary>
        /// <param name="g"></param>
        private void DrawGlow(Graphics g)
        {
            if (_mButtonState == State.Pressed)
            {
                return;
            }
            SetClip(g);
            using (var glow = new GraphicsPath())
            {
                glow.AddEllipse(-5, Height/2 - 10, Width + 11, Height + 11);
                using (var gl = new PathGradientBrush(glow))
                {
                    gl.CenterColor = Color.FromArgb(_glowAlpha, GlowColor);
                    gl.SurroundColors = new[] {Color.FromArgb(0, GlowColor)};
                    g.FillPath(gl, glow);
                }
            }
            g.ResetClip();
        }

        /// <summary>
        /// 绘制剪辑区域
        /// </summary>
        /// <param name="g"></param>
        private void SetClip(Graphics g)
        {
            Rectangle r = ClientRectangle;
            r.X++;
            r.Y++;
            r.Width -= 3;
            r.Height -= 3;
            using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
            {
                g.SetClip(rr);
            }
        }

        /// <summary>
        /// 绘制文本
        /// </summary>
        /// <param name="g"></param>
        private void DrawText(Graphics g)
        {
            StringFormat sf = StringFormatAlignment();
            var s = g.MeasureString(Text, Font);
            var x = (int) ((Width - s.Width - 1)/2);
            var y = (int) ((Height - s.Height - 1)/3*2);
            var r = new Rectangle(x, y, (int) s.Width + 1, (int) s.Height + 1);
            g.DrawString(Text, Font, new SolidBrush(ForeColor), r, sf);
        }

        /// <summary>
        /// 绘制图片
        /// </summary>
        /// <param name="g"></param>
        private void DrawImage(Graphics g)
        {
            if (Image == null)
            {
                return;
            }
            var r = new Rectangle(8, 8, ImageSize.Width, ImageSize.Height);
            switch (ImageAlign)
            {
                case ContentAlignment.TopCenter:
                    r = new Rectangle(Width/2 - ImageSize.Width/2, 8, ImageSize.Width, ImageSize.Height);
                    break;
                case ContentAlignment.TopRight:
                    r = new Rectangle(Width - 8 - ImageSize.Width, 8, ImageSize.Width, ImageSize.Height);
                    break;
                case ContentAlignment.MiddleLeft:
                    r = new Rectangle(8, Height/2 - ImageSize.Height/2, ImageSize.Width, ImageSize.Height);
                    break;
                case ContentAlignment.MiddleCenter:
                    r = new Rectangle(Width/2 - ImageSize.Width/2, Height/2 - ImageSize.Height/2, ImageSize.Width,
                        ImageSize.Height);
                    break;
                case ContentAlignment.MiddleRight:
                    r = new Rectangle(Width - 8 - ImageSize.Width, Height/2 - ImageSize.Height/2, ImageSize.Width,
                        ImageSize.Height);
                    break;
                case ContentAlignment.BottomLeft:
                    r = new Rectangle(8, Height - 8 - ImageSize.Height, ImageSize.Width, ImageSize.Height);
                    break;
                case ContentAlignment.BottomCenter:
                    r = new Rectangle(Width/2 - ImageSize.Width/2, Height - 8 - ImageSize.Height, ImageSize.Width,
                        ImageSize.Height);
                    break;
                case ContentAlignment.BottomRight:
                    r = new Rectangle(Width - 8 - ImageSize.Width, Height - 8 - ImageSize.Height, ImageSize.Width,
                        ImageSize.Height);
                    break;
            }
            g.DrawImage(Image, r);
        }

        /// <summary>
        /// 重绘按钮
        /// </summary>
        /// <param name="pevent"></param>
        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);
            pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            pevent.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            DrawBackground(pevent.Graphics);
            DrawHighlight(pevent.Graphics);
            DrawImage(pevent.Graphics);
            DrawText(pevent.Graphics);
            DrawGlow(pevent.Graphics);
            DrawOuterStroke(pevent.Graphics);
            DrawInnerStroke(pevent.Graphics);
        }

        /// <summary>
        /// 鼠标移入
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseEnter(EventArgs e)
        {
            _mButtonState = State.Hover;
            _fadeOut.Stop();
            _fadeIn.Start();
            base.OnMouseEnter(e);
        }

        /// <summary>
        /// 鼠标移出
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            _mButtonState = State.None;
            if (_mButtonStyle == Style.Flat)
            {
                _glowAlpha = 0;
            }
            _fadeIn.Stop();
            _fadeOut.Start();
            base.OnMouseLeave(e);
        }

        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            if (mevent.Button == MouseButtons.Left)
            {
                _mButtonState = State.Pressed;
                if (_mButtonStyle != Style.Flat)
                {
                    _glowAlpha = 255;
                }
                _fadeIn.Stop();
                _fadeOut.Stop();
                Invalidate();
            }
            base.OnMouseDown(mevent);
        }

        /// <summary>
        /// 鼠标弹起
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            if (mevent.Button == MouseButtons.Left)
            {
                _mButtonState = State.Hover;
                _fadeIn.Stop();
                _fadeOut.Stop();
                Invalidate();
            }
            base.OnMouseUp(mevent);
        }

        /// <summary>
        /// 按钮变化
        /// </summary>
        /// <param name="e"></param>
        protected override void OnResize(EventArgs e)
        {
            Rectangle r = ClientRectangle;
            r.X -= 1;
            r.Y -= 1;
            r.Width += 2;
            r.Height += 2;
            using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
            {
                Region = new Region(rr);
            }
            base.OnResize(e);
        }

        /// <summary>
        /// 鼠标活动类别
        /// </summary>
        public enum State
        {
            /// <summary>
            /// 正常状态
            /// </summary>
            None,
            /// <summary>
            /// 鼠标悬浮状态
            /// </summary>
            Hover,
            /// <summary>
            /// 鼠标按下
            /// </summary>
            Pressed
        }

        /// <summary>
        /// 绘制样式
        /// </summary>
        public enum Style
        {
            /// <summary>
            /// 只画背景的鼠标
            /// </summary>
            Default,
            /// <summary>
            /// 绘制按钮作为正常
            /// </summary>
            Flat
        };
    }
原文地址:https://www.cnblogs.com/rogation/p/3796875.html