737 lines
25 KiB
C#
737 lines
25 KiB
C#
using System;
|
|||
|
|
using System.ComponentModel;
|
||
|
|
using System.Drawing;
|
||
|
|
using System.Drawing.Drawing2D;
|
||
|
|
using System.Windows.Forms;
|
||
|
|
|
||
|
|
namespace JinYuan.ControlLib
|
||
|
|
{
|
||
|
|
public partial class ProcessEllipse : UserControl
|
||
|
|
{
|
||
|
|
private bool _isRefreshPending = false;
|
||
|
|
private SolidBrush _backEllipseBrush;
|
||
|
|
private SolidBrush _coreEllipseBrush;
|
||
|
|
private SolidBrush _valueBrush;
|
||
|
|
private SolidBrush _foreColorBrush;
|
||
|
|
private Pen _coreEllipsePen;
|
||
|
|
private Pen _valueArcPen;
|
||
|
|
|
||
|
|
public ProcessEllipse()
|
||
|
|
{
|
||
|
|
InitializeComponent();
|
||
|
|
SetStyle(ControlStyles.AllPaintingInWmPaint |
|
||
|
|
ControlStyles.DoubleBuffer |
|
||
|
|
ControlStyles.ResizeRedraw |
|
||
|
|
ControlStyles.Selectable |
|
||
|
|
ControlStyles.SupportsTransparentBackColor |
|
||
|
|
ControlStyles.UserPaint |
|
||
|
|
ControlStyles.OptimizedDoubleBuffer, true);
|
||
|
|
UpdateStyles();
|
||
|
|
|
||
|
|
ForeColor = Color.White;
|
||
|
|
Font = new Font("Arial Unicode MS", 20);
|
||
|
|
|
||
|
|
InitDrawingObjects();
|
||
|
|
}
|
||
|
|
|
||
|
|
#region 减少闪烁
|
||
|
|
protected override CreateParams CreateParams
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
CreateParams cp = base.CreateParams;
|
||
|
|
cp.ExStyle |= 0x02000000;
|
||
|
|
return cp;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
[Description("值改变事件"), Category("自定义")]
|
||
|
|
public event EventHandler ValueChanged;
|
||
|
|
|
||
|
|
#region 私有字段
|
||
|
|
private Color m_backEllipseColor = Color.FromArgb(22, 160, 133);
|
||
|
|
private Color m_coreEllipseColor = Color.FromArgb(180, 180, 180);
|
||
|
|
private Color m_valueColor = Color.FromArgb(255, 77, 59);
|
||
|
|
private bool m_isShowCoreEllipseBorder = true;
|
||
|
|
private ShowType m_showType = ShowType.PPM;
|
||
|
|
private ValueType m_valueType = ValueType.Percent;
|
||
|
|
private ValueFloatOrInt m_valueFloatOrInt = ValueFloatOrInt.Int;
|
||
|
|
private int m_valueWidth = 30;
|
||
|
|
private int m_valueMargin = 5;
|
||
|
|
private int m_maxValue = 100;
|
||
|
|
private int m_intValue = 0;
|
||
|
|
private float m_floatValue = 0.00f;
|
||
|
|
private Font m_font = new Font("Arial Unicode MS", 20);
|
||
|
|
Color m_foreColor = Color.White;
|
||
|
|
private ShowStyleType m_showStyleType = ShowStyleType.Ring;
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
|
||
|
|
#region 公共属性
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 圆背景色
|
||
|
|
/// </summary>
|
||
|
|
[Description("圆背景色"), Category("自定义")]
|
||
|
|
public Color BackEllipseColor
|
||
|
|
{
|
||
|
|
get { return m_backEllipseColor; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
m_backEllipseColor = value;
|
||
|
|
//ControlRefreshExtension.RefreshWithMonitor(this);
|
||
|
|
|
||
|
|
if (m_backEllipseColor == value) return; // 判重:值不变不刷新
|
||
|
|
m_backEllipseColor = value;
|
||
|
|
_backEllipseBrush?.Dispose();
|
||
|
|
_backEllipseBrush = new SolidBrush(value);
|
||
|
|
ScheduleRefresh(); // 延迟刷新
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 内圆颜色,ShowType=Ring 有效
|
||
|
|
/// </summary>
|
||
|
|
[Description("内圆颜色,ShowType=Ring 有效"), Category("自定义")]
|
||
|
|
public Color CoreEllipseColor
|
||
|
|
{
|
||
|
|
get { return m_coreEllipseColor; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
m_coreEllipseColor = value;
|
||
|
|
if (m_coreEllipseColor == value) return;
|
||
|
|
m_coreEllipseColor = value;
|
||
|
|
_coreEllipseBrush?.Dispose();
|
||
|
|
_coreEllipseBrush = new SolidBrush(value);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
[Description("值圆颜色"), Category("自定义")]
|
||
|
|
public Color ValueColor
|
||
|
|
{
|
||
|
|
get { return m_valueColor; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_valueColor == value) return;
|
||
|
|
m_valueColor = value;
|
||
|
|
_valueBrush?.Dispose();
|
||
|
|
_valueBrush = new SolidBrush(value);
|
||
|
|
_coreEllipsePen?.Dispose();
|
||
|
|
_coreEllipsePen = new Pen(value, 2);
|
||
|
|
_valueArcPen?.Dispose();
|
||
|
|
_valueArcPen = new Pen(value, m_valueWidth - m_valueMargin * 2);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 内圆是否显示边框,ShowType=Ring 有效
|
||
|
|
/// </summary>
|
||
|
|
[Description("内圆是否显示边框,ShowType=Ring 有效"), Category("自定义")]
|
||
|
|
public bool IsShowCoreEllipseBorder
|
||
|
|
{
|
||
|
|
get { return m_isShowCoreEllipseBorder; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_isShowCoreEllipseBorder == value) return;
|
||
|
|
m_isShowCoreEllipseBorder = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 值文字类型
|
||
|
|
/// </summary>
|
||
|
|
[Description("显示类型"), Category("自定义")]
|
||
|
|
public ShowType ShowType
|
||
|
|
{
|
||
|
|
get { return m_showType; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_showType == value) return;
|
||
|
|
m_showType = value;
|
||
|
|
UpdataMaxValue();
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 值文字类型
|
||
|
|
/// </summary>
|
||
|
|
[Description("值文字类型,Percent-百分比;Absolute-数值"), Category("自定义")]
|
||
|
|
public ValueType ValueType
|
||
|
|
{
|
||
|
|
get { return m_valueType; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_valueType == value) return;
|
||
|
|
m_valueType = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 值文字类型
|
||
|
|
/// </summary>
|
||
|
|
[Description("值类型"), Category("自定义")]
|
||
|
|
public ValueFloatOrInt ValueFloatOrInt
|
||
|
|
{
|
||
|
|
get { return m_valueFloatOrInt; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_valueFloatOrInt == value) return;
|
||
|
|
m_valueFloatOrInt = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 外圆值宽度
|
||
|
|
/// </summary>
|
||
|
|
[Description("外圆值宽度,ShowType=Ring 有效"), Category("自定义")]
|
||
|
|
public int ValueWidth
|
||
|
|
{
|
||
|
|
get { return m_valueWidth; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (value <= 0 || value > Math.Min(this.Width, this.Height) || m_valueWidth == value)
|
||
|
|
return;
|
||
|
|
m_valueWidth = value;
|
||
|
|
_valueArcPen?.Dispose();
|
||
|
|
_valueArcPen = new Pen(m_valueColor, value - m_valueMargin * 2);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 外圆值间距
|
||
|
|
/// </summary>
|
||
|
|
[Description("外圆值间距"), Category("自定义")]
|
||
|
|
public int ValueMargin
|
||
|
|
{
|
||
|
|
get { return m_valueMargin; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (value < 0 || m_valueMargin >= m_valueWidth || m_valueMargin == value)
|
||
|
|
return;
|
||
|
|
m_valueMargin = value;
|
||
|
|
_valueArcPen?.Dispose();
|
||
|
|
_valueArcPen = new Pen(m_valueColor, m_valueWidth - value * 2);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 最大值
|
||
|
|
/// </summary>
|
||
|
|
[Description("最大值"), Category("自定义")]
|
||
|
|
public int MaxValue
|
||
|
|
{
|
||
|
|
get { return m_maxValue; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_maxValue == value) return;
|
||
|
|
m_maxValue = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 当前值
|
||
|
|
/// </summary>
|
||
|
|
[Description("当前值整数,ValueFloatOrInt=Int 有效"), Category("自定义")]
|
||
|
|
public int IntValue
|
||
|
|
{
|
||
|
|
get { return m_intValue; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_maxValue < value || value < 0 || m_intValue == value)
|
||
|
|
return;
|
||
|
|
m_intValue = value;
|
||
|
|
ValueChanged?.Invoke(this, null); // 简化事件调用
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 当前值
|
||
|
|
/// </summary>
|
||
|
|
[Description("当前值浮点数,ValueFloatOrInt=Float 有效"), Category("自定义")]
|
||
|
|
public float FloatValue
|
||
|
|
{
|
||
|
|
get { return m_floatValue; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_maxValue < value || value < 0 || Math.Abs(m_floatValue - value) < 0.001f)
|
||
|
|
return;
|
||
|
|
m_floatValue = value;
|
||
|
|
ValueChanged?.Invoke(this, null);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[Description("文字字体"), Category("自定义")]
|
||
|
|
public override Font Font
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
return m_font;
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_font == value) return;
|
||
|
|
m_font?.Dispose(); // 释放旧字体
|
||
|
|
m_font = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[Description("文字颜色"), Category("自定义")]
|
||
|
|
public override Color ForeColor
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
return m_foreColor;
|
||
|
|
}
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_foreColor == value) return;
|
||
|
|
m_foreColor = value;
|
||
|
|
_foreColorBrush?.Dispose();
|
||
|
|
_foreColorBrush = new SolidBrush(value);
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
[Description("显示样式"), Category("自定义")]
|
||
|
|
public ShowStyleType ShowStyleType
|
||
|
|
{
|
||
|
|
get { return m_showStyleType; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
if (m_showStyleType == value) return;
|
||
|
|
m_showStyleType = value;
|
||
|
|
ScheduleRefresh();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
///// <summary>
|
||
|
|
///// 更新最大值
|
||
|
|
///// </summary>
|
||
|
|
//private void UpdataMaxValue()
|
||
|
|
//{
|
||
|
|
// switch (m_showType)
|
||
|
|
// {
|
||
|
|
// case ShowType.PPM:
|
||
|
|
// this.m_maxValue = 100;
|
||
|
|
// break;
|
||
|
|
// case ShowType.稼动率:
|
||
|
|
// this.m_maxValue = 100;
|
||
|
|
// break;
|
||
|
|
// }
|
||
|
|
|
||
|
|
//}
|
||
|
|
|
||
|
|
|
||
|
|
//protected override void OnPaint(PaintEventArgs e)
|
||
|
|
//{
|
||
|
|
// base.OnPaint(e);
|
||
|
|
|
||
|
|
// var g = e.Graphics;
|
||
|
|
// g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
|
||
|
|
// g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||
|
|
// g.CompositingQuality = CompositingQuality.HighQuality;
|
||
|
|
|
||
|
|
// int intWidth = Math.Min(this.Size.Width, this.Size.Height);
|
||
|
|
// //底圆
|
||
|
|
// g.FillEllipse(new SolidBrush(m_backEllipseColor), new Rectangle(new Point(0, 0), new Size(intWidth, intWidth)));
|
||
|
|
// if (m_showStyleType == ShowStyleType.Ring)
|
||
|
|
// {
|
||
|
|
// //中心圆
|
||
|
|
// int intCore = intWidth - m_valueWidth * 2;
|
||
|
|
// g.FillEllipse(new SolidBrush(m_coreEllipseColor), new Rectangle(new Point(m_valueWidth, m_valueWidth), new Size(intCore, intCore)));
|
||
|
|
// //中心圆边框
|
||
|
|
// if (m_isShowCoreEllipseBorder)
|
||
|
|
// {
|
||
|
|
// g.DrawEllipse(new Pen(m_valueColor, 2), new Rectangle(new Point(m_valueWidth + 1, m_valueWidth + 1), new Size(intCore - 1, intCore - 1)));
|
||
|
|
// }
|
||
|
|
// if (m_valueFloatOrInt == ValueFloatOrInt.Int)
|
||
|
|
// {
|
||
|
|
// if (m_intValue >= 0 && m_maxValue > 0)
|
||
|
|
// {
|
||
|
|
// int fltPercent = (int)m_intValue / (int)m_maxValue;
|
||
|
|
// if (fltPercent > 1)
|
||
|
|
// {
|
||
|
|
// fltPercent = 1;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// g.DrawArc(new Pen(m_valueColor, m_valueWidth - m_valueMargin * 2), new RectangleF(new Point(m_valueWidth / 2 + m_valueMargin / 4, m_valueWidth / 2 + m_valueMargin / 4), new SizeF(intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1), intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1))), -90, fltPercent * 360);
|
||
|
|
|
||
|
|
// string strValueText = m_valueType == ValueType.Percent ? fltPercent.ToString("0%") : m_intValue.ToString();
|
||
|
|
// System.Drawing.SizeF _txtSize = g.MeasureString(strValueText, this.Font);
|
||
|
|
// g.DrawString(strValueText, this.Font, new SolidBrush(this.ForeColor), new PointF((intWidth - _txtSize.Width) / 2 + 1, (intWidth - _txtSize.Height) / 2 + 1));
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// if (m_floatValue >= 0 && m_maxValue > 0)
|
||
|
|
// {
|
||
|
|
// float fltPercent = (float)m_floatValue / (float)m_maxValue;
|
||
|
|
// if (fltPercent > 1f)
|
||
|
|
// {
|
||
|
|
// fltPercent = 1f;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// g.DrawArc(new Pen(m_valueColor, m_valueWidth - m_valueMargin * 2), new RectangleF(new Point(m_valueWidth / 2 + m_valueMargin / 4, m_valueWidth / 2 + m_valueMargin / 4), new SizeF(intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1), intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1))), -90, fltPercent * 360);
|
||
|
|
// string strValueText = m_valueType == ValueType.Percent ? fltPercent.ToString("0%") : m_floatValue.ToString("f2");
|
||
|
|
// System.Drawing.SizeF _txtSize = g.MeasureString(strValueText, this.Font);
|
||
|
|
// g.DrawString(strValueText, this.Font, new SolidBrush(this.ForeColor), new PointF((intWidth - _txtSize.Width) / 2 + 1, (intWidth - _txtSize.Height) / 2 + 1));
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// if (m_valueFloatOrInt == ValueFloatOrInt.Int)
|
||
|
|
// {
|
||
|
|
// if (m_intValue >= 0 && m_maxValue > 0)
|
||
|
|
// {
|
||
|
|
// int fltPercent = (int)m_intValue / (int)m_maxValue;
|
||
|
|
// if (fltPercent > 1)
|
||
|
|
// {
|
||
|
|
// fltPercent = 1;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// g.FillPie(new SolidBrush(m_valueColor), new Rectangle(m_valueMargin, m_valueMargin, intWidth - m_valueMargin * 2, intWidth - m_valueMargin * 2), -90, fltPercent * 360);
|
||
|
|
|
||
|
|
// string strValueText = m_valueType == ValueType.Percent ? fltPercent.ToString("0%") : m_intValue.ToString();
|
||
|
|
// System.Drawing.SizeF _txtSize = g.MeasureString(strValueText, this.Font);
|
||
|
|
// g.DrawString(strValueText, this.Font, new SolidBrush(this.ForeColor), new PointF((intWidth - _txtSize.Width) / 2 + 1, (intWidth - _txtSize.Height) / 2 + 1));
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// if (m_floatValue >= 0 && m_maxValue > 0)
|
||
|
|
// {
|
||
|
|
// float fltPercent = (float)m_floatValue / (float)m_maxValue;
|
||
|
|
// if (fltPercent > 1f)
|
||
|
|
// {
|
||
|
|
// fltPercent = 1f;
|
||
|
|
// }
|
||
|
|
|
||
|
|
// g.FillPie(new SolidBrush(m_valueColor), new Rectangle(m_valueMargin, m_valueMargin, intWidth - m_valueMargin * 2, intWidth - m_valueMargin * 2), -90, fltPercent * 360);
|
||
|
|
// string strValueText = m_valueType == ValueType.Percent ? fltPercent.ToString("0%") : m_floatValue.ToString("f2");
|
||
|
|
// System.Drawing.SizeF _txtSize = g.MeasureString(strValueText, this.Font);
|
||
|
|
// g.DrawString(strValueText, this.Font, new SolidBrush(this.ForeColor), new PointF((intWidth - _txtSize.Width) / 2 + 1, (intWidth - _txtSize.Height) / 2 + 1));
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// }
|
||
|
|
|
||
|
|
#region 核心优化方法
|
||
|
|
/// <summary>
|
||
|
|
/// 初始化绘图对象
|
||
|
|
/// </summary>
|
||
|
|
private void InitDrawingObjects()
|
||
|
|
{
|
||
|
|
_backEllipseBrush = new SolidBrush(m_backEllipseColor);
|
||
|
|
_coreEllipseBrush = new SolidBrush(m_coreEllipseColor);
|
||
|
|
_valueBrush = new SolidBrush(m_valueColor);
|
||
|
|
_foreColorBrush = new SolidBrush(m_foreColor);
|
||
|
|
_coreEllipsePen = new Pen(m_valueColor, 2);
|
||
|
|
_valueArcPen = new Pen(m_valueColor, m_valueWidth - m_valueMargin * 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 延迟刷新
|
||
|
|
/// </summary>
|
||
|
|
private void ScheduleRefresh()
|
||
|
|
{
|
||
|
|
if (_isRefreshPending) return;
|
||
|
|
_isRefreshPending = true;
|
||
|
|
|
||
|
|
// 先判断控件句柄是否已创建
|
||
|
|
if (!this.IsHandleCreated)
|
||
|
|
{
|
||
|
|
// 句柄未创建时:
|
||
|
|
// 1. 注册句柄创建完成的事件,创建后再刷新
|
||
|
|
this.HandleCreated += ProcessEllipse_HandleCreated;
|
||
|
|
// 2. 直接调用Invalidate(句柄未创建时Invalidate无副作用)
|
||
|
|
this.Invalidate();
|
||
|
|
_isRefreshPending = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 句柄已创建时,使用BeginInvoke延迟刷新
|
||
|
|
try
|
||
|
|
{
|
||
|
|
this.BeginInvoke(new Action(() =>
|
||
|
|
{
|
||
|
|
// 双重校验:避免跨线程/句柄释放导致的异常
|
||
|
|
if (this.IsDisposed || !this.IsHandleCreated)
|
||
|
|
{
|
||
|
|
_isRefreshPending = false;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
this.Invalidate();
|
||
|
|
_isRefreshPending = false;
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
catch (ObjectDisposedException)
|
||
|
|
{
|
||
|
|
// 控件已释放时,重置标识
|
||
|
|
_isRefreshPending = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 句柄创建完成后触发的刷新逻辑
|
||
|
|
/// </summary>
|
||
|
|
private void ProcessEllipse_HandleCreated(object sender, EventArgs e)
|
||
|
|
{
|
||
|
|
// 取消事件注册,避免重复触发
|
||
|
|
this.HandleCreated -= ProcessEllipse_HandleCreated;
|
||
|
|
// 句柄创建完成后,执行一次刷新
|
||
|
|
if (!_isRefreshPending)
|
||
|
|
{
|
||
|
|
this.Invalidate();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 更新最大值
|
||
|
|
/// </summary>
|
||
|
|
private void UpdataMaxValue()
|
||
|
|
{
|
||
|
|
switch (m_showType)
|
||
|
|
{
|
||
|
|
case ShowType.PPM:
|
||
|
|
case ShowType.稼动率:
|
||
|
|
m_maxValue = 100;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region 重写OnPaint(复用绘图对象 + 优化逻辑)
|
||
|
|
protected override void OnPaint(PaintEventArgs e)
|
||
|
|
{
|
||
|
|
base.OnPaint(e);
|
||
|
|
|
||
|
|
var g = e.Graphics;
|
||
|
|
// 优化绘图质量(只设置一次,避免重复赋值)
|
||
|
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||
|
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||
|
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
||
|
|
g.Clear(BackColor); // 统一清背景,减少闪烁
|
||
|
|
|
||
|
|
int intWidth = Math.Min(Size.Width, Size.Height);
|
||
|
|
if (intWidth == 0) return; // 避免除以0
|
||
|
|
|
||
|
|
// 绘制底圆(复用画刷)
|
||
|
|
g.FillEllipse(_backEllipseBrush, new Rectangle(0, 0, intWidth, intWidth));
|
||
|
|
|
||
|
|
if (m_showStyleType == ShowStyleType.Ring)
|
||
|
|
{
|
||
|
|
// 绘制中心圆(复用画刷)
|
||
|
|
int intCore = intWidth - m_valueWidth * 2;
|
||
|
|
g.FillEllipse(_coreEllipseBrush, new Rectangle(m_valueWidth, m_valueWidth, intCore, intCore));
|
||
|
|
|
||
|
|
// 绘制中心圆边框(复用画笔)
|
||
|
|
if (m_isShowCoreEllipseBorder)
|
||
|
|
{
|
||
|
|
g.DrawEllipse(_coreEllipsePen, new Rectangle(m_valueWidth + 1, m_valueWidth + 1, intCore - 1, intCore - 1));
|
||
|
|
}
|
||
|
|
|
||
|
|
// 绘制数值圆弧/文字
|
||
|
|
DrawValueContent(g, intWidth);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
// 绘制扇形样式
|
||
|
|
DrawSectorContent(g, intWidth);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 绘制圆环样式的数值内容(复用逻辑)
|
||
|
|
/// </summary>
|
||
|
|
private void DrawValueContent(Graphics g, int intWidth)
|
||
|
|
{
|
||
|
|
float percent = 0f;
|
||
|
|
string strValueText = string.Empty;
|
||
|
|
|
||
|
|
if (m_valueFloatOrInt == ValueFloatOrInt.Int)
|
||
|
|
{
|
||
|
|
if (m_intValue >= 0 && m_maxValue > 0)
|
||
|
|
{
|
||
|
|
percent = (float)m_intValue / m_maxValue;
|
||
|
|
percent = Math.Min(percent, 1f);
|
||
|
|
strValueText = m_valueType == ValueType.Percent ? percent.ToString("0%") : m_intValue.ToString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (m_floatValue >= 0 && m_maxValue > 0)
|
||
|
|
{
|
||
|
|
percent = m_floatValue / m_maxValue;
|
||
|
|
percent = Math.Min(percent, 1f);
|
||
|
|
strValueText = m_valueType == ValueType.Percent ? percent.ToString("0%") : m_floatValue.ToString("f2");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 绘制圆弧(复用画笔)
|
||
|
|
if (percent > 0)
|
||
|
|
{
|
||
|
|
var arcRect = new RectangleF(
|
||
|
|
m_valueWidth / 2 + m_valueMargin / 4,
|
||
|
|
m_valueWidth / 2 + m_valueMargin / 4,
|
||
|
|
intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1),
|
||
|
|
intWidth - m_valueWidth - m_valueMargin / 2 + (m_valueMargin == 0 ? 0 : 1));
|
||
|
|
g.DrawArc(_valueArcPen, arcRect, -90, percent * 360);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 绘制文字(复用画刷)
|
||
|
|
if (!string.IsNullOrEmpty(strValueText))
|
||
|
|
{
|
||
|
|
var txtSize = g.MeasureString(strValueText, Font);
|
||
|
|
g.DrawString(strValueText, Font, _foreColorBrush,
|
||
|
|
(intWidth - txtSize.Width) / 2 + 1,
|
||
|
|
(intWidth - txtSize.Height) / 2 + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 绘制扇形样式的数值内容(复用逻辑)
|
||
|
|
/// </summary>
|
||
|
|
private void DrawSectorContent(Graphics g, int intWidth)
|
||
|
|
{
|
||
|
|
float percent = 0f;
|
||
|
|
string strValueText = string.Empty;
|
||
|
|
|
||
|
|
if (m_valueFloatOrInt == ValueFloatOrInt.Int)
|
||
|
|
{
|
||
|
|
if (m_intValue >= 0 && m_maxValue > 0)
|
||
|
|
{
|
||
|
|
percent = (float)m_intValue / m_maxValue;
|
||
|
|
percent = Math.Min(percent, 1f);
|
||
|
|
strValueText = m_valueType == ValueType.Percent ? percent.ToString("0%") : m_intValue.ToString();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (m_floatValue >= 0 && m_maxValue > 0)
|
||
|
|
{
|
||
|
|
percent = m_floatValue / m_maxValue;
|
||
|
|
percent = Math.Min(percent, 1f);
|
||
|
|
strValueText = m_valueType == ValueType.Percent ? percent.ToString("0%") : m_floatValue.ToString("f2");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 绘制扇形(复用画刷)
|
||
|
|
if (percent > 0)
|
||
|
|
{
|
||
|
|
var pieRect = new Rectangle(m_valueMargin, m_valueMargin,
|
||
|
|
intWidth - m_valueMargin * 2, intWidth - m_valueMargin * 2);
|
||
|
|
g.FillPie(_valueBrush, pieRect, -90, percent * 360);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 绘制文字(复用画刷)
|
||
|
|
if (!string.IsNullOrEmpty(strValueText))
|
||
|
|
{
|
||
|
|
var txtSize = g.MeasureString(strValueText, Font);
|
||
|
|
g.DrawString(strValueText, Font, _foreColorBrush,
|
||
|
|
(intWidth - txtSize.Width) / 2 + 1,
|
||
|
|
(intWidth - txtSize.Height) / 2 + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region 释放资源(避免内存泄漏)
|
||
|
|
protected override void Dispose(bool disposing)
|
||
|
|
{
|
||
|
|
if (disposing)
|
||
|
|
{
|
||
|
|
// 释放缓存的绘图对象
|
||
|
|
_backEllipseBrush?.Dispose();
|
||
|
|
_coreEllipseBrush?.Dispose();
|
||
|
|
_valueBrush?.Dispose();
|
||
|
|
_foreColorBrush?.Dispose();
|
||
|
|
_coreEllipsePen?.Dispose();
|
||
|
|
_valueArcPen?.Dispose();
|
||
|
|
m_font?.Dispose(); // 释放字体
|
||
|
|
components?.Dispose();
|
||
|
|
}
|
||
|
|
base.Dispose(disposing);
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public enum ShowType
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// PPM
|
||
|
|
/// </summary>
|
||
|
|
PPM,
|
||
|
|
/// <summary>
|
||
|
|
/// 数值
|
||
|
|
/// </summary>
|
||
|
|
稼动率,
|
||
|
|
/// <summary>
|
||
|
|
///
|
||
|
|
/// </summary>
|
||
|
|
生产数
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
public enum ValueType
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 百分比
|
||
|
|
/// </summary>
|
||
|
|
Percent,
|
||
|
|
/// <summary>
|
||
|
|
/// 数值
|
||
|
|
/// </summary>
|
||
|
|
Absolute
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum ValueFloatOrInt
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 整数
|
||
|
|
/// </summary>
|
||
|
|
Int,
|
||
|
|
/// <summary>
|
||
|
|
/// 浮点数
|
||
|
|
/// </summary>
|
||
|
|
Float
|
||
|
|
}
|
||
|
|
|
||
|
|
public enum ShowStyleType
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 圆环
|
||
|
|
/// </summary>
|
||
|
|
Ring,
|
||
|
|
/// <summary>
|
||
|
|
/// 扇形
|
||
|
|
/// </summary>
|
||
|
|
Sector
|
||
|
|
}
|
||
|
|
}
|