Files
1257B_DB/JinYuan.ControlLib/StatusExt.cs
T
2026-08-06 09:23:30 +08:00

522 lines
18 KiB
C#

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 处理外部数据的方法
/// <summary>
/// 绑定数据,设置 UI 内容
/// </summary>
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<StatusItemClickEventArgs> 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
}
}