Related
In C#.NET I am trying to programmatically change the color of the border in a group box.
Update: This question was asked when I was working on a winforms system before we switched to .NET.
Just add paint event.
private void groupBox1_Paint(object sender, PaintEventArgs e)
{
GroupBox box = sender as GroupBox;
DrawGroupBox(box, e.Graphics, Color.Red, Color.Blue);
}
private void DrawGroupBox(GroupBox box, Graphics g, Color textColor, Color borderColor)
{
if (box != null)
{
Brush textBrush = new SolidBrush(textColor);
Brush borderBrush = new SolidBrush(borderColor);
Pen borderPen = new Pen(borderBrush);
SizeF strSize = g.MeasureString(box.Text, box.Font);
Rectangle rect = new Rectangle(box.ClientRectangle.X,
box.ClientRectangle.Y + (int)(strSize.Height / 2),
box.ClientRectangle.Width - 1,
box.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);
// Clear text and border
g.Clear(this.BackColor);
// Draw text
g.DrawString(box.Text, box.Font, textBrush, box.Padding.Left, 0);
// Drawing Border
//Left
g.DrawLine(borderPen, rect.Location, new Point(rect.X, rect.Y + rect.Height));
//Right
g.DrawLine(borderPen, new Point(rect.X + rect.Width, rect.Y), new Point(rect.X + rect.Width, rect.Y + rect.Height));
//Bottom
g.DrawLine(borderPen, new Point(rect.X, rect.Y + rect.Height), new Point(rect.X + rect.Width, rect.Y + rect.Height));
//Top1
g.DrawLine(borderPen, new Point(rect.X, rect.Y), new Point(rect.X + box.Padding.Left, rect.Y));
//Top2
g.DrawLine(borderPen, new Point(rect.X + box.Padding.Left + (int)(strSize.Width), rect.Y), new Point(rect.X + rect.Width, rect.Y));
}
}
Building on the previous answer, a better solution that includes the label for the group box:
groupBox1.Paint += PaintBorderlessGroupBox;
private void PaintBorderlessGroupBox(object sender, PaintEventArgs p)
{
GroupBox box = (GroupBox)sender;
p.Graphics.Clear(SystemColors.Control);
p.Graphics.DrawString(box.Text, box.Font, Brushes.Black, 0, 0);
}
You might want to adjust the x/y for the text, but for my use this is just right.
Just set the paint action on any object (not just buttons) to this method to draw a border.
private void UserControl1_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle, Color.Red, ButtonBorderStyle.Solid);
}
It still wont be pretty and rounded like the original, but it is much simpler.
FWIW, this is the implementation I used. It's a child of GroupBox but allows setting not only the BorderColor, but also the thickness of the border and the radius of the rounded corners. Also, you can set the amount of indent you want for the GroupBox label, and using a negative indent indents from the right side.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace BorderedGroupBox
{
public class BorderedGroupBox : GroupBox
{
private Color _borderColor = Color.Black;
private int _borderWidth = 2;
private int _borderRadius = 5;
private int _textIndent = 10;
public BorderedGroupBox() : base()
{
InitializeComponent();
this.Paint += this.BorderedGroupBox_Paint;
}
public BorderedGroupBox(int width, float radius, Color color) : base()
{
this._borderWidth = Math.Max(1,width);
this._borderColor = color;
this._borderRadius = Math.Max(0,radius);
InitializeComponent();
this.Paint += this.BorderedGroupBox_Paint;
}
public Color BorderColor
{
get => this._borderColor;
set
{
this._borderColor = value;
DrawGroupBox();
}
}
public int BorderWidth
{
get => this._borderWidth;
set
{
if (value > 0)
{
this._borderWidth = Math.Min(value, 10);
DrawGroupBox();
}
}
}
public int BorderRadius
{
get => this._borderRadius;
set
{ // Setting a radius of 0 produces square corners...
if (value >= 0)
{
this._borderRadius = value;
this.DrawGroupBox();
}
}
}
public int LabelIndent
{
get => this._textIndent;
set
{
this._textIndent = value;
this.DrawGroupBox();
}
}
private void BorderedGroupBox_Paint(object sender, PaintEventArgs e) =>
DrawGroupBox(e.Graphics);
private void DrawGroupBox() =>
this.DrawGroupBox(this.CreateGraphics());
private void DrawGroupBox(Graphics g)
{
Brush textBrush = new SolidBrush(this.ForeColor);
SizeF strSize = g.MeasureString(this.Text, this.Font);
Brush borderBrush = new SolidBrush(this.BorderColor);
Pen borderPen = new Pen(borderBrush,(float)this._borderWidth);
Rectangle rect = new Rectangle(this.ClientRectangle.X,
this.ClientRectangle.Y + (int)(strSize.Height / 2),
this.ClientRectangle.Width - 1,
this.ClientRectangle.Height - (int)(strSize.Height / 2) - 1);
Brush labelBrush = new SolidBrush(this.BackColor);
// Clear text and border
g.Clear(this.BackColor);
// Drawing Border (added "Fix" from Jim Fell, Oct 6, '18)
int rectX = (0 == this._borderWidth % 2) ? rect.X + this._borderWidth / 2 : rect.X + 1 + this._borderWidth / 2;
int rectHeight = (0 == this._borderWidth % 2) ? rect.Height - this._borderWidth / 2 : rect.Height - 1 - this._borderWidth / 2;
// NOTE DIFFERENCE: rectX vs rect.X and rectHeight vs rect.Height
g.DrawRoundedRectangle(borderPen, rectX, rect.Y, rect.Width, rectHeight, (float)this._borderRadius);
// Draw text
if (this.Text.Length > 0)
{
// Do some work to ensure we don't put the label outside
// of the box, regardless of what value is assigned to the Indent:
int width = (int)rect.Width, posX;
posX = (this._textIndent < 0) ? Math.Max(0-width,this._textIndent) : Math.Min(width, this._textIndent);
posX = (posX < 0) ? rect.Width + posX - (int)strSize.Width : posX;
g.FillRectangle(labelBrush, posX, 0, strSize.Width, strSize.Height);
g.DrawString(this.Text, this.Font, textBrush, posX, 0);
}
}
#region Component Designer generated code
/// <summary>Required designer variable.</summary>
private System.ComponentModel.IContainer components = null;
/// <summary>Clean up any resources being used.</summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
components.Dispose();
base.Dispose(disposing);
}
/// <summary>Required method for Designer support - Don't modify!</summary>
private void InitializeComponent() => components = new System.ComponentModel.Container();
#endregion
}
}
To make it work, you also have to extend the base Graphics class (Note: this is derived from some code I found on here once when I was trying to create a rounded-corners Panel control, but I can't find the original post to link here):
static class GraphicsExtension
{
private static GraphicsPath GenerateRoundedRectangle(
this Graphics graphics,
RectangleF rectangle,
float radius)
{
float diameter;
GraphicsPath path = new GraphicsPath();
if (radius <= 0.0F)
{
path.AddRectangle(rectangle);
path.CloseFigure();
return path;
}
else
{
if (radius >= (Math.Min(rectangle.Width, rectangle.Height)) / 2.0)
return graphics.GenerateCapsule(rectangle);
diameter = radius * 2.0F;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF arc = new RectangleF(rectangle.Location, sizeF);
path.AddArc(arc, 180, 90);
arc.X = rectangle.Right - diameter;
path.AddArc(arc, 270, 90);
arc.Y = rectangle.Bottom - diameter;
path.AddArc(arc, 0, 90);
arc.X = rectangle.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
}
return path;
}
private static GraphicsPath GenerateCapsule(
this Graphics graphics,
RectangleF baseRect)
{
float diameter;
RectangleF arc;
GraphicsPath path = new GraphicsPath();
try
{
if (baseRect.Width > baseRect.Height)
{
diameter = baseRect.Height;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 90, 180);
arc.X = baseRect.Right - diameter;
path.AddArc(arc, 270, 180);
}
else if (baseRect.Width < baseRect.Height)
{
diameter = baseRect.Width;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 180, 180);
arc.Y = baseRect.Bottom - diameter;
path.AddArc(arc, 0, 180);
}
else path.AddEllipse(baseRect);
}
catch { path.AddEllipse(baseRect); }
finally { path.CloseFigure(); }
return path;
}
/// <summary>
/// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
/// for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="width">Width of the rectangle to draw.</param>
/// <param name="height">Height of the rectangle to draw.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void DrawRoundedRectangle(
this Graphics graphics,
Pen pen,
float x,
float y,
float width,
float height,
float radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = graphics.GenerateRoundedRectangle(rectangle, radius);
SmoothingMode old = graphics.SmoothingMode;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawPath(pen, path);
graphics.SmoothingMode = old;
}
/// <summary>
/// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
/// for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="width">Width of the rectangle to draw.</param>
/// <param name="height">Height of the rectangle to draw.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void DrawRoundedRectangle(
this Graphics graphics,
Pen pen,
int x,
int y,
int width,
int height,
int radius)
{
graphics.DrawRoundedRectangle(
pen,
Convert.ToSingle(x),
Convert.ToSingle(y),
Convert.ToSingle(width),
Convert.ToSingle(height),
Convert.ToSingle(radius));
}
}
I'm not sure this applies to every case, but thanks to this thread, we quickly hooked into the Paint event programmatically using:
GroupBox box = new GroupBox();
[...]
box.Paint += delegate(object o, PaintEventArgs p)
{
p.Graphics.Clear(someColorHere);
};
Cheers!
I have achieved same border with something which might be simpler to understand for newbies:
private void groupSchitaCentru_Paint(object sender, PaintEventArgs e)
{
Pen blackPen = new Pen(Color.Black, 2);
Point pointTopLeft = new Point(0, 7);
Point pointBottomLeft = new Point(0, groupSchitaCentru.ClientRectangle.Height);
Point pointTopRight = new Point(groupSchitaCentru.ClientRectangle.Width, 7);
Point pointBottomRight = new Point(groupSchitaCentru.ClientRectangle.Width, groupSchitaCentru.ClientRectangle.Height);
e.Graphics.DrawLine(blackPen, pointTopLeft, pointBottomLeft);
e.Graphics.DrawLine(blackPen, pointTopLeft, pointTopRight);
e.Graphics.DrawLine(blackPen, pointBottomRight, pointTopRight);
e.Graphics.DrawLine(blackPen, pointBottomLeft, pointBottomRight);
}
Set the Paint event on the GroupBox control. In this example the name of my control is "groupSchitaCentru". One needs this event because of its parameter e.
Set up a pen object by making use of the System.Drawing.Pen class : https://msdn.microsoft.com/en-us/library/f956fzw1(v=vs.110).aspx
Set the points which represent the corners of the rectangle represented by the control. Used the property ClientRectangle of the the control to get its dimensions.
I used for TopLeft (0,7) because I want to respect the borders of the control, and draw the line about the its text.
To get more information about the coordinates system walk here : https://learn.microsoft.com/en-us/dotnet/framework/winforms/windows-forms-coordinates
I do not know, may be it helps someone looking to achieve this border adjustment thing.
This tweak to Jim Fell's code placed the borders a little better for me, but it's too long to add as a comment
...
Rectangle rect = new Rectangle(this.ClientRectangle.X,
this.ClientRectangle.Y + (int)(strSize.Height / 2),
this.ClientRectangle.Width,
this.ClientRectangle.Height - (int)(strSize.Height / 2));
Brush labelBrush = new SolidBrush(this.BackColor);
// Clear text and border
g.Clear(this.BackColor);
int drawX = rect.X;
int drawY = rect.Y;
int drawWidth = rect.Width;
int drawHeight = rect.Height;
if (this._borderWidth > 0)
{
drawX += this._borderWidth / 2;
drawY += this._borderWidth / 2;
drawWidth -= this._borderWidth;
drawHeight -= this._borderWidth;
if (this._borderWidth % 2 == 0)
{
drawX -= 1;
drawWidth += 1;
drawY -= 1;
drawHeight += 1;
}
}
g.DrawRoundedRectangle(borderPen, drawX, drawY, drawWidth, drawHeight, (float)this._borderRadius);
I have followed this tutorial in order to create a rounded panel. The code in the tutorial is in vb but I was able to convert it to C# so here is my code:
public class SPanel : Panel
{
Pen pen;
float penWidth = 2.0f;
int _edge = 20;
Color _borderColor = Color.White;
public int Edge
{
get
{
return _edge;
}
set
{
_edge = value;
Invalidate();
}
}
public Color BorderColor
{
get
{
return _borderColor;
}
set
{
_borderColor = value;
pen = new Pen(_borderColor, penWidth);
Invalidate();
}
}
public SPanel()
{
pen = new Pen(_borderColor, penWidth);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ExtendedDraw(e);
//DrawBorder(e.Graphics);
}
private void ExtendedDraw(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
GraphicsPath path = new GraphicsPath();
path.StartFigure();
path.StartFigure();
path.AddArc(GetLeftUpper(Edge), 180, 90);
path.AddLine(Edge, 0, Width - Edge, 0);
path.AddArc(GetRightUpper(Edge), 270, 90);
path.AddLine(Width, Edge, Width, Height - Edge);
path.AddArc(GetRightLower(Edge), 0, 90);
path.AddLine(Width - Edge, Height, Edge, Height);
path.AddArc(GetLeftLower(Edge), 90, 90);
path.AddLine(0, Height - Edge, 0, Edge);
path.CloseFigure();
Region = new Region(path);
}
Rectangle GetLeftUpper(int e)
{
return new Rectangle(0, 0, e, e);
}
Rectangle GetRightUpper(int e)
{
return new Rectangle(Width - e, 0, e, e);
}
Rectangle GetRightLower(int e)
{
return new Rectangle(Width - e, Height - e, e, e);
}
Rectangle GetLeftLower(int e)
{
return new Rectangle(0, Height - e, e, e);
}
void DrawSingleBorder(Graphics graphics)
{
graphics.DrawArc(pen, new Rectangle(0, 0, Edge, Edge), 180, 90);
graphics.DrawArc(pen, new Rectangle(Width - Edge -1, -1, Edge, Edge), 270, 90);
graphics.DrawArc(pen, new Rectangle(Width - Edge - 1, Height - Edge - 1, Edge, Edge), 0, 90);
graphics.DrawArc(pen, new Rectangle(0, Height - Edge - 1, Edge, Edge), 90, 90);
graphics.DrawRectangle(pen, 0.0F, 0.0F, Width - 1, Height - 1);
}
void DrawBorder(Graphics graphics)
{
DrawSingleBorder(graphics);
}
}
I did not use the border however the result is the same. Here is a ss:
I thought smoothing with anti alias would do the trick but I guess i was wrong. The question is how can I smooth the edges?
I was able to solve this by following this link. I just downloaded the sample project and created a new panel. Copied what he had on Form's onpaint to new panel's onpaint and now I have smooth edges.
public class SPanel : Panel
{
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.FillRoundedRectangle(new SolidBrush(Color.White), 10, 10, this.Width - 40, this.Height - 60, 10);
SolidBrush brush = new SolidBrush(
Color.White
);
g.FillRoundedRectangle(brush, 12, 12, this.Width - 44, this.Height - 64, 10);
g.DrawRoundedRectangle(new Pen(ControlPaint.Light(Color.White, 0.00f)), 12, 12, this.Width - 44, this.Height - 64, 10);
g.FillRoundedRectangle(new SolidBrush(Color.White), 12, 12 + ((this.Height - 64) / 2), this.Width - 44, (this.Height - 64)/2, 10);
}
}
Here is his GraphicsExtension class if link ever get broken.
static class GraphicsExtension
{
private static GraphicsPath GenerateRoundedRectangle(
this Graphics graphics,
RectangleF rectangle,
float radius)
{
float diameter;
GraphicsPath path = new GraphicsPath();
if (radius <= 0.0F)
{
path.AddRectangle(rectangle);
path.CloseFigure();
return path;
}
else
{
if (radius >= (Math.Min(rectangle.Width, rectangle.Height)) / 2.0)
return graphics.GenerateCapsule(rectangle);
diameter = radius * 2.0F;
SizeF sizeF = new SizeF(diameter, diameter);
RectangleF arc = new RectangleF(rectangle.Location, sizeF);
path.AddArc(arc, 180, 90);
arc.X = rectangle.Right - diameter;
path.AddArc(arc, 270, 90);
arc.Y = rectangle.Bottom - diameter;
path.AddArc(arc, 0, 90);
arc.X = rectangle.Left;
path.AddArc(arc, 90, 90);
path.CloseFigure();
}
return path;
}
private static GraphicsPath GenerateCapsule(
this Graphics graphics,
RectangleF baseRect)
{
float diameter;
RectangleF arc;
GraphicsPath path = new GraphicsPath();
try
{
if (baseRect.Width > baseRect.Height)
{
diameter = baseRect.Height;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 90, 180);
arc.X = baseRect.Right - diameter;
path.AddArc(arc, 270, 180);
}
else if (baseRect.Width < baseRect.Height)
{
diameter = baseRect.Width;
SizeF sizeF = new SizeF(diameter, diameter);
arc = new RectangleF(baseRect.Location, sizeF);
path.AddArc(arc, 180, 180);
arc.Y = baseRect.Bottom - diameter;
path.AddArc(arc, 0, 180);
}
else path.AddEllipse(baseRect);
}
catch { path.AddEllipse(baseRect); }
finally { path.CloseFigure(); }
return path;
}
/// <summary>
/// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
/// for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="width">Width of the rectangle to draw.</param>
/// <param name="height">Height of the rectangle to draw.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void DrawRoundedRectangle(
this Graphics graphics,
Pen pen,
float x,
float y,
float width,
float height,
float radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = graphics.GenerateRoundedRectangle(rectangle, radius);
SmoothingMode old = graphics.SmoothingMode;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawPath(pen, path);
graphics.SmoothingMode = old;
}
/// <summary>
/// Draws a rounded rectangle specified by a pair of coordinates, a width, a height and the radius
/// for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Pen that determines the color, width and style of the rectangle.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to draw.</param>
/// <param name="width">Width of the rectangle to draw.</param>
/// <param name="height">Height of the rectangle to draw.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void DrawRoundedRectangle(
this Graphics graphics,
Pen pen,
int x,
int y,
int width,
int height,
int radius)
{
graphics.DrawRoundedRectangle(
pen,
Convert.ToSingle(x),
Convert.ToSingle(y),
Convert.ToSingle(width),
Convert.ToSingle(height),
Convert.ToSingle(radius));
}
/// <summary>
/// Fills the interior of a rounded rectangle specified by a pair of coordinates, a width, a height
/// and the radius for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Brush that determines the characteristics of the fill.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to fill.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to fill.</param>
/// <param name="width">Width of the rectangle to fill.</param>
/// <param name="height">Height of the rectangle to fill.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void FillRoundedRectangle(
this Graphics graphics,
Brush brush,
float x,
float y,
float width,
float height,
float radius)
{
RectangleF rectangle = new RectangleF(x, y, width, height);
GraphicsPath path = graphics.GenerateRoundedRectangle(rectangle, radius);
SmoothingMode old = graphics.SmoothingMode;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.FillPath(brush, path);
graphics.SmoothingMode = old;
}
/// <summary>
/// Fills the interior of a rounded rectangle specified by a pair of coordinates, a width, a height
/// and the radius for the arcs that make the rounded edges.
/// </summary>
/// <param name="brush">System.Drawing.Brush that determines the characteristics of the fill.</param>
/// <param name="x">The x-coordinate of the upper-left corner of the rectangle to fill.</param>
/// <param name="y">The y-coordinate of the upper-left corner of the rectangle to fill.</param>
/// <param name="width">Width of the rectangle to fill.</param>
/// <param name="height">Height of the rectangle to fill.</param>
/// <param name="radius">The radius of the arc used for the rounded edges.</param>
public static void FillRoundedRectangle(
this Graphics graphics,
Brush brush,
int x,
int y,
int width,
int height,
int radius)
{
graphics.FillRoundedRectangle(
brush,
Convert.ToSingle(x),
Convert.ToSingle(y),
Convert.ToSingle(width),
Convert.ToSingle(height),
Convert.ToSingle(radius));
}
}
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
int nLeftRect, // x-coordinate of upper-left corner
int nTopRect, // y-coordinate of upper-left corner
int nRightRect, // x-coordinate of lower-right corner
int nBottomRect, // y-coordinate of lower-right corner
int nWidthEllipse, // height of ellipse
int nHeightEllipse // width of ellipse
);
public Form1()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 20, 20));
}
}
}
I found solution internet and tried and success! Hope help you
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace windowsFormsApp
{
public partial class Form2 : Form
{
[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")]
private static extern IntPtr CreateRoundRectRgn
(
int nLeftRect,
int nTopRect,
int nRightRect,
int nBottomRect,
int nWidthEllipse,
int nHeightEllipse
);
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
panel1.Region = Region.FromHrgn(CreateRoundRectRgn(0, 0, panel1.Width,
panel1.Height, 30, 30));
}
}
}
I was also trying to do the same and finally I did this by creating Custom Control.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace your.namespace.here
{
public class CustomPanel : System.Windows.Forms.Panel
{
private System.Windows.Forms.Panel panel;
private Color borderColor = Color.MediumSlateBlue;
private Color borderFocusColor = Color.HotPink;
private int borderSize = 2;
private bool underlinedStyle = false;
private bool isFocused = false;
private int borderRadius = 0;
public Color BorderColor
{
get { return borderColor; }
set
{
borderColor = value;
this.Invalidate();
}
}
public Color BorderFocusColor
{
get { return borderFocusColor; }
set { borderFocusColor = value; }
}
public int BorderSize
{
get { return borderSize; }
set
{
if (value >= 1)
{
borderSize = value;
this.Invalidate();
}
}
}
public bool UnderlinedStyle
{
get { return underlinedStyle; }
set
{
underlinedStyle = value;
this.Invalidate();
}
}
public override Color ForeColor
{
get { return base.ForeColor; }
set
{
base.ForeColor = value;
panel.ForeColor = value;
}
}
public int BorderRadius
{
get { return borderRadius; }
set
{
if (value >= 0)
{
borderRadius = value;
this.Invalidate();//Redraw control
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics graph = e.Graphics;
if (borderRadius > 1)//Rounded TextBox
{
//-Fields
var rectBorderSmooth = this.ClientRectangle;
var rectBorder = Rectangle.Inflate(rectBorderSmooth, -borderSize, -borderSize);
int smoothSize = borderSize > 0 ? borderSize : 1;
using (GraphicsPath pathBorderSmooth = GetFigurePath(rectBorderSmooth, borderRadius))
using (GraphicsPath pathBorder = GetFigurePath(rectBorder, borderRadius - borderSize))
using (Pen penBorderSmooth = new Pen(this.Parent.BackColor, smoothSize))
using (Pen penBorder = new Pen(borderColor, borderSize))
{
//-Drawing
this.Region = new Region(pathBorderSmooth);//Set the rounded region of UserControl
if (borderRadius > 15) SetTextBoxRoundedRegion();//Set the rounded region of TextBox component
graph.SmoothingMode = SmoothingMode.AntiAlias;
penBorder.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
if (isFocused) penBorder.Color = borderFocusColor;
if (underlinedStyle) //Line Style
{
//Draw border smoothing
graph.DrawPath(penBorderSmooth, pathBorderSmooth);
//Draw border
graph.SmoothingMode = SmoothingMode.None;
graph.DrawLine(penBorder, 0, this.Height - 1, this.Width, this.Height - 1);
}
else //Normal Style
{
//Draw border smoothing
graph.DrawPath(penBorderSmooth, pathBorderSmooth);
//Draw border
graph.DrawPath(penBorder, pathBorder);
}
}
}
}
private void SetTextBoxRoundedRegion()
{
GraphicsPath pathTxt;
pathTxt = GetFigurePath(panel.ClientRectangle, borderSize * 2);
panel.Region = new Region(pathTxt);
pathTxt.Dispose();
}
private GraphicsPath GetFigurePath(Rectangle rect, int radius)
{
GraphicsPath path = new GraphicsPath();
float curveSize = radius * 2F;
path.StartFigure();
path.AddArc(rect.X, rect.Y, curveSize, curveSize, 180, 90);
path.AddArc(rect.Right - curveSize, rect.Y, curveSize, curveSize, 270, 90);
path.AddArc(rect.Right - curveSize, rect.Bottom - curveSize, curveSize, curveSize, 0, 90);
path.AddArc(rect.X, rect.Bottom - curveSize, curveSize, curveSize, 90, 90);
path.CloseFigure();
return path;
}
}
}
the output is like:
Note: this code is only for Custom Panel.
Mine is an alternative solution that requires no code or pre-paid modules.
Start by creating a round edged container on MS PowerPoint or MS Paint for example (Draw Rectangle with rounded corners, you can even add shadows if you want).
Take a screenshot of it or use snipping tool and save it as a .png; Then go to any online tool to make the background transparent.
Download the new image and use it on a pictureBox on your C# .NET solution and there, you have your own HD rounded background with shadow effects (Use the Anchor and Dock properties to give it the effects and positions that you want on your Form).
In your code:
private void ExtendedDraw(PaintEventArgs e)
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, Color.White, Color.White, 90); //here you need your target rectangle
GraphicsPath path = new GraphicsPath();
path.StartFigure();
path.StartFigure();
path.AddArc(GetLeftUpper(Edge), 180, 90);
path.AddLine(Edge, 0, Width - Edge, 0);
path.AddArc(GetRightUpper(Edge), 270, 90);
path.AddLine(Width, Edge, Width, Height - Edge);
path.AddArc(GetRightLower(Edge), 0, 90);
path.AddLine(Width - Edge, Height, Edge, Height);
path.AddArc(GetLeftLower(Edge), 90, 90);
path.AddLine(0, Height - Edge, 0, Edge);
path.CloseFigure();
e.Graphics.FillPath(brush, path);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
What i want to do is to show in the middle of the progressBar a text in red and that the text will blink until the progressBar operation end getting to 100%.
The text to display is: Processing Please Wait
In the end in the background completed event just to stop the blinking and display instead: Processing Please Wait to display: Operation Ended or something like that maybe: Process Ended or Finished.
I forgot to mention that my progressBar1 i'm using is a costum UserControl i did and not the regular progressBar for example after dragging this to my form1 designer this progressBar dosen't have the Increment property.
using System;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace VistaStyleProgressBar
{
/// <summary>
/// A replacement for the default ProgressBar control.
/// </summary>
[DefaultEvent("ValueChanged")]
public class ProgressBar : System.Windows.Forms.UserControl
{
#region - Designer -
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Create the control and initialize it.
/// </summary>
public ProgressBar()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.BackColor = Color.Transparent;
if (!InDesignMode())
{
mGlowAnimation.Tick += new EventHandler(mGlowAnimation_Tick);
mGlowAnimation.Interval = 15;
if (Value < MaxValue) { mGlowAnimation.Start(); }
}
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
#region - Component Designer -
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// ProgressBar
//
this.Name = "ProgressBar";
this.Size = new System.Drawing.Size(264, 32);
this.Paint += new PaintEventHandler(ProgressBar_Paint);
}
#endregion
#endregion
#region - Properties -
private int mGlowPosition = -325;
private Timer mGlowAnimation = new Timer();
#region - Value -
private int mValue = 0;
/// <summary>
/// The value that is displayed on the progress bar.
/// </summary>
[Category("Value"),
DefaultValue(0),
Description("The value that is displayed on the progress bar.")]
public int Value
{
get { return mValue; }
set
{
if (value > MaxValue || value < MinValue) { return; }
mValue = value;
if (value < MaxValue) { mGlowAnimation.Start(); }
if (value == MaxValue) { mGlowAnimation.Stop(); }
ValueChangedHandler vc = ValueChanged;
if (vc != null) { vc(this, new System.EventArgs()); }
this.Invalidate();
}
}
private int mMaxValue = 100;
/// <summary>
/// The maximum value for the Value property.
/// </summary>
[Category("Value"),
DefaultValue(100),
Description("The maximum value for the Value property.")]
public int MaxValue
{
get { return mMaxValue; }
set
{
mMaxValue = value;
if (value > MaxValue) { Value = MaxValue; }
if (Value < MaxValue) { mGlowAnimation.Start(); }
MaxChangedHandler mc = MaxChanged;
if (mc != null) { mc(this, new System.EventArgs()); }
this.Invalidate();
}
}
private int mMinValue = 0;
/// <summary>
/// The minimum value for the Value property.
/// </summary>
[Category("Value"),
DefaultValue(0),
Description("The minimum value for the Value property.")]
public int MinValue
{
get { return mMinValue; }
set
{
mMinValue = value;
if (value < MinValue) { Value = MinValue; }
MinChangedHandler mc = MinChanged;
if (mc != null) { mc(this, new System.EventArgs()); }
this.Invalidate();
}
}
#endregion
#region - Bar -
private Color mStartColor = Color.FromArgb(0, 211, 40);
/// <summary>
/// The start color for the progress bar.
/// 210, 000, 000 = Red
/// 210, 202, 000 = Yellow
/// 000, 163, 211 = Blue
/// 000, 211, 040 = Green
/// </summary>
[Category("Bar"),
DefaultValue(typeof(Color), "210, 0, 0"),
Description("The start color for the progress bar." +
"210, 000, 000 = Red\n" +
"210, 202, 000 = Yellow\n" +
"000, 163, 211 = Blue\n" +
"000, 211, 040 = Green\n")]
public Color StartColor
{
get { return mStartColor; }
set { mStartColor = value; this.Invalidate(); }
}
private Color mEndColor = Color.FromArgb(0, 211, 40);
/// <summary>
/// The end color for the progress bar.
/// 210, 000, 000 = Red
/// 210, 202, 000 = Yellow
/// 000, 163, 211 = Blue
/// 000, 211, 040 = Green
/// </summary>
[Category("Bar"),
DefaultValue(typeof(Color), "0, 211, 40"),
Description("The end color for the progress bar." +
"210, 000, 000 = Red\n" +
"210, 202, 000 = Yellow\n" +
"000, 163, 211 = Blue\n" +
"000, 211, 040 = Green\n")]
public Color EndColor
{
get { return mEndColor; }
set { mEndColor = value; this.Invalidate(); }
}
#endregion
#region - Highlights and Glows -
private Color mHighlightColor = Color.White;
/// <summary>
/// The color of the highlights.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "White"),
Description("The color of the highlights.")]
public Color HighlightColor
{
get { return mHighlightColor; }
set { mHighlightColor = value; this.Invalidate(); }
}
private Color mBackgroundColor = Color.FromArgb(201, 201, 201);
/// <summary>
/// The color of the background.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "201,201,201"),
Description("The color of the background.")]
public Color BackgroundColor
{
get { return mBackgroundColor; }
set { mBackgroundColor = value; this.Invalidate(); }
}
private bool mAnimate = true;
/// <summary>
/// Whether the glow is animated.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(bool), "true"),
Description("Whether the glow is animated or not.")]
public bool Animate
{
get { return mAnimate; }
set
{
mAnimate = value;
if (value) { mGlowAnimation.Start(); } else { mGlowAnimation.Stop(); }
this.Invalidate();
}
}
private Color mGlowColor = Color.FromArgb(150, 255, 255, 255);
/// <summary>
/// The color of the glow.
/// </summary>
[Category("Highlights and Glows"),
DefaultValue(typeof(Color), "150, 255, 255, 255"),
Description("The color of the glow.")]
public Color GlowColor
{
get { return mGlowColor; }
set { mGlowColor = value; this.Invalidate(); }
}
#endregion
#endregion
#region - Drawing -
private void DrawBackground(Graphics g)
{
Rectangle r = this.ClientRectangle; r.Width--; r.Height--;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.FillPath(new SolidBrush(this.BackgroundColor), rr);
}
private void DrawBackgroundShadows(Graphics g)
{
Rectangle lr = new Rectangle(2, 2, 10, this.Height - 5);
LinearGradientBrush lg = new LinearGradientBrush(lr, Color.FromArgb(30, 0, 0, 0),
Color.Transparent,
LinearGradientMode.Horizontal);
lr.X--;
g.FillRectangle(lg, lr);
Rectangle rr = new Rectangle(this.Width - 12, 2, 10, this.Height - 5);
LinearGradientBrush rg = new LinearGradientBrush(rr, Color.Transparent,
Color.FromArgb(20, 0, 0, 0),
LinearGradientMode.Horizontal);
g.FillRectangle(rg, rr);
}
private void DrawBar(Graphics g)
{
Rectangle r = new Rectangle(1, 2, this.Width - 3, this.Height - 3);
r.Width = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width);
g.FillRectangle(new SolidBrush(GetIntermediateColor()), r);
}
private void DrawBarShadows(Graphics g)
{
Rectangle lr = new Rectangle(1, 2, 15, this.Height - 3);
LinearGradientBrush lg = new LinearGradientBrush(lr, Color.White, Color.White,
LinearGradientMode.Horizontal);
ColorBlend lc = new ColorBlend(3);
lc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
lc.Positions = new float[] { 0.0F, 0.2F, 1.0F };
lg.InterpolationColors = lc;
lr.X--;
g.FillRectangle(lg, lr);
Rectangle rr = new Rectangle(this.Width - 3, 2, 15, this.Height - 3);
rr.X = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width) - 14;
LinearGradientBrush rg = new LinearGradientBrush(rr, Color.Black, Color.Black,
LinearGradientMode.Horizontal);
ColorBlend rc = new ColorBlend(3);
rc.Colors = new Color[] { Color.Transparent, Color.FromArgb(40, 0, 0, 0), Color.Transparent };
rc.Positions = new float[] { 0.0F, 0.8F, 1.0F };
rg.InterpolationColors = rc;
g.FillRectangle(rg, rr);
}
private void DrawHighlight(Graphics g)
{
Rectangle tr = new Rectangle(1, 1, this.Width - 1, 6);
GraphicsPath tp = RoundRect(tr, 2, 2, 0, 0);
g.SetClip(tp);
LinearGradientBrush tg = new LinearGradientBrush(tr, Color.White,
Color.FromArgb(128, Color.White),
LinearGradientMode.Vertical);
g.FillPath(tg, tp);
g.ResetClip();
Rectangle br = new Rectangle(1, this.Height - 8, this.Width - 1, 6);
GraphicsPath bp = RoundRect(br, 0, 0, 2, 2);
g.SetClip(bp);
LinearGradientBrush bg = new LinearGradientBrush(br, Color.Transparent,
Color.FromArgb(100, this.HighlightColor),
LinearGradientMode.Vertical);
g.FillPath(bg, bp);
g.ResetClip();
}
private void DrawInnerStroke(Graphics g)
{
Rectangle r = this.ClientRectangle;
r.X++; r.Y++; r.Width -= 3; r.Height -= 3;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.DrawPath(new Pen(Color.FromArgb(100, Color.White)), rr);
}
private void DrawGlow(Graphics g)
{
Rectangle r = new Rectangle(mGlowPosition, 0, 60, this.Height);
LinearGradientBrush lgb = new LinearGradientBrush(r, Color.White, Color.White,
LinearGradientMode.Horizontal);
ColorBlend cb = new ColorBlend(4);
cb.Colors = new Color[] { Color.Transparent, this.GlowColor, this.GlowColor, Color.Transparent };
cb.Positions = new float[] { 0.0F, 0.5F, 0.6F, 1.0F };
lgb.InterpolationColors = cb;
Rectangle clip = new Rectangle(1, 2, this.Width - 3, this.Height - 3);
clip.Width = (int)(Value * 1.0F / (MaxValue - MinValue) * this.Width);
g.SetClip(clip);
g.FillRectangle(lgb, r);
g.ResetClip();
}
private void DrawOuterStroke(Graphics g)
{
Rectangle r = this.ClientRectangle; r.Width--; r.Height--;
GraphicsPath rr = RoundRect(r, 2, 2, 2, 2);
g.DrawPath(new Pen(Color.FromArgb(178, 178, 178)), rr);
}
#endregion
#region - Functions -
private GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
{
float x = r.X, y = r.Y, w = r.Width, h = r.Height;
GraphicsPath rr = new GraphicsPath();
rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
rr.AddLine(x + r1, y, x + w - r2, y);
rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
rr.AddLine(x + w, y + r2, x + w, y + h - r3);
rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
rr.AddLine(x + w - r3, y + h, x + r4, y + h);
rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
rr.AddLine(x, y + h - r4, x, y + r1);
return rr;
}
private bool InDesignMode()
{
return (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}
private Color GetIntermediateColor()
{
Color c = this.StartColor;
Color c2 = this.EndColor;
float pc = this.Value * 1.0F / (this.MaxValue - this.MinValue);
int ca = c.A, cr = c.R, cg = c.G, cb = c.B;
int c2a = c2.A, c2r = c2.R, c2g = c2.G, c2b = c2.B;
int a = (int)Math.Abs(ca + (ca - c2a) * pc);
int r = (int)Math.Abs(cr - ((cr - c2r) * pc));
int g = (int)Math.Abs(cg - ((cg - c2g) * pc));
int b = (int)Math.Abs(cb - ((cb - c2b) * pc));
if (a > 255) { a = 255; }
if (r > 255) { r = 255; }
if (g > 255) { g = 255; }
if (b > 255) { b = 255; }
return (Color.FromArgb(a, r, g, b));
}
#endregion
#region - Other -
private void ProgressBar_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
DrawBackground(e.Graphics);
DrawBackgroundShadows(e.Graphics);
DrawBar(e.Graphics);
DrawBarShadows(e.Graphics);
DrawHighlight(e.Graphics);
DrawInnerStroke(e.Graphics);
DrawGlow(e.Graphics);
DrawOuterStroke(e.Graphics);
}
private void mGlowAnimation_Tick(object sender, EventArgs e)
{
if (this.Animate)
{
mGlowPosition += 4;
if (mGlowPosition > this.Width)
{
mGlowPosition = -300;
}
this.Invalidate();
}
else
{
mGlowAnimation.Stop();
mGlowPosition = -320;
}
}
#endregion
#region - Events -
/// <summary>
/// When the Value property is changed.
/// </summary>
public delegate void ValueChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the Value property is changed.
/// </summary>
public event ValueChangedHandler ValueChanged;
/// <summary>
/// When the MinValue property is changed.
/// </summary>
public delegate void MinChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the MinValue property is changed.
/// </summary>
public event MinChangedHandler MinChanged;
/// <summary>
/// When the MaxValue property is changed.
/// </summary>
public delegate void MaxChangedHandler(object sender, EventArgs e);
/// <summary>
/// When the MaxValue property is changed.
/// </summary>
public event MaxChangedHandler MaxChanged;
#endregion
}
}
I tried this case the Increment property not exist so it's a problem.
private void timer2_Tick(object sender, EventArgs e)
{
progressBar1.Increment(+1);
int percent = progressBar1.Value;
progressBar1
.CreateGraphics()
.DrawString(
percent.ToString() + "%",
new Font("Arial", (float)8.25, FontStyle.Regular),
Brushes.Black,
new PointF(progressBar1.Width / 2 - 10,
progressBar1.Height / 2 - 7)
);
if (progressBar1.Value >= 99)
{
timer2.Stop();
this.Close();
}
}
What I would do is make a label with the desired text and then add to the background worker:
if ( progressBar1.Value == 100% )
{
label1.Text = "Process finished";
}
If you cant see the label and it is hidden behind the processBar change the location of the label to front
Hope I could help!
Edit: This link should explain the blinking event How to implement a blinking label on a form
Have wrote no blinking/flickering TextProgressBar
You can find source code here: https://github.com/ukushu/TextProgressBar
Sample:
How can I get HBRUSH from Brush and HPEN from Pen ?
I wonder is there any connection between the two sides ?
(I want to use WinApi functions that are not implemented in .NET's System.Drawing such as DrawRoundRect/CreateRoundRectRgn and I want to use brushes from .NET for that instead of creating them on my own.)
The Brush class does have a private field called nativeBrush which holds the HBRUSH handle as an IntPtr.
Because it's a private field, it could change with any revision to .Net, but if you don't mind using some dodgy, brittle reflection to get at its value, you could do something nasty like this:
Brush brush = ...the brush that you want to get at the handle for
FieldInfo field = typeof(Brush).GetField("nativeBrush",BindingFlags.NonPublic|BindingFlags.Instance);
IntPtr hbrush = (IntPtr)field.GetValue(brush);
There is a similar field for Pen called nativePen which you can access using similar reflection code.
However, if you can use GraphicsPath as Don shows above, that would be much less risky.
Also check out this article on creating rounded rectangles using GraphicsPath
I don't have the original source any longer, might even have been a SO item. At any rate, here's a class someone provided a while back that I use:
/// <summary>
/// Collection of often-used classes and methods for easy access.
/// </summary>
public class RoundedDrawing
{
private static GraphicsPath GetRoundedRectanglePath(Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
{
GraphicsPath path = new GraphicsPath();
path.AddLine(x + radius, y, x + width - radius, y);
if (radius > 0)
path.AddArc(x + width - 2 * radius, y, 2 * radius, 2 * radius, 270.0f, 90.0f);
path.AddLine(x + width, y + radius, x + width, y + height - radius);
if (radius > 0)
path.AddArc(x + width - 2 * radius, y + height - 2 * radius, 2 * radius, 2 * radius, 0.0f, 90.0f);
path.AddLine(x + width - radius, y + height, x + radius, y + height);
if (radius > 0)
path.AddArc(x, y + height - 2 * radius, 2 * radius, 2 * radius, 90.0f, 90.0f);
path.AddLine(x, y + height - radius, x, y + radius);
if (radius > 0)
path.AddArc(x, y, 2 * radius, 2 * radius, 180.0f, 90.0f);
return path;
}
/// <summary>
/// Fills the interior of a rounded rectangle.
/// </summary>
public static void FillRoundedRectangle(Graphics graphics, Brush brush, float x, float y, float width, float height, float radius)
{
FillRoundedRectangle(graphics, brush, (Int32)x, (Int32)y, (Int32)width, (Int32)height, (Int32)radius);
}
/// <summary>
/// Fills the interior of a rounded rectangle.
/// </summary>
public static void FillRoundedRectangle(Graphics graphics, Brush brush, Rectangle rect, Int32 radius)
{
FillRoundedRectangle(graphics, brush, rect.Left, rect.Top, rect.Width, rect.Height, radius);
}
/// <summary>
/// Fills the interior of a rounded rectangle.
/// </summary>
public static void FillRoundedRectangle(Graphics graphics, Brush brush, RectangleF rect, float radius)
{
FillRoundedRectangle(graphics, brush, (Int32)rect.Left, (Int32)rect.Top, (Int32)rect.Width, (Int32)rect.Height, (Int32)radius);
}
/// <summary>
/// Fills the interior of a rounded rectangle.
/// </summary>
public static void FillRoundedRectangle(Graphics graphics, Brush brush, Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
{
using (GraphicsPath path = GetRoundedRectanglePath(x, y, width, height, radius))
graphics.FillPath(brush, path);
}
/// <summary>
/// Draws the outline of a rounded rectangle.
/// </summary>
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, float x, float y, float width, float height, float radius)
{
DrawRoundedRectangle(graphics, pen, (Int32)x, (Int32)y, (Int32)width, (Int32)height, (Int32)radius);
}
/// <summary>
/// Draws the outline of a rounded rectangle.
/// </summary>
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, Rectangle rect, Int32 radius)
{
DrawRoundedRectangle(graphics, pen, rect.Left, rect.Top, rect.Width, rect.Height, radius);
}
/// <summary>
/// Draws the outline of a rounded rectangle.
/// </summary>
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, RectangleF rect, float radius)
{
DrawRoundedRectangle(graphics, pen, (Int32)rect.Left, (Int32)rect.Top, (Int32)rect.Width, (Int32)rect.Height, (Int32)radius);
}
/// <summary>
/// Draws the outline of a rounded rectangle.
/// </summary>
public static void DrawRoundedRectangle(Graphics graphics, Pen pen, Int32 x, Int32 y, Int32 width, Int32 height, Int32 radius)
{
using (GraphicsPath path = GetRoundedRectanglePath(x, y, width, height, radius))
graphics.DrawPath(pen, path);
}
}
Just make calls from within any Paint or PaintBackground event where you're handed a Graphics object. Pass that in along with whatever else, and draw rounded stuff.
It's an option to keep it all in .NET without external P/Invokes.
I am working on game. I want to highlight a spot on the screen when something happens.
I created a class to do this for me, and found a bit of code to draw the rectangle:
static private Texture2D CreateRectangle(int width, int height, Color colori)
{
Texture2D rectangleTexture = new Texture2D(game.GraphicsDevice, width, height, 1, TextureUsage.None,
SurfaceFormat.Color);// create the rectangle texture, ,but it will have no color! lets fix that
Color[] color = new Color[width * height];//set the color to the amount of pixels in the textures
for (int i = 0; i < color.Length; i++)//loop through all the colors setting them to whatever values we want
{
color[i] = colori;
}
rectangleTexture.SetData(color);//set the color data on the texture
return rectangleTexture;//return the texture
}
The problem is that the code above is called every update, (60 times a second), and it was not written with optimization in mind. It needs to be extremely fast (the code above freezes the game, which has only skeleton code right now).
Any suggestions?
Note: Any new code would be great (WireFrame/Fill are both fine). I would like to be able to specify color.
The SafeArea demo on the XNA Creators Club site has code to do specifically that.
You don't have to create the Texture every frame, just in LoadContent. A very stripped down version of the code from that demo:
public class RectangleOverlay : DrawableGameComponent
{
SpriteBatch spriteBatch;
Texture2D dummyTexture;
Rectangle dummyRectangle;
Color Colori;
public RectangleOverlay(Rectangle rect, Color colori, Game game)
: base(game)
{
// Choose a high number, so we will draw on top of other components.
DrawOrder = 1000;
dummyRectangle = rect;
Colori = colori;
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
dummyTexture = new Texture2D(GraphicsDevice, 1, 1);
dummyTexture.SetData(new Color[] { Color.White });
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin();
spriteBatch.Draw(dummyTexture, dummyRectangle, Colori);
spriteBatch.End();
}
}
This is how I did it. It is probably not the fastest or the best solution, but it works.
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Engine
{
/// <summary>
/// An extended version of the SpriteBatch class that supports line and
/// rectangle drawing.
/// </summary>
public class ExtendedSpriteBatch : SpriteBatch
{
/// <summary>
/// The texture used when drawing rectangles, lines and other
/// primitives. This is a 1x1 white texture created at runtime.
/// </summary>
public Texture2D WhiteTexture { get; protected set; }
public ExtendedSpriteBatch(GraphicsDevice graphicsDevice)
: base(graphicsDevice)
{
this.WhiteTexture = new Texture2D(this.GraphicsDevice, 1, 1);
this.WhiteTexture.SetData(new Color[] { Color.White });
}
/// <summary>
/// Draw a line between the two supplied points.
/// </summary>
/// <param name="start">Starting point.</param>
/// <param name="end">End point.</param>
/// <param name="color">The draw color.</param>
public void DrawLine(Vector2 start, Vector2 end, Color color)
{
float length = (end - start).Length();
float rotation = (float)Math.Atan2(end.Y - start.Y, end.X - start.X);
this.Draw(this.WhiteTexture, start, null, color, rotation, Vector2.Zero, new Vector2(length, 1), SpriteEffects.None, 0);
}
/// <summary>
/// Draw a rectangle.
/// </summary>
/// <param name="rectangle">The rectangle to draw.</param>
/// <param name="color">The draw color.</param>
public void DrawRectangle(Rectangle rectangle, Color color)
{
this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, rectangle.Width, 1), color);
this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Bottom, rectangle.Width, 1), color);
this.Draw(this.WhiteTexture, new Rectangle(rectangle.Left, rectangle.Top, 1, rectangle.Height), color);
this.Draw(this.WhiteTexture, new Rectangle(rectangle.Right, rectangle.Top, 1, rectangle.Height + 1), color);
}
/// <summary>
/// Fill a rectangle.
/// </summary>
/// <param name="rectangle">The rectangle to fill.</param>
/// <param name="color">The fill color.</param>
public void FillRectangle(Rectangle rectangle, Color color)
{
this.Draw(this.WhiteTexture, rectangle, color);
}
}
}
This is probably not the best solution, but you should be able to use a 1x1 pixel texture stretched to fit the rectangle.