Я создал пользовательский элемент управления для рисования индикатора типа Dial, но натолкнулся на странную проблему.Форма, на которой я использую датчик, имеет два таких датчика.Один датчик работает отлично (тот, который закреплен слева), но справа буквально не рисует, даже в Visual Studio.
Если я в Visual Studio и меняю с вкладки кодана вкладке с датчиком, этот датчик никогда не рисуется, и он по-прежнему показывает текст с предыдущей вкладки.Если я щелкну на датчике, то индикатор неожиданно начнет рисовать.
Это происходит, когда программа также запускается, но вместо того, чтобы не перерисовывать пространство, она просто полностью прозрачна, даже стирая фон формы.
Код 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;
}
}