Glass Effected Button



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace Mesoft.Control
{
    public class MeGlassButton : Button
    {
        #region properties
        private Bitmap _bmpBackBuffer;
        private State _status;
        [Category("Mesoft")]
        private State ButtonStatus
        {
            get { return _status; }
            set
            {
                _status = value;
                _bmpBackBuffer = null;
                this.Refresh();
            }
        }
        private enum State
        {
            Normal,
            Hover,
            Click
        }
        [Category("Mesoft")]
        private enum RectangleCorners
        {
            None = 0, TopLeft = 1, TopRight = 2,
            BottomLeft = 4, BottomRight = 8,
            All = TopLeft | TopRight | BottomLeft | BottomRight
        }
        private int _radius = 6;
        [Category("Mesoft")]
        public int RoundedCornerRadius
        {
            get { return _radius; }
            set { _radius = value; ButtonStatus = _status; }
        }
        private bool _antialias = true;
        [Category("Mesoft")]
        public bool FontAntiAlias
        {
            get { return _antialias; }
            set { _antialias = value; ButtonStatus = _status; }
        }
        [Category("Mesoft")]
        public override ContentAlignment TextAlign
        {
            get
            {
                return base.TextAlign;
            }
            set
            {
                base.TextAlign = value;
                ButtonStatus = _status;
            }
        }
        [Category("Mesoft")]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
                ButtonStatus = _status;
            }
        }
        [Category("Mesoft")]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
               base.Text = value;
                ButtonStatus = _status;
            }
        }
        [Category("Mesoft")]
        public override Font Font
        {
            get
            {
               return base.Font;
            }
            set
            {
                base.Font = value;
                ButtonStatus = _status;
            }
        }
        [Category("Mesoft")]
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
                ButtonStatus = _status;
            }
        }
        #endregion
        public MeGlassButton()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.UserPaint, true);
        }
        private void InitializeComponent()
        {
            this.Size = new System.Drawing.Size(100, 32);
            this.Font = new Font("Calibri", 12, FontStyle.Bold);
            this.ForeColor = Color.White;
            this.MouseEnter += new System.EventHandler(this.GlassButton_MouseEnter);
            this.MouseLeave += new System.EventHandler(this.GlassButton_MouseLeave);
            this.MouseDown += new MouseEventHandler(GlassButton_MouseDown);
            this.MouseUp += new MouseEventHandler(GlassButton_MouseUp);
            this.Resize += new EventHandler(GlassButton_Resize);
        }
        void GlassButton_Resize(object sender, EventArgs e)
       {
            ButtonStatus = State.Normal;
        }
        private void GlassButton_MouseUp(object sender, MouseEventArgs e)
        {
            ButtonStatus = State.Hover;
        }
        private void GlassButton_MouseDown(object sender, MouseEventArgs e)
        {
            ButtonStatus = State.Click
        }
        private void GlassButton_MouseLeave(object sender, EventArgs e)
        {
            ButtonStatus = State.Normal;
        }
        private void GlassButton_MouseEnter(object sender, EventArgs e)
        {
            ButtonStatus = State.Hover;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            if (_bmpBackBuffer == null)
            {
                DrawButton(ref _bmpBackBuffer);
            }
            if (_bmpBackBuffer != null)
            {
                e.Graphics.DrawImage(_bmpBackBuffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
            }
        }
        private void DrawButton(ref Bitmap bmp)
        {
            if (bmp == null)
            {
                bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
            }
            using (Graphics gr = Graphics.FromImage(bmp))
            {
                DrawGlass(gr, new Rectangle(0, 0, this.Width, this.Height));
            }
        }
        private void DrawGlass(Graphics gr, Rectangle rectBar)
        {
            // Some calculations
            if (rectBar.Height <= 0) rectBar.Height = 1;
            int nAlphaStart = (int)(185 + 5 * rectBar.Width / 24),
                nAlphaEnd = (int)(10 + 4 * rectBar.Width / 24);
            if (nAlphaStart > 255) nAlphaStart = 255;
            else if (nAlphaStart < 0) nAlphaStart = 0;
            if (nAlphaEnd > 255) nAlphaEnd = 255;
            else if (nAlphaEnd < 0) nAlphaEnd = 0;
            Color ColorBacklight;
            Color ColorFillBK;
            Color ColorBorder;
            switch (_status)
            {
                case State.Click:
                    ColorBacklight = GetDarkerColor(this.BackColor, 20);
                    ColorFillBK = GetDarkerColor(this.BackColor, 40);
                    ColorBorder = GetDarkerColor(this.BackColor, 60);
                    break;
                case State.Hover:
                    ColorBacklight = GetLighterColor(this.BackColor, 5);
                    ColorFillBK = GetLighterColor(this.BackColor, 10);
                    ColorBorder = GetDarkerColor(this.BackColor, 100);
                    break;
                case State.Normal:
                default:
                    ColorBacklight = this.BackColor;
                    ColorFillBK = GetDarkerColor(this.BackColor, 85);
                   ColorBorder = GetDarkerColor(this.BackColor, 100);
                    break;
            }
            Color ColorBacklightEnd = Color.FromArgb(50, 0, 0, 0);
            Color ColorGlowStart = Color.FromArgb(nAlphaEnd, 255, 255, 255);
            Color ColorGlowEnd = Color.FromArgb(nAlphaStart, 255, 255, 255);
            // Create gradient path
            RectangleF er = new RectangleF(rectBar.Left - (rectBar.Width), rectBar.Top - (rectBar.Height / 2), rectBar.Width * 3, rectBar.Height * 4);
            GraphicsPath rctPath = new GraphicsPath();
            rctPath.AddEllipse(er);
            // Create gradient
            PathGradientBrush pgr = new PathGradientBrush(rctPath);
            pgr.CenterPoint = new PointF(rectBar.Width / 2, rectBar.Height);
            pgr.CenterColor = ColorBacklight;
            pgr.SurroundColors = new Color[] { ColorBacklightEnd };
            // Create glow
            GraphicsPath rectBarPath = CreateRoundedPath(rectBar.X, rectBar.Y, rectBar.Width - 1, rectBar.Height - 1, _radius, RectangleCorners.All);
            GraphicsPath rectBarPathHalf = CreateRoundedPath(rectBar.X, rectBar.Y, rectBar.Width - 1, (rectBar.Height - 1) / 2, _radius, RectangleCorners.TopRight | RectangleCorners.TopLeft);
            Rectangle rectGlow = new Rectangle(rectBar.Left, rectBar.Top, rectBar.Width, rectBar.Height / 2);
            LinearGradientBrush brGlow = new LinearGradientBrush(
                new PointF(rectGlow.Left, rectGlow.Height + 1), new PointF(rectGlow.Left, rectGlow.Top - 1),
                ColorGlowStart, ColorGlowEnd);
            // Draw the button
            gr.FillRectangle(new SolidBrush(this.Parent.BackColor), rectBar);
            gr.FillPath(new SolidBrush(ColorFillBK), rectBarPath);
            gr.FillPath(pgr, rectBarPath);
            gr.FillPath(brGlow, rectBarPathHalf);
            gr.DrawPath(new Pen(ColorBorder, 1), rectBarPath);
            StringFormat stringFormat = new StringFormat();
            switch (this.TextAlign)
            {
                case ContentAlignment.TopLeft:
                    stringFormat.Alignment = StringAlignment.Near;
                    stringFormat.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopCenter:
                    stringFormat.Alignment = StringAlignment.Center;
                    stringFormat.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.TopRight:
                    stringFormat.Alignment = StringAlignment.Far;
                    stringFormat.LineAlignment = StringAlignment.Near;
                    break;
                case ContentAlignment.MiddleLeft:
                    stringFormat.Alignment = StringAlignment.Near;
                    stringFormat.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.MiddleCenter:
                    stringFormat.Alignment = StringAlignment.Center;
                    stringFormat.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.MiddleRight:
                    stringFormat.Alignment = StringAlignment.Far;
                    stringFormat.LineAlignment = StringAlignment.Center;
                    break;
                case ContentAlignment.BottomLeft:
                    stringFormat.Alignment = StringAlignment.Near;
                    stringFormat.LineAlignment = StringAlignment.Far;
                    break;
                case ContentAlignment.BottomCenter:
                    stringFormat.Alignment = StringAlignment.Center;
                    stringFormat.LineAlignment = StringAlignment.Far;
                    break;
                case ContentAlignment.BottomRight:
                    stringFormat.Alignment = StringAlignment.Far;
                    stringFormat.LineAlignment = StringAlignment.Far;
                    break;
            }
            SolidBrush drawBrush = new SolidBrush(this.ForeColor);
            if (_antialias)
                gr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            gr.DrawString(this.Text, this.Font, drawBrush, rectBar, stringFormat);
        }
        private Color GetDarkerColor(Color color, byte intensity)
        {
            int r, g, b;
            r = color.R - intensity;
            g = color.G - intensity;
            b = color.B - intensity;
            if (r > 255 || r < 0) r *= -1;
            if (g > 255 || g < 0) g *= -1;
            if (b > 255 || b < 0) b *= -1;
            return Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
        }
        private Color GetLighterColor(Color color, byte intensity)
        {
            int r, g, b;
            r = color.R + intensity;
            g = color.G + intensity;
            b = color.B + intensity;
            if (r > 255 || r < 0) r *= -1;
            if (g > 255 || g < 0) g *= -1;
            if (b > 255 || b < 0) b *= -1;
            return Color.FromArgb(255, (byte)r, (byte)g, (byte)b);
        }
        private GraphicsPath CreateRoundedPath(int x, int y, int width, int height, int radius, RectangleCorners corners)
        {
            int xw = x + width - 1;
            int yh = y + height - 1;
            int xwr = xw - radius;
            int yhr = yh - radius;
            int xr = x + radius;
            int yr = y + radius;
            int r2 = radius * 2;
            int xwr2 = xw - r2;
            int yhr2 = yh - r2;
            GraphicsPath p = new GraphicsPath();
            p.StartFigure();
            //Top Left Corner
            if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft)
            {
                p.AddArc(x, y, r2, r2, 180, 90);
            }
            else
            {
                p.AddLine(x, yr, x, y);
                p.AddLine(x, y, xr, y);
            }
            //Top Edge
            p.AddLine(xr, y, xwr, y);
            //Top Right Corner
            if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight)
            {
                p.AddArc(xwr2, y, r2, r2, 270, 90);
            }
            else
            {
                p.AddLine(xwr, y, xw, y);
                p.AddLine(xw, y, xw, yr);
            }
            //Right Edge
            p.AddLine(xw, yr, xw, yhr);
            //Bottom Right Corner
            if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight)
            {
                p.AddArc(xwr2, yhr2, r2, r2, 0, 90);
            }
            else
            {
                p.AddLine(xw, yhr, xw, yh);
                p.AddLine(xw, yh, xwr, yh);
            }
            //Bottom Edge
            p.AddLine(xwr, yh, xr, yh);
            //Bottom Left Corner
            if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft)
            {
                p.AddArc(x, yhr2, r2, r2, 90, 90);
            }
            else
            {
                p.AddLine(xr, yh, x, yh);
                p.AddLine(x, yh, x, yhr);
            }
            //Left Edge
            p.AddLine(x, yhr, x, yr);
            p.CloseFigure();
            return p;
        }
    }
}

No comments: