ScpMonitor/ScpButton.cs (195 lines of code) (raw):

using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace ScpMonitor { [DesignTimeVisible(true), ToolboxItem(true)] public partial class ScpButton : Button { private readonly Color m_HoverColor = Color.DodgerBlue; private Color m_NormalColor = Color.Silver; protected State m_State = State.Normal; public ScpButton() { InitializeComponent(); } public bool Glassy { get { return m_NormalColor == Color.Black; } set { if (value ^ Glassy) { m_NormalColor = value ? Color.Black : Color.Silver; Invalidate(); } } } private static GraphicsPath CreateRoundRectangle(Rectangle Rectangle, int Radius) { var gp = new GraphicsPath(); var l = Rectangle.Left; var t = Rectangle.Top; var w = Rectangle.Width; var h = Rectangle.Height; var d = Radius << 1; gp.AddArc(l, t, d, d, 180, 90); // top left gp.AddLine(l + Radius, t, l + w - Radius, t); // top gp.AddArc(l + w - d, t, d, d, 270, 90); // top right gp.AddLine(l + w, t + Radius, l + w, t + h - Radius); // right gp.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottom right gp.AddLine(l + w - Radius, t + h, l + Radius, t + h); // bottom gp.AddArc(l, t + h - d, d, d, 90, 90); // bottom left gp.AddLine(l, t + h - Radius, l, t + Radius); // left gp.CloseFigure(); return gp; } private static GraphicsPath CreateTopRoundRectangle(Rectangle Rectangle, int Radius) { var gp = new GraphicsPath(); var l = Rectangle.Left; var t = Rectangle.Top; var w = Rectangle.Width; var h = Rectangle.Height; var d = Radius << 1; gp.AddArc(l, t, d, d, 180, 90); // topleft gp.AddLine(l + Radius, t, l + w - Radius, t); // top gp.AddArc(l + w - d, t, d, d, 270, 90); // topright gp.AddLine(l + w, t + Radius, l + w, t + h); // right gp.AddLine(l + w, t + h, l, t + h); // bottom gp.AddLine(l, t + h, l, t + Radius); // left gp.CloseFigure(); return gp; } private static GraphicsPath CreateBottomRadialPath(Rectangle Rectangle) { var gp = new GraphicsPath(); RectangleF rf = Rectangle; rf.X -= rf.Width*.35f; rf.Y -= rf.Height*.15f; rf.Width *= 1.7f; rf.Height *= 2.3f; gp.AddEllipse(rf); gp.CloseFigure(); return gp; } private void Glassify(Rectangle Rectangle, PaintEventArgs e, Color Color, bool Pressed) { using (var gp = CreateRoundRectangle(Rectangle, 2)) { var opacity = 0x7f; using (Brush brush = new SolidBrush(Color.FromArgb(opacity, Color))) { e.Graphics.FillPath(brush, gp); } } using (var clip = CreateRoundRectangle(Rectangle, 2)) { e.Graphics.SetClip(clip, CombineMode.Intersect); using (var gp = CreateBottomRadialPath(Rectangle)) { using (var brush = new PathGradientBrush(gp)) { var opacity = (int) (0xB2*.99f + .5f); var bounds = gp.GetBounds(); brush.CenterPoint = new PointF((bounds.Left + bounds.Right)/2f, (bounds.Top + bounds.Bottom)/2f); brush.CenterColor = Color.FromArgb(opacity, Color.White); brush.SurroundColors = new[] {Color.FromArgb(0, Color.White)}; e.Graphics.FillPath(brush, gp); } } e.Graphics.ResetClip(); } var newRect = Rectangle; newRect.Height >>= 1; if (newRect.Width > 0 && newRect.Height > 0) { newRect.Height++; using (var gp = CreateTopRoundRectangle(newRect, 2)) { var opacity = Pressed ? (int) (.4f*0x9 + .5f) : 0x99; newRect.Height++; using ( var brush = new LinearGradientBrush(newRect, Color.FromArgb(opacity, Color.White), Color.FromArgb(opacity/3, Color.White), LinearGradientMode.Vertical)) { e.Graphics.FillPath(brush, gp); } } } var Y = Rectangle.Y + Rectangle.Height - 1; // e.Graphics.DrawLine(new Pen(Color.Black), Rectangle.Left, Y, Rectangle.Right, Y); } protected override void OnPaint(PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.HighQuality; e.Graphics.Clear(Color.White); var textSize = e.Graphics.MeasureString(Text, Font); var textX = Size.Width/2 - (int) (textSize.Width/2); var textY = Size.Height/2 - (int) (textSize.Height/2); var newRect = new Rectangle(ClientRectangle.X - 1, ClientRectangle.Y - 1, ClientRectangle.Width + 1, ClientRectangle.Height + 1); if (Enabled) { switch (m_State) { case State.Normal: { Glassify(newRect, e, m_NormalColor, false); e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), textX, textY); } break; case State.Hover: { Glassify(newRect, e, m_HoverColor, false); e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), textX, textY); } break; case State.Clicked: { Glassify(newRect, e, m_HoverColor, true); e.Graphics.DrawRectangle(new Pen(m_HoverColor, 2), newRect); e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), textX + 1, textY + 1); } break; } } else { Glassify(newRect, e, m_NormalColor, false); e.Graphics.DrawString(Text, Font, new SolidBrush(ForeColor), textX, textY); } } protected override void OnMouseLeave(EventArgs e) { m_State = State.Normal; Invalidate(); base.OnMouseLeave(e); } protected override void OnMouseEnter(EventArgs e) { if (Enabled) m_State = State.Hover; Invalidate(); base.OnMouseEnter(e); } protected override void OnMouseUp(MouseEventArgs e) { if (Enabled) m_State = State.Hover; Invalidate(); base.OnMouseUp(e); } protected override void OnMouseDown(MouseEventArgs e) { if (Enabled) m_State = State.Clicked; Invalidate(); base.OnMouseDown(e); } protected enum State { Normal, Hover, Clicked } } }