I am having a small issue with using Graphics.DrawArc method. When used it's coming up short than what the actual size is. I am basing this control off another post found here
I am trying to make this into a UserControl with some properties and expand on it. The issue is when I set the percentage per say 50% it comes up short...
This is what the UserControl looks like at 50%... It's should be centered (blue) at the bottom of circle. I have tried adjusting everything I could, but I am at lost right now.
Here is my current code...
Color _ProgressCompletedColor = SystemColors.MenuHighlight;
Color _ProgressNotCompleted = Color.LightGray;
Int32 _ProgressThickness = 2;
Single _ProgressCompleted = 25;
public AttuneProgressBar()
{
InitializeComponent();
}
public Single PercentageCompleted
{
get
{
return this._ProgressCompleted;
}
set
{
this._ProgressCompleted = value;
this.Invalidate();
}
}
public Int32 ProgressBarThickness
{
get
{
return this._ProgressThickness;
}
set
{
this._ProgressThickness = value;
this.Invalidate();
}
}
public Color ProgressNotCompletedColor
{
get
{
return this._ProgressNotCompleted;
}
set
{
this._ProgressNotCompleted = value;
this.Invalidate();
}
}
public Color ProgressCompletedColor
{
get
{
return this._ProgressCompletedColor;
}
set
{
this._ProgressCompletedColor = value;
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
// Call the OnPaint method of the base class.
base.OnPaint(e);
DrawProgress(e.Graphics, new Rectangle(new Point(1,1), new Size(this.ClientSize.Width - 3, this.ClientSize.Height - 3)), PercentageCompleted);
}
private void DrawProgress(Graphics g, Rectangle rec, Single percentage)
{
Single progressAngle = (360 / 100 * percentage);
Single remainderAngle = 360 - progressAngle;
try
{
using (Pen progressPen = new Pen(ProgressCompletedColor, ProgressBarThickness), remainderPen = new Pen(ProgressNotCompletedColor, ProgressBarThickness))
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.DrawArc(progressPen, rec, -90, progressAngle);
g.DrawArc(remainderPen, rec, progressAngle - 90, remainderAngle);
}
}
catch (Exception exc) { }
}
}
You are calculating the angle with integers. When you do this:
angle = 360 / 100 * percentage;
it means
angle = 3 * percentage;
this of course leads to errors. There is a simple fix if you want to keep using ints:
angle = 360 * percentage / 100;
This way it doesn't get rounded down before multiplication. Or you can just use floats all the way:
angle = 360f / 100f * percentage;
Related
Is there some way to rotate an image in a certain way? I will explain it to you: I do not want the rotation in the sense of PictureBox1.Image.RotateFlip(RotateFlipType.Rotate90FlipNone), or as shown here, but rather orient a crooked rectangle to the camera (being flush with the camera).
I made a drawing for this. This is a view from above. Imagine, you are the person who is standing at point (0, 0) and currently taking a picture of the body („Rechteck“). I want to rotate that image by a certain angle, for example 35°, because you stood 35° to the body (perspectively).
I've already prepared some source code and did the math for that.
The code works like follows: The user has to enter the distance from himself to the center of the rectangle, as well as the angle. In the attached picture this is the red line. You also need to know how wide the rectangle is. The program calculates the x and y coordinates (x_v and y_v). The program calculates all distances and angles from the left edge of the rectangle to the right edge.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace schiefes_Rechteck
{
public partial class Form_Main : Form
{
/// <summary>
/// entered angle in degrees
/// </summary>
private Int16 eingegebener_Winkel_in_Grad;
private UInt16 Radius_in_mm;
/// <summary>
/// Length of the rectangle in mm
/// </summary>
private UInt16 Laenge_des_Rechtecks_in_mm;
/// <summary>
/// all distances [mm]
/// </summary>
private List<double> alle_Entfernungen = new List<double>();
/// <summary>
/// all angles [°]
/// </summary>
private List<double> alle_Winkel = new List<double>();
public Form_Main()
{
InitializeComponent();
}
private void Form_Main_Load(object sender, EventArgs e)
{
this.BackColor = Color.FromArgb(148, 148, 109);
this.Location = new Point(0, 0);
Button_Start.BackColor = Color.FromArgb(194, 194, 165);
TextBox_Entfernung.Text = "1300";
TextBox_Winkel.Text = "35";
TextBox_Rechtecklaenge.Text = "503";
if (System.IO.File.Exists(Application.StartupPath + "\\schiefes_Rechteck_Grafik.PNG"))
{
PictureBox1.Image = Image.FromFile(Application.StartupPath + "\\schiefes_Rechteck_Grafik.PNG");
}
}
private void Form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
if (PictureBox1.Image != null)
{
PictureBox1.Image.Dispose();
}
if (PictureBox2.Image != null)
{
PictureBox2.Image.Dispose();
}
}
private void TextBox_Entfernung_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(TextBox_Entfernung.Text))
{
bool erfolgreich = UInt16.TryParse(TextBox_Entfernung.Text, out Radius_in_mm);
if (erfolgreich)
{
TextBox_Entfernung.ForeColor = Color.FromArgb(0, 163, 0);
}
else
{
TextBox_Entfernung.ForeColor = Color.FromArgb(163, 0, 0);
}
}
}
private void TextBox_Winkel_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(TextBox_Winkel.Text))
{
bool erfolgreich = Int16.TryParse(TextBox_Winkel.Text, out eingegebener_Winkel_in_Grad);
if (erfolgreich)
{
TextBox_Winkel.ForeColor = Color.FromArgb(0, 163, 0);
}
else
{
TextBox_Winkel.ForeColor = Color.FromArgb(163, 0, 0);
}
}
}
private void TextBox_Rechtecklaenge_TextChanged(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(TextBox_Rechtecklaenge.Text))
{
bool erfolgreich = UInt16.TryParse(TextBox_Rechtecklaenge.Text, out Laenge_des_Rechtecks_in_mm);
if (erfolgreich)
{
TextBox_Rechtecklaenge.ForeColor = Color.FromArgb(0, 163, 0);
}
else
{
TextBox_Rechtecklaenge.ForeColor = Color.FromArgb(163, 0, 0);
}
}
}
private async void Button_Start_Click(object sender, EventArgs e)
{
ListBox1.Items.Clear();
await Task.Run(() => Berechnung_aller_Werte());
}
private void Berechnung_aller_Werte()
{
alle_Entfernungen.Clear();
alle_Winkel.Clear();
double x_v, y_v; // Mitte des Rechtecks, davon die x-Koordinate und die y-Koordinate.
x_v = Radius_in_mm * Math.Cos((90.0 - (double)eingegebener_Winkel_in_Grad) * Math.PI / 180.0); //richtig
y_v = Radius_in_mm * Math.Sin((90.0 - (double)eingegebener_Winkel_in_Grad) * Math.PI / 180.0); //richtig
double alpha_in_Grad = 0.0;
double Entfernung = 0.0;
double halbe_Rechteckbreite = Laenge_des_Rechtecks_in_mm / 2.0;
double Position_linker_Rand = x_v - halbe_Rechteckbreite; //richtig
double Zaehler = 0.0;
while (Zaehler < Laenge_des_Rechtecks_in_mm)
{
alpha_in_Grad = Math.Atan((Position_linker_Rand + Zaehler) / y_v) * 180.0 / Math.PI;
alle_Winkel.Add(alpha_in_Grad);
Entfernung = Math.Sqrt(Math.Pow(Position_linker_Rand + Zaehler, 2) + Math.Pow(y_v, 2));
alle_Entfernungen.Add(Entfernung);
Zaehler += 1.0;
}
this.BeginInvoke((Action)(() => { ListBox1.Items.Add(Math.Round(alle_Entfernungen.Last(), 0).ToString() + " mm"); ListBox1.Items.Add(Math.Round(alle_Winkel.Last(), 0).ToString() + " °"); }));
}
}//Form
}
If you want a non-crooked image, i.e., all lines remain either vertical or horizontal, then all what happens to the image is that its width will appear smaller when viewed from the side, and its height will remain the same.
Get the scaling factor for the x-Axis by dividing the apparent angle under which you see the image, i.e., the angle between the yellow-green and the pink lines in your image, by the corresponding angle you would have when standing right in front of the image. A very good approximation for this factor is simply cos(36° * PI / 180), where the angle is the angle to your red line in the image.
xScale = Math.Cos(angleToMidLineInDegrees * Math.PI / 180);
yScale = 1;
or simply
xScale = Math.Cos(angleToMidLineInRadians);
yScale = 1;
where
angleToMidLineInRadians = Math.ATan(x_redLine / y_v);
or in one step
xScale = y_v / Math.Sqrt(x_redLine * x_redLine + y_v * y_v);
See: cos(arctan(x/y)) on WolframAlpha.
However, when transforming an image, you must do the inverse transformation (as explained towards the end of the video), because you want to determine the pixels of the transformed image. I.e., you will do in pseudo code (where t means transformed and without t are the coordinates in the original):
for (yt = 0 to height_t - 1; yt++) {
for (xt = 0 to width_t - 1; xt++) {
(x, y) = inverse_transformation(xt, yt);
color_t = get_color(picture, x, y);
draw(picture_t, xt, yt, color_t);
}
}
hello I am making an application that the design requires special graphs that change depending on the value that is give. like this:
how would i go about doing this? could someone point me in the right direction?
the outer ring of the orange changes with the value but the middle circle stays static.
p.s my paint skills are amazing.
You can draw your own control quite easily. The main thing is the FillPie method, which draws only part of a circle. To change the starting point of the outer ring or the filling direction you need to change the starting and sweep angle in the FillPie call of the OnPaint event.
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
public class CircularProgressBar : Control
{
#region "Properties"
private Color _BorderColor;
public Color BorderColor
{
get { return _BorderColor; }
set
{
_BorderColor = value;
this.Invalidate();
}
}
private Color _InnerColor;
public Color InnerColor
{
get { return _InnerColor; }
set
{
_InnerColor = value;
this.Invalidate();
}
}
private bool _ShowPercentage;
public bool ShowPercentage
{
get { return _ShowPercentage; }
set
{
_ShowPercentage = value;
this.Invalidate();
}
}
private int _BorderWidth;
public int BorderWidth
{
get { return _BorderWidth; }
set
{
_BorderWidth = value;
this.Invalidate();
}
}
private float _Value;
public float Value
{
get { return _Value; }
set
{
_Value = value;
this.Invalidate();
}
}
#endregion
#region "Constructor"
public CircularProgressBar()
{
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
_Value = 100;
_BorderColor = Color.Orange;
_BorderWidth = 30;
_ShowPercentage = true;
_InnerColor = Color.DarkGray;
this.ForeColor = Color.White;
}
#endregion
#region "Painting"
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Measure the single parts
int Diameter = Math.Min(this.ClientSize.Width, this.ClientSize.Height);
int InnerDiameter = Diameter - BorderWidth;
Rectangle PieRect = new Rectangle(Convert.ToInt32(this.ClientSize.Width / 2 - Diameter / 2), Convert.ToInt32(this.ClientSize.Height / 2 - Diameter / 2), Diameter, Diameter);
Rectangle InnerRect = new Rectangle(Convert.ToInt32(this.ClientSize.Width / 2 - InnerDiameter / 2), Convert.ToInt32(this.ClientSize.Height / 2 - InnerDiameter / 2), InnerDiameter, InnerDiameter);
//Draw outer ring
using (SolidBrush b = new SolidBrush(BorderColor))
{
e.Graphics.FillPie(b, PieRect, 0, Value / 100 * 360);
}
//Draw inner ring
using (SolidBrush b = new SolidBrush(this._InnerColor))
{
e.Graphics.FillEllipse(b, InnerRect);
}
//Draw percentage
if (ShowPercentage)
{
using (StringFormat sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
using (SolidBrush b = new SolidBrush(this.ForeColor))
{
e.Graphics.DrawString(Convert.ToInt32(Value).ToString() + "%", this.Font, b, InnerRect, sf);
}
}
}
}
#endregion
}
The result:
I have a custom CheckListBox control that is supposed to function the same way as the CheckedListBox control but it is not. The problem is when I scroll down, the drawing gets all messed up. The container won't actually scroll down, it will just "jitter" the check boxes around, draw random lines, etc.
Update: I changed the code so the location of each CheckBox was set in the OnControlAdded method instead of the OnPaint method. It now scrolls fine, but the drawing is still messed up! The border is missing, the BackColor changes, the lines for the check boxes are not straight; just a whole mess of things. It works perfectly in the designer (the scrolling and drawing), but not when I run the program.
Here's the code for the control:
public class ChromeCheckListBox : ChromeContainerControl
{
[Description("Determines what corner(s) will be rounded.")]
public Utilities.RoundedRectangle.RectangleCorners Corners { get; set; }
private int cornerRadius;
[Description("Determines the radius of the the corners")]
public int CornerRadius
{
get { return cornerRadius; }
set
{
if (value < 1)
Utilities.ThrowError("The radius cannot be less than 1. If you want no radius, set Corners to None.");
else
cornerRadius = value;
}
}
[Description("Determines the list of ChromeRadioButton controls that are displayed.")]
private ChromeCheckBox[] items;
public ChromeCheckBox[] Items
{
get { return items; }
set
{
items = value;
Controls.Clear();
Controls.AddRange(items);
}
}
public ChromeCheckListBox()
{
this.AutoScroll = true;
this.Corners = Utilities.RoundedRectangle.RectangleCorners.All;
this.CornerRadius = 1;
this.Items = new ChromeCheckBox[0];
this.Size = new Size(100, 100);
}
protected override void OnControlAdded(ControlEventArgs e)
{
for (int i = 0; i < Items.Length; i++)
{
if (i == 0)
Items[i].Location = new Point(2 + Padding.Left, 2 + Padding.Top);
else
Items[i].Location = new Point(2 + Padding.Left, Items[i - 1].Location.Y + Size.Ceiling(this.CreateGraphics().MeasureString(Items[i - 1].Text, Items[i - 1].Font)).Height);
}
base.OnControlAdded(e);
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics canvas = e.Graphics;
canvas.SmoothingMode = SmoothingMode.HighQuality;
Rectangle region = new Rectangle(0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
GraphicsPath path = Utilities.RoundedRectangle.Create(region, CornerRadius, Corners);
canvas.FillPath(new LinearGradientBrush(region, fillColors[0], fillColors[1], 90), path);
canvas.DrawPath(new Pen(borderColor), path);
}
}
I got it! Instead of setting the location of the check boxes in the OnPaint method, I should set them in the OnControlAdded method. Also, on the OnScroll method, I need to Invalidate the control causing it to redraw.
So, it should (well maybe not should, but could) look like this:
public class ChromeCheckListBox : ChromeContainerControl
{
[Description("Determines what corner(s) will be rounded.")]
public Utilities.RoundedRectangle.RectangleCorners Corners { get; set; }
private int cornerRadius;
[Description("Determines the radius of the the corners")]
public int CornerRadius
{
get { return cornerRadius; }
set
{
if (value < 1)
Utilities.ThrowError("The radius cannot be less than 1. If you want no radius, set Corners to None.");
else
cornerRadius = value;
}
}
[Description("Determines the list of ChromeRadioButton controls that are displayed.")]
private ChromeCheckBox[] items;
public ChromeCheckBox[] Items
{
get { return items; }
set
{
items = value;
Controls.Clear();
Controls.AddRange(items);
}
}
public ChromeCheckListBox()
{
this.AutoScroll = true;
this.Corners = Utilities.RoundedRectangle.RectangleCorners.All;
this.CornerRadius = 1;
this.Items = new ChromeCheckBox[0];
this.Size = new Size(100, 100);
}
protected override void OnControlAdded(ControlEventArgs e)
{
for (int i = 0; i < Items.Length; i++)
{
if (i == 0)
Items[i].Location = new Point(2 + Padding.Left, 2 + Padding.Top);
else
Items[i].Location = new Point(2 + Padding.Left, Items[i - 1].Location.Y + Size.Ceiling(this.CreateGraphics().MeasureString(Items[i - 1].Text, Items[i - 1].Font)).Height);
}
base.OnControlAdded(e);
}
protected override void OnScroll(ScrollEventArgs se)
{
base.OnScroll(se);
base.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics canvas = e.Graphics;
canvas.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle region = new Rectangle(0, 0, ClientRectangle.Width - 1, ClientRectangle.Height - 1);
GraphicsPath path = Utilities.RoundedRectangle.Create(region, CornerRadius, Corners);
canvas.FillPath(new LinearGradientBrush(region, fillColors[0], fillColors[1], 90), path);
canvas.DrawPath(new Pen(borderColor), path);
}
I have a application in which the text of different length is set on the button every 5 seconds.
How do i resize the text to fit it in the button.
Also i need to resize the font on resizing the window.(my button size increases on resizing window as i have used dock property on it.
The following is the code i used to do it, but its not working very fine when the text length is 2 or less.(the text pops a bit out of the control)
public static void FitControlFont(Control control)
{
if (control.Text.Length == 0)
{
return;
}
try
{
Font currentFont = control.Font;
Graphics graphics = control.CreateGraphics();
SizeF newSize = graphics.MeasureString(control.Text, control.Font);
graphics.Dispose();
float factorX = control.Width / newSize.Width;
float factorY = control.Height / newSize.Height;
float factor = factorX > factorY ? factorY : factorX;
if (control.InvokeRequired)
{
control.Invoke(new MethodInvoker(delegate { control.Font = new Font(currentFont.Name, currentFont.SizeInPoints * factor); }));
}
else
{
control.Font = new Font(currentFont.Name, currentFont.SizeInPoints * factor);
}
}
catch (Exception ex)
{
if (Exceptions.IsCritical(ex))
{
throw;
}
return;
}
}
You can set the button's autosize property to true, this will make it's width fit to content.
Concerning changing the font, you can handle the SizeChanged of the button ( since you set it's dock property) and determine some ratio for the font relative to the form's height :
private void button1_SizeChanged(object sender, EventArgs e)
{
button1.Font = new Font(button1.Font.FontFamily, this.Size.Height / 10) ;
}
I improved the function a bit because in your example the control.Width and newSize.Width are integer, control.Height and newSize.Height are also integer, so when you calculate the form factors you get an integer result and cast it as float, which is not a good form factor (and can be zero crashing the newly created Font):
public static void FitControlFont(Control control)
{
if (control.Text.Length == 0)
{
return;
}
try
{
Font currentFont = control.Font;
Graphics graphics = control.CreateGraphics();
SizeF newSize = graphics.MeasureString(control.Text, control.Font);
graphics.Dispose();
float factorX = ((float)control.Width) / newSize.Width;
float factorY = ((float)control.Height) / newSize.Height;
float factor = factorX > factorY ? factorY : factorX;
if (control.InvokeRequired)
{
control.Invoke(new MethodInvoker(delegate { control.Font = new Font(currentFont.Name, currentFont.SizeInPoints * factor); }));
}
else
{
control.Font = new Font(currentFont.Name, currentFont.SizeInPoints * factor);
}
}
catch (Exception ex)
{
if (Exceptions.IsCritical(ex))
{
throw;
}
return;
}
}
This question already has answers here:
C# vertical label in a Windows Forms
(9 answers)
Closed 9 years ago.
I want to show a label rotated 90 degrees (so I can put a bunch of them at the top of a table as the headings). Is there an easy way to do this?
You will need to write your own or use a custom control.
A The Code Project article you can start with is Customized Text - Orientated Controls in C# - Part I (Label Control). This contains extra functionality, so you should be able to trim it down if you'd like.
And here is some code from it that is of interest:
/// <summary>
/// This is a lable, in which you can set the text in any direction/angle
/// </summary>
#region Orientation
//Orientation of the text
public enum Orientation
{
Circle,
Arc,
Rotate
}
public enum Direction
{
Clockwise,
AntiClockwise
}
#endregion
public class OrientedTextLabel : System.Windows.Forms.Label
{
#region Variables
private double rotationAngle;
private string text;
private Orientation textOrientation;
private Direction textDirection;
#endregion
#region Constructor
public OrientedTextLabel()
{
//Setting the initial condition.
rotationAngle = 0d;
textOrientation = Orientation.Rotate;
this.Size = new Size(105,12);
}
#endregion
#region Properties
[Description("Rotation Angle"),Category("Appearance")]
public double RotationAngle
{
get
{
return rotationAngle;
}
set
{
rotationAngle = value;
this.Invalidate();
}
}
[Description("Kind of Text Orientation"),Category("Appearance")]
public Orientation TextOrientation
{
get
{
return textOrientation;
}
set
{
textOrientation = value;
this.Invalidate();
}
}
[Description("Direction of the Text"),Category("Appearance")]
public Direction TextDirection
{
get
{
return textDirection;
}
set
{
textDirection = value;
this.Invalidate();
}
}
[Description("Display Text"),Category("Appearance")]
public override string Text
{
get
{
return text;
}
set
{
text = value;
this.Invalidate();
}
}
#endregion
#region Method
protected override void OnPaint(PaintEventArgs e)
{
Graphics graphics = e.Graphics;
StringFormat stringFormat = new StringFormat();
stringFormat.Alignment = StringAlignment.Center;
stringFormat.Trimming = StringTrimming.None;
Brush textBrush = new SolidBrush(this.ForeColor);
//Getting the width and height of the text, which we are going to write
float width = graphics.MeasureString(text,this.Font).Width;
float height = graphics.MeasureString(text,this.Font).Height;
//The radius is set to 0.9 of the width or height, b'cos not to
//hide and part of the text at any stage
float radius = 0f;
if (ClientRectangle.Width<ClientRectangle.Height)
{
radius = ClientRectangle.Width *0.9f/2;
}
else
{
radius = ClientRectangle.Height *0.9f/2;
}
//Setting the text according to the selection
switch (textOrientation)
{
case Orientation.Arc:
{
//Arc angle must be get from the length of the text.
float arcAngle = (2*width/radius)/text.Length;
if(textDirection == Direction.Clockwise)
{
for (int i=0; i<text.Length; i++)
{
graphics.TranslateTransform(
(float)(radius*(1 - Math.Cos(arcAngle*i + rotationAngle/180 * Math.PI))),
(float)(radius*(1 - Math.Sin(arcAngle*i + rotationAngle/180*Math.PI))));
graphics.RotateTransform((-90 + (float)rotationAngle + 180*arcAngle*i/(float)Math.PI));
graphics.DrawString(text[i].ToString(), this.Font, textBrush, 0, 0);
graphics.ResetTransform();
}
}
else
{
for (int i=0; i<text.Length; i++)
{
graphics.TranslateTransform(
(float)(radius*(1 - Math.Cos(arcAngle*i + rotationAngle/180*Math.PI))),
(float)(radius*(1 + Math.Sin(arcAngle*i + rotationAngle/180*Math.PI))));
graphics.RotateTransform((-90 - (float)rotationAngle - 180*arcAngle*i/(float)Math.PI));
graphics.DrawString(text[i].ToString(), this.Font, textBrush, 0, 0);
graphics.ResetTransform();
}
}
break;
}
case Orientation.Circle:
{
if (textDirection == Direction.Clockwise)
{
for(int i=0;i<text.Length;i++)
{
graphics.TranslateTransform(
(float)(radius*(1 - Math.Cos((2*Math.PI/text.Length)*i + rotationAngle/180*Math.PI))),
(float)(radius*(1 - Math.Sin((2*Math.PI/text.Length)*i + rotationAngle/180*Math.PI))));
graphics.RotateTransform(-90 + (float)rotationAngle + (360/text.Length)*i);
graphics.DrawString(text[i].ToString(), this.Font, textBrush, 0, 0);
graphics.ResetTransform();
}
}
else
{
for(int i=0;i<text.Length;i++)
{
graphics.TranslateTransform(
(float)(radius*(1 - Math.Cos((2*Math.PI/text.Length)*i + rotationAngle/180*Math.PI))),
(float)(radius*(1 + Math.Sin((2*Math.PI/text.Length)*i + rotationAngle/180*Math.PI))));
graphics.RotateTransform(-90 - (float)rotationAngle - (360/text.Length)*i);
graphics.DrawString(text[i].ToString(), this.Font, textBrush, 0, 0);
graphics.ResetTransform();
}
}
break;
}
case Orientation.Rotate:
{
//For rotation, who about rotation?
double angle = (rotationAngle/180)*Math.PI;
graphics.TranslateTransform(
(ClientRectangle.Width+(float)(height*Math.Sin(angle))-(float)(width*Math.Cos(angle)))/2,
(ClientRectangle.Height-(float)(height*Math.Cos(angle))-(float)(width*Math.Sin(angle)))/2);
graphics.RotateTransform((float)rotationAngle);
graphics.DrawString(text,this.Font,textBrush,0,0);
graphics.ResetTransform();
break;
}
}
}
#endregion
}
You can also take a look at the Windows ToolStrip control. It has an option for TextDirection that can be set to Vertical90 or Vertical270 and this will rotate your Label text in the appropriate direction.
Overview: ToolStrip Class (MSDN)
Setting the property (learn.microsoft.com)
Enumerated Values (learn.microsoft.com)