按钮 C# (WinForms) 中的圆角边缘

Rounded edges in button C# (WinForms)

您好,通过对这里和其他网站的一些研究,我制作了一个圆边按钮。

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

我遇到的问题是按钮的 "blue highlight":它显示在大部分按钮上,但没有显示在圆边上,所以我的按钮部分突出显示,部分未突出显示(在边缘)。我能做些什么来解决这个问题?谢谢。

PS: 我不会使用 WPF。该应用程序适用于一台非常旧的计算机;所以,请不要建议。此外,客户没有钱购买更新的计算机。

除了自己画,我觉得你也无能为力。基本按钮绘制逻辑未写为 "show a blue highlight around such-and-such portion of whatever the window region is"。相反,它是用它期望的区域类型编写的——一个矩形区域。所以底漆总是会将矩形图像绘制成裁剪后的形状。在 WPF 中,您会更轻松地完成这些事情。

这是一个快速的过程,您可能需要微调并优化很多细节..

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

显然,由于我们有一个 class,我们可以将 GraphicsPath 缓存在 class 变量中。当然,你可以选择颜色..

您可以使用 WebBrowser,用 HTML 和 CSS 创建一个按钮,然后使用 webbrowser.DocumentText = "your html";

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

这是对 TaW 答案的一个调整,可以更轻松地调整 borderRadius 和 borderThickness。如果边框和按钮背景色之间出现随机白色 space,则需要调整 m。

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

干杯!

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

}