Hello, through some research around here and other sites, I\'ve made a roun
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!
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.
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;
}
}
}
You can use a WebBrowser, make a button with HTML and CSS, then use 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));
}
}
}
}
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..