24

It's a rounded edges button

Hello, through some research around here and other sites, I've made a rounded edges button.

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    Rectangle Rect = new Rectangle(0, 0, this.Width, this.Height);
    GraphicsPath GraphPath = new GraphicsPath();
    GraphPath.AddArc(Rect.X, Rect.Y, 50, 50, 180, 90);
    GraphPath.AddArc(Rect.X + Rect.Width - 50, Rect.Y, 50, 50, 270, 90);
    GraphPath.AddArc(Rect.X + Rect.Width - 50, Rect.Y + Rect.Height - 50, 50, 50, 0, 90);
    GraphPath.AddArc(Rect.X, Rect.Y + Rect.Height - 50, 50, 50, 90, 90);
    this.Region = new Region(GraphPath);
}

The problem I'm facing is the button's "blue highlight": It shows on most of the button, but it doesn't show on the rounded edges, so my button is part highlighted and part non-highlighted (on the edges). What could I do to solve this? Thank you.

PS: I can't use WPF. The application is for an very old computer; so, please, don't suggest it. Also, the client doesn't have the money to get a newer computer.

soulblazer
  • 1,178
  • 7
  • 20
  • 30

6 Answers6

36

This is a quick one, you may want to fine tune things and optimize quite a few details..

class RoundedButton : Button
{
   GraphicsPath GetRoundPath(RectangleF Rect, int radius)
   {
      float r2 = radius / 2f;
      GraphicsPath GraphPath = new GraphicsPath();
      GraphPath.AddArc(Rect.X, Rect.Y, radius, radius, 180, 90);
      GraphPath.AddLine(Rect.X + r2, Rect.Y, Rect.Width - r2, Rect.Y);
      GraphPath.AddArc(Rect.X + Rect.Width - radius, Rect.Y, radius, radius, 270, 90);
      GraphPath.AddLine(Rect.Width, Rect.Y + r2, Rect.Width, Rect.Height - r2);
      GraphPath.AddArc(Rect.X + Rect.Width - radius, 
                       Rect.Y + Rect.Height - radius, radius, radius, 0, 90);
      GraphPath.AddLine(Rect.Width - r2, Rect.Height, Rect.X + r2, Rect.Height);
      GraphPath.AddArc(Rect.X, Rect.Y + Rect.Height - radius, radius, radius, 90, 90);
      GraphPath.AddLine(Rect.X, Rect.Height - r2, Rect.X, Rect.Y + r2);
      GraphPath.CloseFigure();
      return GraphPath;
   }

   protected override void OnPaint(PaintEventArgs e)
   {
      base.OnPaint(e);
      RectangleF Rect = new RectangleF(0, 0, this.Width, this.Height);
      using (GraphicsPath GraphPath = GetRoundPath(Rect, 50))
      {
        this.Region = new Region(GraphPath);
        using (Pen pen = new Pen(Color.CadetBlue, 1.75f))
        {
            pen.Alignment = PenAlignment.Inset;
            e.Graphics.DrawPath(pen, GraphPath);
        }
      }
   }
}

Obviously, since we have a class we can cache the GraphicsPath in a class variable. And of course you pick the color..

enter image description here

TaW
  • 53,122
  • 8
  • 69
  • 111
  • 1
    It's too troublesome to make apps for old computers... Thank you for sharing this code! – soulblazer Feb 16 '15 at 02:28
  • This is a good solution. But still the border line is not very impressive. Actually too lame, it made me not to use this. – Ghasem Sep 10 '15 at 04:23
  • 1
    Well, one could try a Graphics.SmoothingMode but you're right: Winforms is not good at glitz.. – TaW Sep 10 '15 at 06:16
  • @TaW, thank you very much for the precise code, but the second parameter name of the GetRoundPath function, shouldn't be `diameter` instead of `radius`? (That is how I personally understand the AddArc function) Then, the `float r2` variable could simply be called `radius`... – Aaron Tuil Jan 05 '22 at 15:59
  • As noted by [Jimi](https://stackoverflow.com/questions/72545288/c-sharp-winforms-button-corners-rounded-differently-with-graphicspath?noredirect=1#comment128154090_72545288), always setting/disposing the region&path in the OnPaint event may not be the best idea. So, especially if the appearance won't change all the time, one may want to set the region in the constructor and keep the region & path for the lifetime of the control. – TaW Jun 08 '22 at 15:15
6

This is a tweak on TaW's answer to more easily tweak the borderRadius and borderThickness. If you get random white space between the border and the button background color, m needs to be tweaked.

public class RoundedButton : Button
{
  GraphicsPath GetRoundPath(RectangleF Rect, int radius)
  {
    float m = 2.75F;
    float r2 = radius / 2f;
    GraphicsPath GraphPath = new GraphicsPath();

    GraphPath.AddArc(Rect.X + m, Rect.Y + m, radius, radius, 180, 90);
    GraphPath.AddLine(Rect.X + r2 + m, Rect.Y + m, Rect.Width - r2 - m, Rect.Y + m);
    GraphPath.AddArc(Rect.X + Rect.Width - radius - m, Rect.Y + m, radius, radius, 270, 90);
    GraphPath.AddLine(Rect.Width - m, Rect.Y + r2, Rect.Width - m, Rect.Height - r2 - m);
    GraphPath.AddArc(Rect.X + Rect.Width - radius - m,
                   Rect.Y + Rect.Height - radius - m, radius, radius, 0, 90);
    GraphPath.AddLine(Rect.Width - r2 - m, Rect.Height - m, Rect.X + r2 - m, Rect.Height - m);
    GraphPath.AddArc(Rect.X + m, Rect.Y + Rect.Height - radius - m, radius, radius, 90, 90);
    GraphPath.AddLine(Rect.X + m, Rect.Height - r2 - m, Rect.X + m, Rect.Y + r2 + m);

    GraphPath.CloseFigure();
    return GraphPath;
  }

  protected override void OnPaint(PaintEventArgs e)
  {
    int borderRadius = 50;
    float borderThickness = 1.75f;
    base.OnPaint(e);
    RectangleF Rect = new RectangleF(0, 0, this.Width, this.Height);
    GraphicsPath GraphPath = GetRoundPath(Rect, borderRadius);

    this.Region = new Region(GraphPath);
    using (Pen pen = new Pen(Color.Silver, borderThickness))
    {
      pen.Alignment = PenAlignment.Inset;
      e.Graphics.DrawPath(pen, GraphPath);
    }
  }
}

Cheers!

Daniel Lord
  • 754
  • 5
  • 18
3
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace button2
{
    public partial class Form1 : Form
    {
        private Button button1;
        private GroupBox box;
        public Form1()
        {
            InitializeComponent();
            show();
        }
        private void show()
        {
            box = new GroupBox();
            button1 = new Button();
            button1.Location = new Point(50, 50);
            ElipseControl nn = new ElipseControl();            
            nn.TargetControl = button1;            
            button1.Text = "First Name";
            button1.BackColor = Color.Cyan;
            button1.FlatStyle = FlatStyle.Flat;
            button1.FlatAppearance.BorderSize = 0;
            button1.FlatAppearance.BorderColor = Color.White;
            nn.CornerRadius = 10;

            button1.ForeColor = Color.Blue;
            button1.Font = new Font("Arial", 9, FontStyle.Bold);
            box.Controls.Add(button1);
            box.AutoSize = true;


            this.Controls.Add(box);

        }
    }
    class ElipseControl : Component
    {
        [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
        public static extern IntPtr CreateRoundRectRgn
            (
               int nLeftRect,
               int nTopRect,
               int nRightRect,
               int nBottomRect,
               int nWidthEllipse,
               int nHeightEllipse
            );
        private Control _cntrl;
        private int _CornerRadius = 30;

        public Control TargetControl
        {
            get { return _cntrl; }
            set
            {
                _cntrl = value;
                _cntrl.SizeChanged += (sender, eventArgs) => _cntrl.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, _cntrl.Width, _cntrl.Height, _CornerRadius, _CornerRadius));
            }
        }

        public int CornerRadius
        {
            get { return _CornerRadius; }
            set
            {
                _CornerRadius = value;
                if (_cntrl != null)
                    _cntrl.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, _cntrl.Width, _cntrl.Height, _CornerRadius, _CornerRadius));
            }
        }
    }
}
biwicks
  • 39
  • 2
  • 3
    Could you please write a bit of a comment describing what your code does and why it might be helpful? – Szab Jan 03 '19 at 10:07
1
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace ButtonRounded
{
    public enum ButtonAction
    {
        Highlight,
        Click,
        Disabled,
        Normal,
    }
public enum ShadowPosition
{
    BottomRight,
    Bottom,
    BottomLeft,
    Left,
    TopLeft,
    Top,
    TopRight,
    Right,
}

public enum ShadowSize
{
    Thin,
    Normal,
    Thick,
    None,
}

public static class ControlExtensions
{
    public static T Clone<T>(this T controlToClone)
        where T : Control
    {
        PropertyInfo[] controlProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        T instance = Activator.CreateInstance<T>();

        foreach (PropertyInfo propInfo in controlProperties)
        {
            if (propInfo.CanWrite && propInfo.Name != "WindowTarget")
            {
                propInfo.SetValue(instance, propInfo.GetValue(controlToClone, null), null);
            }
        }

        return instance;
    }

    public static void Copy<T>(this T controlToClone, ref T targetControl)
        where T : Control
    {
        foreach (PropertyInfo propInfo in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (propInfo.CanWrite && propInfo.Name != "WindowTarget")
            {
                propInfo.SetValue(targetControl, propInfo.GetValue(controlToClone, null), null);
            }
        }
    }
}

public class RoundedButtons : IDisposable
{
    public bool IsDisposed;
    private readonly Dictionary<Button, Button> _ButtonDataDictionary = new Dictionary<Button, Button>();

    public RoundedButtons()
    {
        MouseEventClick = (sender, e) => Button_MouseAction(sender, ButtonAction.Click);
        MouseEventHighlight = (sender, e) => Button_MouseAction(sender, ButtonAction.Highlight);
        EventHighlight = (sender, e) => Button_MouseAction(sender, ButtonAction.Highlight);
        EventNormal = (sender, e) => Button_MouseAction(sender, ButtonAction.Normal);
    }

    private event EventHandler EventHighlight;

    private event EventHandler EventNormal;

    private event MouseEventHandler MouseEventClick;

    private event MouseEventHandler MouseEventHighlight;

    public int Btn_CornerRadius { get; set; } = 8;
    public int Btn_LineWidth { get; set; } = 1;
    public ShadowPosition Btn_ShadowLocation { get; set; }
    public ShadowSize Btn_ShadowWidth { get; set; } = ShadowSize.Normal;
    public Padding Btn_TextPadding { get; set; } = new Padding(0);

    public Color ClickBGColor { get; set; } = Color.Empty;
    public Color ClickLineColor { get; set; } = Color.Black;
    public Color ClickShadowColor { get; set; } = Color.Black;
    public Color ClickTextColor { get; set; } = Color.GhostWhite;
    public Color DisabledBGColor { get; set; } = Color.Empty;
    public Color DisabledLineColor { get; set; } = Color.LightGray;
    public Color DisabledShadowColor { get; set; } = Color.DarkGray;
    public Color DisabledTextColor { get; set; } = Color.Gray;
    public Color HighlightBGColor { get; set; } = Color.Empty;
    public Color HighlightLineColor { get; set; } = Color.Blue;
    public Color HighlightShadowColor { get; set; } = Color.Black;
    public Color HighlightTextColor { get; set; } = Color.Empty;
    public Color MainBGColor { get; set; } = Color.Empty;
    public Color MainLineColor { get; set; } = Color.Black;
    public Color MainShadowColor { get; set; } = Color.DarkGray;
    public Color MainTextColor { get; set; } = Color.Empty;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public string GetButtonText(Button button)
    {
        string text = "";
        _ButtonDataDictionary.TryGetValue(button, out Button copy);
        if (copy != null)
        {
            text = copy.Text;
        }

        return text;
    }

    public void PaintButton(object sender)
    {
        if (sender is Button b)
        {
            _ButtonDataDictionary.Add(b, b.Clone());
            b.TabStop = false;
            b.FlatStyle = FlatStyle.Flat;
            b.FlatAppearance.BorderSize = 0;
            b.FlatAppearance.MouseDownBackColor = Color.FromArgb(0, 255, 255, 255);
            b.FlatAppearance.MouseOverBackColor = Color.FromArgb(0, 255, 255, 255);
            b.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
            b.BackColor = Color.FromArgb(0, 255, 255, 255);

            //Clear text field to prevent double drawn text with Transparency.
            b.Text = "";

            b.Paint += B_Paint;
            b.EnabledChanged += EventNormal;
            b.MouseEnter += EventHighlight;
            b.MouseLeave += EventNormal;
            b.MouseDown += MouseEventClick;
            b.MouseUp += MouseEventHighlight;
            b.TextChanged += B_TextChanged;

            b.Refresh();
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!IsDisposed && disposing)
        {
            Button[] keys = _ButtonDataDictionary.Keys.ToArray();
            for (int i = 0; i < keys.Length; i++)
            {
                Button b = _ButtonDataDictionary.ElementAt(i).Key;
                Button copy = _ButtonDataDictionary.ElementAt(i).Value;

                b.Paint -= B_Paint;
                b.EnabledChanged -= EventNormal;
                b.MouseEnter -= EventHighlight;
                b.MouseLeave -= EventNormal;
                b.MouseDown -= MouseEventClick;
                b.MouseUp -= MouseEventHighlight;
                b.TextChanged -= B_TextChanged;
                copy?.Copy(ref b);
                copy?.Dispose();
                b?.Refresh();
            }

            _ButtonDataDictionary.Clear();
            IsDisposed = true;
        }
    }

    private void B_Paint(object sender, PaintEventArgs e)
    {
        RoundedButton_Paint(sender, e, ButtonAction.Normal);
    }

    private void B_Paint_Click(object sender, PaintEventArgs e)
    {
        RoundedButton_Paint(sender, e, ButtonAction.Click);
    }

    private void B_Paint_Disable(object sender, PaintEventArgs e)
    {
        RoundedButton_Paint(sender, e, ButtonAction.Disabled);
    }

    private void B_Paint_Hightlight(object sender, PaintEventArgs e)
    {
        RoundedButton_Paint(sender, e, ButtonAction.Highlight);
    }

    private void B_TextChanged(object sender, EventArgs e)
    {
        if (sender is Button b)
        {
            _ButtonDataDictionary.TryGetValue(b, out Button copy);
            copy.Text = b.Text;
            b.TextChanged -= B_TextChanged;
            b.Text = "";
            b.TextChanged += B_TextChanged;
        }
    }

    private void Button_MouseAction(object sender, ButtonAction action)
    {
        if (sender is Button b)
        {
            b.Paint -= B_Paint_Disable;
            b.Paint -= B_Paint_Click;
            b.Paint -= B_Paint_Hightlight;
            b.Paint -= B_Paint;

            b.Paint += action switch
            {
                ButtonAction.Click => B_Paint_Click,
                ButtonAction.Disabled => B_Paint_Disable,
                ButtonAction.Highlight => B_Paint_Hightlight,
                _ => B_Paint
            };

            b.Refresh();
        }
    }

    private Rectangle[] CalculateRects(Button b, int shadowWidth)
    {
        int width = b.Size.Width - 1;
        int height = b.Size.Height - 1;
        if (Btn_ShadowLocation.ToString().Contains("Bottom") || Btn_ShadowLocation.ToString().Contains("Top"))
        {
            height -= Btn_LineWidth * 2; height -= shadowWidth;
        }

        if (Btn_ShadowLocation.ToString().Contains("Right") || Btn_ShadowLocation.ToString().Contains("Left"))
        {
            width -= Btn_LineWidth * 2; width -= shadowWidth;
        }

        Size size = new Size(width, height);
        Rectangle shadow = new Rectangle(new Point(0, 0), size);
        Rectangle button = new Rectangle(new Point(0, 0), size);

        if (Btn_ShadowLocation.ToString().Contains("Right"))
        {
            shadow.X = shadowWidth;
            button.X = 0;
        }

        if (Btn_ShadowLocation.ToString().Contains("Bottom"))
        {
            shadow.Y = shadowWidth;
            button.Y = 0;
        }

        if (Btn_ShadowLocation.ToString().Contains("Left"))
        {
            shadow.X = 0;
            button.X = shadowWidth;
        }

        if (Btn_ShadowLocation.ToString().Contains("Top"))
        {
            shadow.Y = 0;
            button.Y = shadowWidth;
        }

        return new Rectangle[] { shadow, button };
    }

    private void RoundedButton_Paint(object sender, PaintEventArgs e, ButtonAction action = ButtonAction.Normal)
    {
        if (sender is Button b)
        {
            if (!b.Enabled)
            {
                action = ButtonAction.Disabled;
            }

            //================Setup================
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
            e.Graphics.CompositingQuality = CompositingQuality.HighSpeed;
            e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault; //Causes issues with application text.

            StringFormat stringFormat = new StringFormat
            {
                Alignment = StringAlignment.Center,
                LineAlignment = StringAlignment.Center
            };

            int shadowWidth = (Btn_ShadowWidth == ShadowSize.Thin) ? 1 : (Btn_ShadowWidth == ShadowSize.Normal) ? 2 : (Btn_ShadowWidth == ShadowSize.Thick) ? 3 : 0;
            Rectangle[] rect = CalculateRects(b, shadowWidth);
            _ButtonDataDictionary.TryGetValue(b, out Button copy);

            //=====================================
            //===============Colors================
            Color shadowColor = action switch
            {
                ButtonAction.Click => ClickShadowColor,
                ButtonAction.Disabled => DisabledShadowColor,
                ButtonAction.Highlight => HighlightShadowColor,
                ButtonAction.Normal => MainShadowColor,
                _ => MainShadowColor
            };
            shadowColor = shadowColor == Color.Transparent ? Color.FromArgb(0, 255, 255, 255) : shadowColor;

            Color bgColor = action switch
            {
                ButtonAction.Click => ClickBGColor,
                ButtonAction.Disabled => DisabledBGColor,
                ButtonAction.Highlight => HighlightBGColor,
                ButtonAction.Normal => MainBGColor,
                _ => MainBGColor
            };
            bgColor = bgColor == Color.Transparent ? Color.FromArgb(0, 255, 255, 255) : bgColor;
            bgColor = bgColor.IsEmpty ? copy.BackColor : bgColor;

            Color lineColor = action switch
            {
                ButtonAction.Click => ClickLineColor,
                ButtonAction.Disabled => DisabledLineColor,
                ButtonAction.Highlight => HighlightLineColor,
                ButtonAction.Normal => MainLineColor,
                _ => MainLineColor
            };
            lineColor = lineColor == Color.Transparent ? Color.FromArgb(0, 255, 255, 255) : lineColor;

            Color textColor = action switch
            {
                ButtonAction.Click => ClickTextColor,
                ButtonAction.Disabled => DisabledTextColor,
                ButtonAction.Highlight => HighlightTextColor,
                ButtonAction.Normal => MainTextColor,
                _ => MainTextColor
            };
            textColor = textColor == Color.Transparent ? Color.FromArgb(0, 255, 255, 255) : textColor;
            if (shadowWidth > 0)
            {
                //Draw shadow in the back
                using Brush shadowBrush = new SolidBrush(shadowColor);
                using Pen shadowPen = new Pen(shadowBrush, shadowWidth * 2);
                if (b.Parent is PictureBox || copy.BackColor == Color.FromArgb(0, 255, 255, 255))
                {
                    e.Graphics.DrawRoundedRectanglePart(shadowPen, rect[0], Btn_CornerRadius, Btn_ShadowLocation);
                }
                else
                {
                    e.Graphics.DrawRoundedRectangle(shadowPen, rect[0], Btn_CornerRadius);
                }
            }

            //Draw over any existing button graphics
            using Brush clearBrush = new SolidBrush((b.Parent is PictureBox) ? Color.FromArgb(0, 255, 255, 255) : ExtensionMethods.GetParentBackColor(b));
            e.Graphics.FillRoundedRectangle(clearBrush, rect[1], Btn_CornerRadius);

            //Draw background color of the button
            using Brush backBrush = new SolidBrush(bgColor);
            e.Graphics.FillRoundedRectangle(backBrush, rect[1], Btn_CornerRadius);

            //Draw outline of the button
            using Brush buttonBrush = new SolidBrush(lineColor);
            using Pen buttonPen = new Pen(buttonBrush, Btn_LineWidth);
            e.Graphics.DrawRoundedRectangle(buttonPen, rect[1], Btn_CornerRadius);

            //Draw text of the button
            //Button text is set to "" so that transparency will not show the original text.
            //I use a copy of the button to pull the text to draw.
            using Brush textBrush = new SolidBrush(textColor.IsEmpty ? b.ForeColor : textColor);
            Rectangle rectangleText = new Rectangle(
                rect[1].X + Btn_TextPadding.Left,
                rect[1].Y + Btn_TextPadding.Top,
                rect[1].Width - Btn_TextPadding.Right,
                rect[1].Height - Btn_TextPadding.Bottom
                );
            e.Graphics.DrawString(copy.Text, b.Font, textBrush, rectangleText, stringFormat);

        }
    }
}

internal static class ExtensionMethods
{
    public static void DrawRoundedRectangle(this Graphics graphics, Pen pen, Rectangle bounds, int cornerRadius)
    {
        using GraphicsPath path = RoundedRect(bounds, cornerRadius);
        graphics.DrawPath(pen, path);
    }

    public static void DrawRoundedRectanglePart(this Graphics graphics, Pen pen, Rectangle bounds, int cornerRadius, ShadowPosition position)
    {
        using GraphicsPath path = RoundedRectPart(bounds, cornerRadius, position);
        path.Flatten(new Matrix(), 0.12f);

        PointF prevP = new PointF();
        int total = path.PathPoints.Length;
        int count = 1;
        float penSize;

        int trim;
        if (position == ShadowPosition.Bottom || position == ShadowPosition.Top || position == ShadowPosition.Left || position == ShadowPosition.Right)
        {
            trim = 1;
        }
        else
        {
            trim = 2;
        }

        foreach (PointF p in path.PathPoints)
        {
            if (prevP.IsEmpty || count <= trim || count >= total - trim)
            {
                prevP = p; count++; continue;
            }

            if (count <= 3 || count >= total - 3)
            {
                penSize = 1;
            }
            else if (count <= 5 || count >= total - 5)

            {
                penSize = 2;
            }
            else if (count <= 8 || count >= total - 8)
            {
                penSize = 3;
            }
            else
            {
                penSize = pen.Width;
            }

            if (penSize > pen.Width)
            {
                penSize = pen.Width;
            }

            graphics.DrawLine(new Pen(pen.Color, penSize), prevP, p);
            prevP = p;
            count++;
        }
    }

    public static void FillRoundedRectangle(this Graphics graphics, Brush brush, Rectangle bounds, int cornerRadius)
    {
        using GraphicsPath path = RoundedRect(bounds, cornerRadius);
        graphics.FillPath(brush, path);
    }

    internal static Color GetParentBackColor(object sender)
    {
        Color c;
        try
        {
            if ((sender as dynamic)?.Parent != null)
            {
                c = (sender as dynamic)?.Parent.BackColor;
            }
            else
            {
                c = Color.White;
            }
        }
        catch
        {
            c = Color.White;
        }

        if (c == Color.Transparent)
        {
            try
            {
                if ((sender as dynamic)?.Parent != null)
                {
                    c = GetParentBackColor((sender as dynamic)?.Parent);
                }
                else
                {
                    c = Color.White;
                }
            }
            catch
            {
                c = Color.White;
            }
        }

        return c;
    }

    internal static GraphicsPath RoundedRect(Rectangle bounds, int radius)
    {
        int diameter = radius * 2;
        Size size = new Size(diameter, diameter);
        Rectangle arc = new Rectangle(bounds.Location, size);
        GraphicsPath path = new GraphicsPath { FillMode = FillMode.Alternate };

        if (radius == 0)
        {
            path.AddRectangle(bounds);
            return path;
        }

        path.AddArc(arc, 180, 90);

        arc.X = bounds.Right - diameter;
        path.AddArc(arc, 270, 90);

        arc.Y = bounds.Bottom - diameter;
        path.AddArc(arc, 0, 90);

        arc.X = bounds.Left;
        path.AddArc(arc, 90, 90);

        path.CloseFigure();
        return path;
    }

    internal static GraphicsPath RoundedRectPart(Rectangle bounds, int radius, ShadowPosition position)
    {
        int diameter = radius * 2;
        Size size = new Size(diameter, diameter);
        Rectangle arc = new Rectangle(bounds.Location, size);
        GraphicsPath path = new GraphicsPath { FillMode = FillMode.Alternate, };

        if (radius == 0)
        {
            path.AddRectangle(bounds);
            return path;
        }

        if (position == ShadowPosition.Right)
        {
            arc.X = bounds.Right - diameter;
            path.AddArc(arc, 270, 90);
            arc.Y = bounds.Bottom - diameter;
            path.AddArc(arc, 0, 90);
        }
        else if (position == ShadowPosition.BottomRight)
        {
            arc.X = bounds.Right - diameter;
            path.AddArc(arc, 270, 90);
            arc.Y = bounds.Bottom - diameter;
            path.AddArc(arc, 0, 90);
            arc.X = bounds.Left;
            path.AddArc(arc, 90, 90);
        }
        else if (position == ShadowPosition.Bottom)
        {
            arc.X = bounds.Right - diameter;
            arc.Y = bounds.Bottom - diameter;
            path.AddArc(arc, 0, 90);
            arc.X = bounds.Left;
            path.AddArc(arc, 90, 90);
        }
        else if (position == ShadowPosition.BottomLeft)
        {
            arc.X = bounds.Right - diameter;
            arc.Y = bounds.Bottom - diameter;
            path.AddArc(arc, 0, 90);
            arc.X = bounds.Left;
            path.AddArc(arc, 90, 90);
            arc.Y = bounds.Top;
            path.AddArc(arc, 180, 90);
        }
        else if (position == ShadowPosition.Left)
        {
            arc.Y = bounds.Bottom - diameter;
            arc.X = bounds.Left;
            path.AddArc(arc, 90, 90);
            arc.Y = bounds.Top;
            path.AddArc(arc, 180, 90);
        }
        else if (position == ShadowPosition.TopLeft)
        {
            arc.Y = bounds.Bottom - diameter;
            arc.X = bounds.Left;
            path.AddArc(arc, 90, 90);
            arc.Y = bounds.Top;
            path.AddArc(arc, 180, 90);
            arc.X = bounds.Right - diameter;
            path.AddArc(arc, 270, 90);
        }
        else if (position == ShadowPosition.Top)
        {
            path.AddArc(arc, 180, 90);
            arc.X = bounds.Right - diameter;
            path.AddArc(arc, 270, 90);
        }
        else if (position == ShadowPosition.TopRight)
        {
            path.AddArc(arc, 180, 90);
            arc.X = bounds.Right - diameter;
            path.AddArc(arc, 270, 90);
            arc.Y = bounds.Bottom - diameter;
            path.AddArc(arc, 0, 90);
        }

        return path;
    }
}

}

DrakeLam
  • 11
  • 3
-1

Short of painting it yourself, I don't think there's anything you can do. The base button paint logic isn't written as "show a blue highlight around such-and-such portion of whatever the window region is". Instead, it's written with the type of region it expects -- a rectangular one. So the base paint is always going to paint a rectangular image into a cropped shape. You'll have an easier time of such things in WPF.

Michael Gunter
  • 12,528
  • 1
  • 24
  • 58
  • Try to tell that to the client who expects the app to be beautiful, but doesn't want to buy a newer, more graphically capable computer. I don't know how to knock some sense into him. Just because a computer is a computer, it doesn't mean it's gonna be useful for everything. – soulblazer Feb 12 '15 at 20:01
  • 3
    Also, I notice that you (like the documentation at https://msdn.microsoft.com/en-us/library/system.windows.forms.control.region.aspx ) are setting the Region property in your Paint event handler. You probably want to only do this in a handler for the Layout event. The documentation has a poor example and I'm going to leave a comment there to state as much. :) – Michael Gunter Feb 12 '15 at 20:04
  • @Michael good catch, that's some terrible piece of advice from the docs... :-\ – Lucas Trzesniewski Feb 12 '15 at 20:08
-1

You can use a WebBrowser, make a button with HTML and CSS, then use webbrowser.DocumentText = "your html";

isaque
  • 158
  • 5