Я создал пользовательский элемент управления для рисования индикатора типа Dial, но натолкнулся на странную проблему.Форма, на которой я использую датчик, имеет два таких датчика.Один датчик работает отлично (тот, который закреплен слева), но справа буквально не рисует, даже в Visual Studio.
Если я в Visual Studio и меняю с вкладки кодана вкладке с датчиком, этот датчик никогда не рисуется, и он по-прежнему показывает текст с предыдущей вкладки.Если я щелкну на датчике, то индикатор неожиданно начнет рисовать.
Это происходит, когда программа также запускается, но вместо того, чтобы не перерисовывать пространство, она просто полностью прозрачна, даже стирая фон формы.
![Paint Issue](https://i.imgur.com/EHISBBr.png)
Код OnPaint выглядит следующим образом:
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);
}
У меня действительно нет ни малейшего понятия, что могло бы привести к тому, что весь элемент управления вообще не рисовалпока вы не нажмете на него.
Я уже проверил Display.Designer.CS, и оба элемента управления добавлены в "Display.Controls".
Кто-нибудь видит или знает что-то, что я не знаю?
Я запустил Debug, и функция OnPaint буквально никогда не вызывается на индикаторе GPU, пока датчик не потеряет / не получит фокус.
Вот весь мой класс DialGauge:
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;
}
}