添加项目文件。
This commit is contained in:
@@ -0,0 +1,521 @@
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user