using Controls; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Threading.Tasks; using System.Windows.Forms; namespace JinYuan.ControlLib { #region 枚举定义 public enum StatusEnum { Init, //初始化状态 - 空白,无填充 GradeNG, // 等级查询OK状态 - 白底:黑色系渐变; 黑底:黄色系渐变? PackNG, // 上传NG状态 - 红色系渐变 Normal // 正常状态 - 绿色系渐变 } #endregion public partial class StatusExt : UserControl { // 公开属性,电芯条码用于绑定唯一标识 public string ItemId { get; set; } // 电芯位置 public string RowId { get; set; } #region 私有字段 private StatusEnum _currentStatus = StatusEnum.Init; private Color _borderColor = Color.DarkGray; private int _borderWidth = 1; private bool _showHighlight = false; private const int padding = 2; // 外部留白 private static readonly Color _backBlackColor = Color.FromArgb(11, 20, 36); //private static readonly Color _backWhiteColor = Color.FromArgb(255, 255, 255); //private Color _backColor = _backBlackColor; #endregion #region 颜色配置 private readonly Color _whiteEdge = Color.FromArgb(200, 200, 200); // 白色边缘 private readonly Color _greenEdge = Color.FromArgb(50, 150, 50); // 绿色边缘 private readonly Color _greenMid = Color.FromArgb(140, 180, 130); // 绿色过渡 private readonly Color _grayEdge = Color.FromArgb(0, 0, 0); // 黑色边缘 private readonly Color _grayMid = Color.FromArgb(135, 135, 135); // 灰色过渡 private readonly Color _redEdge = Color.FromArgb(150, 60, 60); // 红色边缘 private readonly Color _redMid = Color.FromArgb(170, 140, 130); // 红色过渡 private readonly Color _center = Color.FromArgb(245, 245, 245); // 中心色(稍暗避免过曝) private readonly Color _highlightStart = Color.FromArgb(120, Color.White); // 高光起始色 private readonly Color _highlightEnd = Color.FromArgb(0, Color.White); // 高光结束色 #endregion private bool _isClicking = false; private DateTime _lastClickTime; // 缓存渐变画刷,避免重复创建 private GraphicsPath _cachedPath; private Rectangle _lastDrawRect; private bool _clickHandled = false; #region 构造函数 public StatusExt() { this.Text = string.Empty; // 清空文本 //SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | //ControlStyles.Opaque | // 避免背景重绘干扰 ControlStyles.SupportsTransparentBackColor, true); this.DoubleBuffered = true; this.Size = new Size(40, 40); // 确保正方形 this.MinimumSize = new Size(20, 20); this.MaximumSize = new Size(60, 60); // 设置最大尺寸 this.BackColor = _backBlackColor; } //private void InitializeBrushCache() //{ // _brushCache[StatusEnum.Init] = new SolidBrush(Color.Transparent); // _brushCache[StatusEnum.Normal] = new LinearGradientBrush( // new Rectangle(0, 0, 100, 100), // Color.FromArgb(50, 150, 50), // Color.FromArgb(140, 180, 130), // 45f); // _brushCache[StatusEnum.GradeNG] = new LinearGradientBrush( // new Rectangle(0, 0, 100, 100), // Color.FromArgb(0, 0, 0), // Color.FromArgb(135, 135, 135), // 45f); // _brushCache[StatusEnum.PackNG] = new LinearGradientBrush( // new Rectangle(0, 0, 100, 100), // Color.FromArgb(150, 60, 60), // Color.FromArgb(170, 140, 130), // 45f); //} #endregion #region 处理外部数据的方法 /// /// 绑定数据,设置 UI 内容 /// public void BindData(string id, string rowId, string title, StatusEnum status) { this.ItemId = id; this.RowId = rowId; this.CurrentStatus = status; } public void SetStatus(StatusEnum status) { if (_currentStatus != status) { _currentStatus = status; Invalidate(); // 状态变化时重绘 } } #endregion #region 属性 [Category("工业风"), Description("当前状态")] public StatusEnum CurrentStatus { get => _currentStatus; set { if (_currentStatus != value) { _currentStatus = value; Invalidate(); // 只有变化时才重绘 } } } [Category("工业风"), Description("边框宽度")] public int BorderWidth { get => _borderWidth; set { _borderWidth = value; Invalidate(); } } [Category("工业风"), Description("边框颜色")] public Color BorderColor { get { return _borderColor; } set { _borderColor = value; Invalidate(); } } [Category("工业风"), Description("是否显示高光效果")] public bool ShowHighlight { get { return _showHighlight; } set { _showHighlight = value; Invalidate(); } } #endregion #region 重写方法 protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); var g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; // 抗锯齿,圆形更平滑 g.PixelOffsetMode = PixelOffsetMode.HighQuality; // 减少模糊 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //g.SmoothingMode = SmoothingMode.HighSpeed; // 改用高速渲染 //g.CompositingQuality = CompositingQuality.HighSpeed; // === 关键:有效直径要扣除两边的边框宽度 === int availableSize = Math.Min(Width, Height); int drawDiameter = availableSize - _borderWidth - padding * 2; // 确保左右各留出 1~2 像素给边框 if (drawDiameter <= 0) drawDiameter = 1; // 防止负数 // 居中定位 int x = (Width - drawDiameter) / 2; int y = (Height - drawDiameter) / 2; var drawRect = new Rectangle(x, y, drawDiameter, drawDiameter); //// 绘制背景圆形 //DrawBackgroundCircle(g, drawRect); //// 绘制边框 //DrawBorder(g, drawRect); // 只在尺寸变化时重建路径 if (_cachedPath == null || _lastDrawRect != drawRect) { _cachedPath?.Dispose(); _cachedPath = new GraphicsPath(); _cachedPath.AddEllipse(drawRect); _lastDrawRect = drawRect; } // 根据状态绘制渐变背景 DrawStatusBackground(g, drawRect); // 绘制高光效果 if (_showHighlight && _currentStatus != StatusEnum.Init) { DrawHighlightEffect(g, drawRect); } // 绘制边框 DrawBorder(g, drawRect); //// 使用缓存画刷 //if (_brushCache.TryGetValue(_currentStatus, out var brush)) //{ // g.FillPath(brush, _cachedPath); //} //// 绘制边框 //using (Pen borderPen = new Pen(GetBorderColor(), _borderWidth)) //{ // borderPen.Alignment = PenAlignment.Center; // g.DrawEllipse(borderPen, drawRect); //} } // 确保控件保持正方形 protected override void OnResize(EventArgs e) { base.OnResize(e); // 强制保持正方形 int size = Math.Min(Width, Height); this.Size = new Size(size, size); Invalidate(); } protected override void OnClick(EventArgs e) { // 防重复触发 if (_isClicking || (DateTime.Now - _lastClickTime).TotalMilliseconds < 300) { return; } _isClicking = true; _lastClickTime = DateTime.Now; try { StatusExtClicked?.Invoke(this, new StatusItemClickEventArgs(this.ItemId, this.CurrentStatus, this.RowId, this.Name)); base.OnClick(e); } finally { // 使用异步延迟重置,避免阻塞UI Task.Delay(300).ContinueWith(_ => { if (!IsDisposed) { SafeInvoke(() => _isClicking = false); } }); } } #endregion #region 私有绘制方法 //private void DrawBackgroundCircle(Graphics g, Rectangle rect) //{ // var (edgeColor, midColor) = GetStatusColor(); // using (GraphicsPath path = CreateCirclePath(rect)) // { // using (PathGradientBrush brush = new PathGradientBrush(path)) // { // brush.CenterColor = _center; // brush.SurroundColors = new Color[] { edgeColor }; // brush.FocusScales = new PointF(0.1f, 0.1f); // g.FillPath(brush, path); // } // } //} //// 绘制高光效果 //private void DrawHighlightEffect(Graphics g, Rectangle rect) //{ // // 高光区域(右上角的椭圆) // int highlightSize = rect.Width / 3; // Rectangle highlightRect = new Rectangle( // rect.X + rect.Width / 6, // rect.Y + rect.Height / 6, // highlightSize, // highlightSize // ); // // 创建半透明高光渐变 // using (LinearGradientBrush highlightBrush = new LinearGradientBrush( // highlightRect, // Color.FromArgb(120, Color.White), // Color.FromArgb(0, Color.White), // 45f)) // { // g.FillEllipse(highlightBrush, highlightRect); // } // // 中心小圆高光(增强中心亮度) // int centerHighlightSize = rect.Width / 5; // Rectangle centerRect = new Rectangle( // rect.X + (rect.Width - centerHighlightSize) / 2, // rect.Y + (rect.Height - centerHighlightSize) / 2, // centerHighlightSize, // centerHighlightSize // ); // using (SolidBrush centerBrush = new SolidBrush(Color.FromArgb(80, Color.White))) // { // g.FillEllipse(centerBrush, centerRect); // } //} //private void DrawBorder(Graphics g, Rectangle rect) //{ // var (edgeColor, _) = GetStatusColor(); // using (Pen borderPen = new Pen(edgeColor, _borderWidth)) // { // borderPen.Alignment = PenAlignment.Center; // 明确居中 // g.DrawEllipse(borderPen, rect); // } //} private void DrawStatusBackground(Graphics g, Rectangle rect) { var (edgeColor, midColor) = GetStatusColor(); // 绘制渐变背景 using (PathGradientBrush brush = new PathGradientBrush(_cachedPath)) { brush.CenterColor = _center; brush.SurroundColors = new Color[] { edgeColor }; brush.FocusScales = new PointF(0.1f, 0.1f); g.FillPath(brush, _cachedPath); // 添加中间渐变层增强效果 if (_currentStatus != StatusEnum.Init) { using (SolidBrush midBrush = new SolidBrush(Color.FromArgb(50, midColor))) { int innerSize = rect.Width / 2; Rectangle innerRect = new Rectangle( rect.X + (rect.Width - innerSize) / 2, rect.Y + (rect.Height - innerSize) / 2, innerSize, innerSize); g.FillEllipse(midBrush, innerRect); } } } } private void DrawHighlightEffect(Graphics g, Rectangle rect) { // 主高光区域(右上角) int highlightSize = rect.Width / 3; Rectangle highlightRect = new Rectangle( rect.X + rect.Width / 6, rect.Y + rect.Height / 6, highlightSize, highlightSize); using (LinearGradientBrush highlightBrush = new LinearGradientBrush( highlightRect, _highlightStart, _highlightEnd, 45f)) { g.FillEllipse(highlightBrush, highlightRect); } // 中心高光点 int centerHighlightSize = rect.Width / 5; Rectangle centerRect = new Rectangle( rect.X + (rect.Width - centerHighlightSize) / 2, rect.Y + (rect.Height - centerHighlightSize) / 2, centerHighlightSize, centerHighlightSize); using (SolidBrush centerBrush = new SolidBrush(Color.FromArgb(80, Color.White))) { g.FillEllipse(centerBrush, centerRect); } // 边缘光泽效果 using (Pen glowPen = new Pen(Color.FromArgb(30, Color.White), 1)) { g.DrawEllipse(glowPen, rect); } } private void DrawBorder(Graphics g, Rectangle rect) { var (edgeColor, _) = GetStatusColor(); // 外边框 using (Pen outerPen = new Pen(Color.FromArgb(80, edgeColor), _borderWidth + 1)) { outerPen.Alignment = PenAlignment.Inset; g.DrawEllipse(outerPen, rect); } // 内边框 using (Pen innerPen = new Pen(Color.FromArgb(150, edgeColor), _borderWidth)) { innerPen.Alignment = PenAlignment.Inset; Rectangle innerRect = new Rectangle( rect.X + 1, rect.Y + 1, rect.Width - 2, rect.Height - 2); g.DrawEllipse(innerPen, innerRect); } } private (Color, Color) GetStatusColor() { switch (_currentStatus) { case StatusEnum.PackNG: return (_redEdge, _redMid); case StatusEnum.GradeNG: return (_grayEdge, _grayMid); case StatusEnum.Normal: return (_greenEdge, _greenMid); default: // Init return (_whiteEdge, Color.FromArgb(50, 50, 50)); } } private void SafeInvoke(Action action) { if (IsHandleCreated && !IsDisposed) { if (InvokeRequired) { try { Invoke(action); } catch { } } else { action(); } } } //private Color GetBorderColor() //{ // var (edgeColor, midColor) = GetStatusColor(); // return edgeColor; //} //private GraphicsPath CreateCirclePath(Rectangle rect) //{ // GraphicsPath path = new GraphicsPath(); // path.AddEllipse(rect); // return path; //} //private (Color, Color) GetStatusColor() //{ // switch (_currentStatus) // { // case StatusEnum.PackNG: // return (_redEdge, _redMid); // case StatusEnum.GradeNG: // return (_grayEdge, _grayMid); // case StatusEnum.Normal: // return (_greenEdge, _greenMid); // default: // return (_whiteEdge, _whiteEdge); // } //} #endregion #region 事件 public event EventHandler StatusExtClicked; // 自定义事件参数,用于传递点击的 ID 和状态 public class StatusItemClickEventArgs : EventArgs { public string ItemId { get; } public string RowId { get; } public string Name { get; } public StatusEnum Status { get; } public StatusItemClickEventArgs(string itemId, StatusEnum status, string rowId, string name) { ItemId = itemId; Status = status; RowId = rowId; Name = Name; } } #endregion } }