I have created a custom control for drawing a Dial type gauge but I've come across a strange issue. The form that I am using the gauge on has two of these gauges. One gauge works perfectly fine (the one docked on the left), but the one on the right literally does not paint, even in Visual Studio.
If I'm in Visual Studio and I change from a code tab to the tab with the gauge, that one gauge is never drawn and it still shows the text from the previous tab. If I click on the gauge, then the gauge suddenly draws.
This happens when the program is run as well but instead of not redrawing the space, it is just completely transparent, even erasing the form background.
The OnPaint Code is like this:
protected override void OnPaint(PaintEventArgs e)
{
int size = ClientSize.Height - GaugeThickness;
float x = (GaugeThickness / 2) + OffsetX;
float y = (GaugeThickness / 2) + OffsetY;
if (this.HorizontalAlignment == HorizontalAlignment.Left)
{
x = ((size / 2) * -1) + OffsetX;
}
else if (this.HorizontalAlignment == HorizontalAlignment.Right)
{
x = (size / 2) + OffsetX;
}
if (this.VerticalAlignment == VerticalAlignment.Top)
{
y = ((size / 2) * -1) + OffsetY;
}
else if (this.VerticalAlignment == VerticalAlignment.Bottom)
{
y = (size / 2) + OffsetY;
}
PaintBackground(e, x, y);
PaintText(e, x, y, size, size);
PaintMarks(e, x, y);
PaintNeedle(e, x, y);
}
protected virtual void PaintBackground(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw background
using (Pen p = new Pen(GaugeColor, GaugeThickness))
{
e.Graphics.DrawArc(p, x, y, size, size, StartAngle, SweepAngle);
}
}
protected virtual void PaintText(PaintEventArgs e, float x, float y, int width, int height)
{
TextFormatFlags horizontal = TextFormatFlags.HorizontalCenter;
TextFormatFlags vertical = TextFormatFlags.VerticalCenter;
if (this.TextAlignmentHorizontal == HorizontalAlignment.Left)
{
horizontal = TextFormatFlags.Left;
}
else if (this.TextAlignmentHorizontal == HorizontalAlignment.Right)
{
horizontal = TextFormatFlags.Right;
}
if (this.TextAlignmentVertical == VerticalAlignment.Top)
{
vertical = TextFormatFlags.Top;
}
else if (this.TextAlignmentVertical == VerticalAlignment.Bottom)
{
vertical = TextFormatFlags.Bottom;
}
Rectangle rect = new Rectangle((int)x, (int)y, width, height);
e.Graphics.FillEllipse(new SolidBrush(Color.Transparent), rect);
TextRenderer.DrawText(e.Graphics, this.Text, this.Font, rect,
this.ForeColor, horizontal | vertical);
}
protected virtual void PaintMarks(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw Marks
float markLocation = 0.0f;
float spacing = SweepAngle / 10;
for (int i = 0; i < 11; i++)
{
using (Pen p = new Pen(MarkColor, MarkLength))
{
p.Alignment = PenAlignment.Inset;
e.Graphics.DrawArc(p, x, y, size, size, markLocation + StartAngle, MarkThickness);
markLocation += spacing;
}
}
}
protected virtual void PaintNeedle(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw needle.
if (Value >= MaxValue) Value = MaxValue;
using (Pen p = new Pen(NeedleColor, NeedleLength))
{
p.Alignment = PenAlignment.Inset;
e.Graphics.DrawArc(p, x, y, size, size, StartAngle + GetNeedleAngle(), NeedleSweep);
}
base.OnPaint(e);
}
I really don't have the slightest clue what would be causing the entire control to not paint at all until you click it.
I already checked Display.Designer.CS and both controls are added to "Display.Controls".
Does anyone see or know anything that I don't?
I ran Debug and the OnPaint function literally never gets called on the GPU gauge until the gauge loses/gains focus.
Here is my entire DialGauge class:
public class DialGauge : Control
{
#region Properties
[Browsable(true)]
public float StartAngle { get => _startAngle; set { _startAngle = value; Invalidate(); } }
[Browsable(true)]
public float SweepAngle { get => _sweepAngle; set { _sweepAngle = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(100d)]
public double MaxValue { get => _maxvalue; set { _maxvalue = value; Invalidate(); } }
[Browsable(true)]
public int GaugeThickness { get => _gaugethickness; set { _gaugethickness = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(150)]
public int NeedleLength { get => _needlelength; set { _needlelength = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(5)]
public float NeedleSweep { get => _needlesweep; set { _needlesweep = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(0.0)]
public double Value { get => _value; set { _value = value; Invalidate(); } }
[Browsable(true)]
public Color GaugeColor { get => gaugecolor; set { gaugecolor = value; Invalidate(); } }
[Browsable(true)]
public Color NeedleColor { get => needlecolor; set { needlecolor = value; Invalidate(); } }
[Browsable(true)]
public float MarkLength { get => _marklength; set { _marklength = value; Invalidate(); } }
[Browsable(true)]
public Color MarkColor { get => _markcolor; set { _markcolor = value; Invalidate(); } }
[Browsable(true)]
public float MarkThickness { get => _markthickness; set { _markthickness = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(HorizontalAlignment.Center)]
public HorizontalAlignment HorizontalAlignment { get => _horizontalalignment; set { _horizontalalignment = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(VerticalAlignment.Center)]
public VerticalAlignment VerticalAlignment { get => _verticalalignment; set { _verticalalignment = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(0f)]
public float OffsetX { get => _offset_x; set { _offset_x = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(0f)]
public float OffsetY { get => _offset_y; set { _offset_y = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(HorizontalAlignment.Center)]
public HorizontalAlignment TextAlignmentHorizontal { get => _texthorizontalalignment; set { _texthorizontalalignment = value; Invalidate(); } }
[Browsable(true)]
[DefaultValue(VerticalAlignment.Center)]
public VerticalAlignment TextAlignmentVertical { get => _textverticalalignment; set { _textverticalalignment = value; Invalidate(); } }
[Browsable(true)]
public override string Text { get => base.Text; set { base.Text = value; Invalidate(); } }
[Browsable(true)]
public override Font Font { get => base.Font; set { base.Font = value; Invalidate(); } }
protected float _startAngle;
protected float _sweepAngle;
protected double _maxvalue;
protected int _gaugethickness;
protected int _needlelength;
protected float _needlesweep;
protected double _value;
protected Color gaugecolor;
protected Color needlecolor;
protected float _marklength;
protected Color _markcolor;
protected float _markthickness;
protected HorizontalAlignment _horizontalalignment;
protected VerticalAlignment _verticalalignment;
protected HorizontalAlignment _texthorizontalalignment;
protected VerticalAlignment _textverticalalignment;
protected float _offset_x;
protected float _offset_y;
#endregion
public DialGauge()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
DoubleBuffered = true;
}
#region PAINT
protected override void OnPaint(PaintEventArgs e)
{
int size = ClientSize.Height - GaugeThickness;
float x = (GaugeThickness / 2) + OffsetX;
float y = (GaugeThickness / 2) + OffsetY;
if (this.HorizontalAlignment == HorizontalAlignment.Left)
{
x = ((size / 2) * -1) + OffsetX;
}
else if (this.HorizontalAlignment == HorizontalAlignment.Right)
{
x = (size / 2) + OffsetX;
}
if (this.VerticalAlignment == VerticalAlignment.Top)
{
y = ((size / 2) * -1) + OffsetY;
}
else if (this.VerticalAlignment == VerticalAlignment.Bottom)
{
y = (size / 2) + OffsetY;
}
PaintBackground(e, x, y);
PaintText(e, x, y, size, size);
PaintMarks(e, x, y);
PaintNeedle(e, x, y);
}
protected virtual void PaintBackground(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw background
using (Pen p = new Pen(GaugeColor, GaugeThickness))
{
e.Graphics.DrawArc(p, x, y, size, size, StartAngle, SweepAngle);
}
}
protected virtual void PaintText(PaintEventArgs e, float x, float y, int width, int height)
{
TextFormatFlags horizontal = TextFormatFlags.HorizontalCenter;
TextFormatFlags vertical = TextFormatFlags.VerticalCenter;
if (this.TextAlignmentHorizontal == HorizontalAlignment.Left)
{
horizontal = TextFormatFlags.Left;
}
else if (this.TextAlignmentHorizontal == HorizontalAlignment.Right)
{
horizontal = TextFormatFlags.Right;
}
if (this.TextAlignmentVertical == VerticalAlignment.Top)
{
vertical = TextFormatFlags.Top;
}
else if (this.TextAlignmentVertical == VerticalAlignment.Bottom)
{
vertical = TextFormatFlags.Bottom;
}
Rectangle rect = new Rectangle((int)x, (int)y, width, height);
e.Graphics.FillEllipse(new SolidBrush(Color.Transparent), rect);
TextRenderer.DrawText(e.Graphics, this.Text, this.Font, rect,
this.ForeColor, horizontal | vertical);
}
protected virtual void PaintMarks(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw Marks
float markLocation = 0.0f;
float spacing = SweepAngle / 10;
for (int i = 0; i < 11; i++)
{
using (Pen p = new Pen(MarkColor, MarkLength))
{
p.Alignment = PenAlignment.Inset;
e.Graphics.DrawArc(p, x, y, size, size, markLocation + StartAngle, MarkThickness);
markLocation += spacing;
}
}
}
protected virtual void PaintNeedle(PaintEventArgs e, float x, float y)
{
int size = ClientSize.Height - GaugeThickness;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
//Draw needle.
if (Value >= MaxValue) Value = MaxValue;
using (Pen p = new Pen(NeedleColor, NeedleLength))
{
p.Alignment = PenAlignment.Inset;
e.Graphics.DrawArc(p, x, y, size, size, StartAngle + GetNeedleAngle(), NeedleSweep);
}
base.OnPaint(e);
}
#endregion
protected float GetNeedleAngle()
{
float percentage = (float)(Value / MaxValue);
float angle = SweepAngle * percentage;
return angle;
}
}