文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。
相关链接:
推荐链接:
开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客
开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客
开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客
开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客
开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客
开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客
开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客
开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客
开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客
本章节主要内容是:编写仪表盘控件从而实现工业仪表的显示。这个仪表盘控件展示了完整的自定义控件开发流程,从图形绘制到用户交互,是一个功能完善的工业级控件实现。
目录:
1.源码分析
2.所有源码
3.效果演示
一、源码分析
分为两个主要部分:DashboardControl
自定义控件和 Form1
测试窗体。
- DashboardControl 自定义控件分析
1.1 属性和字段设计
字段定义:
private float _minValue = 0; // 最小值
private float _maxValue = 100; // 最大值
private float _currentValue = 0; // 当前值
private float _warningValue = 80; // 警告阈值
private float _dangerValue = 90; // 危险阈值
属性封装特点:
所有属性都调用 Invalidate() 方法,实现属性变化时自动重绘
CurrentValue 属性使用 Math.Max 和 Math.Min 进行范围约束
1.2 构造函数关键设置
public DashboardControl()
{
// 双缓冲和控件样式设置
this.DoubleBuffered = true;
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.Opaque, true); // 关键:避免闪烁
}
1.3 核心绘图方法分析
OnPaint 方法 - 主绘制入口
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias; // 抗锯齿
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
// 绘制顺序:背景 → 表盘 → 刻度 → 指针 → 文本
}
DrawDial 方法 - 表盘绘制
private void DrawDial(Graphics g, RectangleF dialRect)
{
// 1. 填充表盘底色
g.FillEllipse(brush, dialRect);
// 2. 创建渐变效果(高光)
using (PathGradientBrush pgb = new PathGradientBrush(path))
{
pgb.CenterColor = Color.FromArgb(100, 255, 255, 255); // 半透明白色
pgb.SurroundColors = new Color[] { Color.Transparent };
}
// 3. 绘制彩色区域(正常/警告/危险)
DrawColorZones(g, dialRect);
// 4. 绘制外边框
g.DrawEllipse(borderPen, dialRect);
}
DrawColorZones 方法 - 彩色区域绘制
private void DrawColorZones(Graphics g, RectangleF dialRect)
{
float startAngle = 135; // 起始角度(左下)
float sweepAngle = 270; // 扫描角度(270度圆弧)
// 计算各区域角度范围
float normalSweep = (_warningValue - _minValue) / (_maxValue - _minValue) * sweepAngle;
float warningSweep = (_dangerValue - _warningValue) / (_maxValue - _minValue) * sweepAngle;
float dangerSweep = (_maxValue - _dangerValue) / (_maxValue - _minValue) * sweepAngle;
// 分别绘制三个区域
DrawZone(g, dialRect, startAngle, normalSweep, Color.Green);
DrawZone(g, dialRect, startAngle + normalSweep, warningSweep, _warningColor);
DrawZone(g, dialRect, startAngle + normalSweep + warningSweep, dangerSweep, _dangerColor);
}
DrawScales 方法 - 刻度绘制
private void DrawScales(Graphics g, RectangleF dialRect)
{
// 极坐标计算刻度位置
PointF center = new PointF(dialRect.X + dialRect.Width / 2, dialRect.Y + dialRect.Height / 2);
float radius = dialRect.Width / 2;
for (int i = 0; i <= majorDivisions; i++)
{
// 角度计算(极坐标转直角坐标)
float angle = startAngle + (sweepAngle / majorDivisions) * i;
float radian = angle * (float)Math.PI / 180;
// 计算内外端点
PointF outerPoint = new PointF(
center.X + radius * (float)Math.Cos(radian),
center.Y + radius * (float)Math.Sin(radian));
// 绘制主刻度和数值标签
}
}
DrawPointer 方法 - 指针绘制
- Form1 测试窗体分析
2.1 控件初始化
private void SetupDashboard()
{
dashboard = new DashboardControl();
dashboard.Location = new Point(50, 50);
dashboard.Size = new Size(400, 400);
dashboard.Title = "速度表";
dashboard.Unit = "km/h";
// ... 属性设置
}
2.2 控制面板构建
窗体右侧创建了完整的控制面板:
控件类型:
NumericUpDown:数值输入控制
TrackBar:滑块控制
ComboBox:颜色选择
Button:操作控制
Label:状态显示
2.3 数据绑定和事件处理
// 数值变化同步更新
nudCurrentValue.ValueChanged += delegate {
dashboard.CurrentValue = (float)nudCurrentValue.Value;
trbValue.Value = (int)nudCurrentValue.Value; // 同步滑块
};
// 滑块事件
trbValue.Scroll += delegate {
dashboard.CurrentValue = trbValue.Value;
nudCurrentValue.Value = trbValue.Value; // 同步数值框
};
2.4 定时器模拟功能
private void SetupTimer()
{
updateTimer = new System.Timers.Timer(100); // 100ms间隔
updateTimer.Elapsed += OnTimerElapsed;
updateTimer.SynchronizingObject = this; // 关键:线程安全
}
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
// 带缓动效果的数值变化
float targetValue = 50 + (float)(Math.Sin(DateTime.Now.Ticks * 0.0000001) * 70);
float newValue = currentValue + (targetValue - currentValue) * 0.1f; // 缓动插值
}
- 技术亮点
3.1 图形绘制优化
双缓冲技术:DoubleBuffered = true 避免闪烁
抗锯齿:SmoothingMode.AntiAlias 提升视觉效果
路径渐变:PathGradientBrush 创建立体效果
3.2 数学计算精确
极坐标转换:准确计算刻度和指针位置
角度映射:将数值范围映射到270度圆弧
范围约束:确保数值在有效范围内
3.3 用户体验设计
实时响应:所有属性变化立即重绘
多种控制方式:数值框、滑块、按钮、定时器
状态反馈:实时显示当前状态和数值
二、所有源码
DashboardControl.cs文件源码
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace _4_dashboard
{
public class DashboardControl : Control
{
#region 属性和字段
// 仪表盘设置
private float _minValue = 0;
private float _maxValue = 100;
private float _currentValue = 0;
private float _warningValue = 80;
private float _dangerValue = 90;
// 外观设置 - 修改默认背景色
private Color _backgroundColor = Color.Black; // 改为不透明颜色
private Color _dialColor = Color.FromArgb(30, 30, 30);
private Color _scaleColor = Color.White;
private Color _pointerColor = Color.Red;
private Color _warningColor = Color.Orange;
private Color _dangerColor = Color.Red;
private Color _valueColor = Color.White;
private Color _titleColor = Color.LightGray;
// 字体
private Font _valueFont;
private Font _titleFont;
private Font _scaleFont;
// 文本
private string _title = "仪表盘";
private string _unit = "单位";
// 尺寸比例
private float _dialThickness = 0.1f;
private float _pointerLength = 0.7f;
private float _pointerWidth = 0.02f;
#endregion
#region 属性公开接口
public float MinValue
{
get { return _minValue; }
set { _minValue = value; Invalidate(); }
}
public float MaxValue
{
get { return _maxValue; }
set { _maxValue = value; Invalidate(); }
}
public float CurrentValue
{
get { return _currentValue; }
set
{
_currentValue = Math.Max(_minValue, Math.Min(_maxValue, value));
Invalidate();
}
}
public float WarningValue
{
get { return _warningValue; }
set { _warningValue = value; Invalidate(); }
}
public float DangerValue
{
get { return _dangerValue; }
set { _dangerValue = value; Invalidate(); }
}
public Color BackgroundColor
{
get { return _backgroundColor; }
set { _backgroundColor = value; Invalidate(); }
}
public Color DialColor
{
get { return _dialColor; }
set { _dialColor = value; Invalidate(); }
}
public Color PointerColor
{
get { return _pointerColor; }
set { _pointerColor = value; Invalidate(); }
}
public Color ScaleColor
{
get { return _scaleColor; }
set { _scaleColor = value; Invalidate(); }
}
public string Title
{
get { return _title; }
set { _title = value; Invalidate(); }
}
public string Unit
{
get { return _unit; }
set { _unit = value; Invalidate(); }
}
public Color WarningColor
{
get { return _warningColor; }
set { _warningColor = value; Invalidate(); }
}
public Color DangerColor
{
get { return _dangerColor; }
set { _dangerColor = value; Invalidate(); }
}
#endregion
#region 构造函数
public DashboardControl()
{
// 初始化字体
_valueFont = new Font("Arial", 16, FontStyle.Bold);
_titleFont = new Font("Arial", 12);
_scaleFont = new Font("Arial", 8);
this.DoubleBuffered = true;
// 修复:使用不透明的背景色
this.BackColor = Color.Black; // 改为不透明颜色
this.Size = new Size(200, 200);
// 设置控件样式,确保正确绘制
SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer |
ControlStyles.ResizeRedraw |
ControlStyles.Opaque, true); // 添加 Opaque 样式
}
#endregion
#region 绘图方法
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
// 先清除背景
using (SolidBrush backgroundBrush = new SolidBrush(_backgroundColor))
{
g.FillRectangle(backgroundBrush, this.ClientRectangle);
}
// 计算仪表盘尺寸和位置
int size = Math.Min(Width, Height) - 20;
if (size <= 0) return; // 添加安全检查
int x = (Width - size) / 2;
int y = (Height - size) / 2;
RectangleF dialRect = new RectangleF(x, y, size, size);
// 绘制表盘
DrawDial(g, dialRect);
// 绘制刻度
DrawScales(g, dialRect);
// 绘制指针
DrawPointer(g, dialRect);
// 绘制数值和标题
DrawText(g, dialRect);
}
private void DrawDial(Graphics g, RectangleF dialRect)
{
// 绘制表盘底色
using (SolidBrush brush = new SolidBrush(_dialColor))
{
g.FillEllipse(brush, dialRect);
}
// 绘制渐变效果
using (GraphicsPath path = new GraphicsPath())
{
path.AddEllipse(dialRect);
using (PathGradientBrush pgb = new PathGradientBrush(path))
{
pgb.CenterPoint = new PointF(
dialRect.X + dialRect.Width * 0.3f,
dialRect.Y + dialRect.Height * 0.3f);
pgb.CenterColor = Color.FromArgb(100, 255, 255, 255);
pgb.SurroundColors = new Color[] { Color.Transparent };
g.FillEllipse(pgb, dialRect);
}
}
// 绘制刻度区域(彩色圆弧)
DrawColorZones(g, dialRect);
// 绘制外边框
using (Pen borderPen = new Pen(Color.FromArgb(100, 255, 255, 255), 2f))
{
g.DrawEllipse(borderPen, dialRect);
}
}
private void DrawColorZones(Graphics g, RectangleF dialRect)
{
float startAngle = 135;
float sweepAngle = 270;
// 检查除零错误
if (_maxValue - _minValue <= 0) return;
// 正常区域(绿色)
float normalSweep = (_warningValue - _minValue) / (_maxValue - _minValue) * sweepAngle;
if (normalSweep > 0)
DrawZone(g, dialRect, startAngle, normalSweep, Color.Green);
// 警告区域(橙色)
float warningSweep = (_dangerValue - _warningValue) / (_maxValue - _minValue) * sweepAngle;
if (warningSweep > 0)
DrawZone(g, dialRect, startAngle + normalSweep, warningSweep, _warningColor);
// 危险区域(红色)
float dangerSweep = (_maxValue - _dangerValue) / (_maxValue - _minValue) * sweepAngle;
if (dangerSweep > 0)
DrawZone(g, dialRect, startAngle + normalSweep + warningSweep, dangerSweep, _dangerColor);
}
private void DrawZone(Graphics g, RectangleF dialRect, float startAngle, float sweepAngle, Color color)
{
if (sweepAngle <= 0) return;
float penWidth = dialRect.Width * _dialThickness;
if (penWidth <= 0) return;
RectangleF zoneRect = new RectangleF(
dialRect.X + penWidth / 2,
dialRect.Y + penWidth / 2,
dialRect.Width - penWidth,
dialRect.Height - penWidth);
using (Pen zonePen = new Pen(color, penWidth))
{
zonePen.StartCap = LineCap.Round;
zonePen.EndCap = LineCap.Round;
g.DrawArc(zonePen, zoneRect, startAngle, sweepAngle);
}
}
private void DrawScales(Graphics g, RectangleF dialRect)
{
float startAngle = 135;
float sweepAngle = 270;
int majorDivisions = 10;
int minorDivisions = 5;
float penWidth = dialRect.Width * 0.01f;
float majorTickLength = dialRect.Width * 0.05f;
float minorTickLength = dialRect.Width * 0.025f;
using (Pen majorPen = new Pen(_scaleColor, penWidth * 2))
using (Pen minorPen = new Pen(_scaleColor, penWidth))
using (SolidBrush textBrush = new SolidBrush(_scaleColor))
{
PointF center = new PointF(dialRect.X + dialRect.Width / 2, dialRect.Y + dialRect.Height / 2);
float radius = dialRect.Width / 2;
for (int i = 0; i <= majorDivisions; i++)
{
float angle = startAngle + (sweepAngle / majorDivisions) * i;
float radian = angle * (float)Math.PI / 180;
// 主刻度
PointF outerPoint = new PointF(
center.X + radius * (float)Math.Cos(radian),
center.Y + radius * (float)Math.Sin(radian));
PointF innerPoint = new PointF(
center.X + (radius - majorTickLength) * (float)Math.Cos(radian),
center.Y + (radius - majorTickLength) * (float)Math.Sin(radian));
g.DrawLine(majorPen, outerPoint, innerPoint);
// 主刻度数值
float value = _minValue + (_maxValue - _minValue) * i / majorDivisions;
string text = value.ToString("F0");
SizeF textSize = g.MeasureString(text, _scaleFont);
PointF textPoint = new PointF(
center.X + (radius - majorTickLength - textSize.Height) * (float)Math.Cos(radian) - textSize.Width / 2,
center.Y + (radius - majorTickLength - textSize.Height) * (float)Math.Sin(radian) - textSize.Height / 2);
g.DrawString(text, _scaleFont, textBrush, textPoint);
// 次刻度
if (i < majorDivisions)
{
for (int j = 1; j < minorDivisions; j++)
{
float minorAngle = angle + (sweepAngle / majorDivisions / minorDivisions) * j;
float minorRadian = minorAngle * (float)Math.PI / 180;
PointF minorOuter = new PointF(
center.X + radius * (float)Math.Cos(minorRadian),
center.Y + radius * (float)Math.Sin(minorRadian));
PointF minorInner = new PointF(
center.X + (radius - minorTickLength) * (float)Math.Cos(minorRadian),
center.Y + (radius - minorTickLength) * (float)Math.Sin(minorRadian));
g.DrawLine(minorPen, minorOuter, minorInner);
}
}
}
}
}
private void DrawPointer(Graphics g, RectangleF dialRect)
{
PointF center = new PointF(dialRect.X + dialRect.Width / 2, dialRect.Y + dialRect.Height / 2);
float radius = dialRect.Width / 2;
// 计算指针角度
float normalizedValue = (_currentValue - _minValue) / (_maxValue - _minValue);
float angle = 135 + normalizedValue * 270;
float radian = angle * (float)Math.PI / 180;
// 指针长度
float pointerLength = radius * _pointerLength;
float pointerWidth = radius * _pointerWidth;
// 指针端点
PointF tipPoint = new PointF(
center.X + pointerLength * (float)Math.Cos(radian),
center.Y + pointerLength * (float)Math.Sin(radian));
// 指针两侧点
float perpendicularRadian = radian + (float)Math.PI / 2;
PointF side1 = new PointF(
center.X + pointerWidth * (float)Math.Cos(perpendicularRadian),
center.Y + pointerWidth * (float)Math.Sin(perpendicularRadian));
PointF side2 = new PointF(
center.X - pointerWidth * (float)Math.Cos(perpendicularRadian),
center.Y - pointerWidth * (float)Math.Sin(perpendicularRadian));
// 绘制指针
using (GraphicsPath path = new GraphicsPath())
{
path.AddLine(side1, tipPoint);
path.AddLine(tipPoint, side2);
path.CloseFigure();
using (SolidBrush brush = new SolidBrush(_pointerColor))
{
g.FillPath(brush, path);
}
// 指针边框
using (Pen borderPen = new Pen(Color.DarkRed, pointerWidth * 0.3f))
{
g.DrawPath(borderPen, path);
}
}
// 绘制中心点
float centerSize = pointerWidth * 2;
using (SolidBrush centerBrush = new SolidBrush(Color.Silver))
{
g.FillEllipse(centerBrush,
center.X - centerSize / 2,
center.Y - centerSize / 2,
centerSize, centerSize);
}
using (Pen centerPen = new Pen(Color.Gray, pointerWidth * 0.2f))
{
g.DrawEllipse(centerPen,
center.X - centerSize / 2,
center.Y - centerSize / 2,
centerSize, centerSize);
}
}
private void DrawText(Graphics g, RectangleF dialRect)
{
PointF center = new PointF(dialRect.X + dialRect.Width / 2, dialRect.Y + dialRect.Height / 2);
using (SolidBrush valueBrush = new SolidBrush(_valueColor))
using (SolidBrush titleBrush = new SolidBrush(_titleColor))
using (StringFormat format = new StringFormat())
{
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
// 绘制当前值
string valueText = string.Format("{0:F1} {1}", _currentValue, _unit);
RectangleF valueRect = new RectangleF(
center.X - dialRect.Width / 2,
center.Y + dialRect.Height * 0.1f,
dialRect.Width,
_valueFont.Height * 1.5f);
g.DrawString(valueText, _valueFont, valueBrush, valueRect, format);
// 绘制标题
RectangleF titleRect = new RectangleF(
center.X - dialRect.Width / 2,
center.Y + dialRect.Height * 0.3f,
dialRect.Width,
_titleFont.Height * 1.2f);
g.DrawString(_title, _titleFont, titleBrush, titleRect, format);
}
}
#endregion
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Invalidate();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_valueFont != null) _valueFont.Dispose();
if (_titleFont != null) _titleFont.Dispose();
if (_scaleFont != null) _scaleFont.Dispose();
}
base.Dispose(disposing);
}
}
}
Form1.cs文件源码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Timers;
namespace _4_dashboard
{
public partial class Form1 : Form
{
private DashboardControl dashboard;
private System.Timers.Timer updateTimer;
private Random random = new Random();
// 控制控件
private NumericUpDown nudMinValue, nudMaxValue, nudCurrentValue;
private NumericUpDown nudWarningValue, nudDangerValue;
private Button btnStart, btnStop, btnRandom;
private ComboBox cmbPointerColor, cmbBackgroundColor;
private TrackBar trbValue;
private Label lblStatus;
public Form1()
{
InitializeComponent();
this.Text = "仪表盘控件演示 - .NET 4.0";
this.Size = new Size(1000, 700);
this.StartPosition = FormStartPosition.CenterScreen;
this.BackColor = Color.White;
SetupDashboard();
SetupControls();
SetupTimer();
}
private void SetupDashboard()
{
dashboard = new DashboardControl();
dashboard.Location = new Point(50, 50);
dashboard.Size = new Size(400, 400);
dashboard.Title = "速度表";
dashboard.Unit = "km/h";
dashboard.MinValue = 0;
dashboard.MaxValue = 200;
dashboard.WarningValue = 160;
dashboard.DangerValue = 180;
dashboard.CurrentValue = 60;
this.Controls.Add(dashboard);
}
private void SetupControls()
{
int xPos = 500;
int yPos = 50;
// 量程设置
AddLabel("量程设置:", xPos, yPos);
nudMinValue = CreateNumericUpDown(xPos + 80, yPos, 0, 1000, 0);
nudMaxValue = CreateNumericUpDown(xPos + 150, yPos, 1, 1000, 200);
nudMinValue.ValueChanged += UpdateDashboardRange;
nudMaxValue.ValueChanged += UpdateDashboardRange;
yPos += 40;
// 警戒值设置
AddLabel("警戒值:", xPos, yPos);
nudWarningValue = CreateNumericUpDown(xPos + 80, yPos, 0, 1000, 160);
nudDangerValue = CreateNumericUpDown(xPos + 150, yPos, 0, 1000, 180);
nudWarningValue.ValueChanged += UpdateThresholds;
nudDangerValue.ValueChanged += UpdateThresholds;
yPos += 40;
// 当前值设置
AddLabel("当前值:", xPos, yPos);
nudCurrentValue = CreateNumericUpDown(xPos + 80, yPos, 0, 1000, 60);
nudCurrentValue.ValueChanged += delegate (object sender, EventArgs e)
{
dashboard.CurrentValue = (float)nudCurrentValue.Value;
trbValue.Value = (int)nudCurrentValue.Value;
};
yPos += 40;
// 滑块控制
AddLabel("滑块控制:", xPos, yPos);
trbValue = new TrackBar()
{
Location = new Point(xPos + 80, yPos),
Size = new Size(200, 45),
Minimum = 0,
Maximum = 200,
Value = 60,
TickFrequency = 20
};
trbValue.Scroll += delegate (object sender, EventArgs e)
{
dashboard.CurrentValue = trbValue.Value;
nudCurrentValue.Value = trbValue.Value;
};
this.Controls.Add(trbValue);
yPos += 60;
// 颜色设置
AddLabel("指针颜色:", xPos, yPos);
cmbPointerColor = CreateColorComboBox(xPos + 80, yPos);
cmbPointerColor.SelectedIndex = 0;
cmbPointerColor.SelectedIndexChanged += delegate (object sender, EventArgs e)
{
dashboard.PointerColor = GetSelectedColor(cmbPointerColor);
};
yPos += 40;
AddLabel("背景颜色:", xPos, yPos);
cmbBackgroundColor = CreateColorComboBox(xPos + 80, yPos);
cmbBackgroundColor.SelectedIndex = 0;
cmbBackgroundColor.SelectedIndexChanged += delegate (object sender, EventArgs e)
{
// 移除透明色选项,只提供不透明颜色
dashboard.BackgroundColor = GetSelectedBackgroundColor(cmbBackgroundColor);
};
yPos += 60;
// 控制按钮
btnStart = new Button() { Text = "开始模拟", Location = new Point(xPos, yPos), Size = new Size(80, 30) };
btnStop = new Button() { Text = "停止模拟", Location = new Point(xPos + 90, yPos), Size = new Size(80, 30) };
btnRandom = new Button() { Text = "随机数值", Location = new Point(xPos + 180, yPos), Size = new Size(80, 30) };
btnStart.Click += delegate (object sender, EventArgs e)
{
updateTimer.Start();
UpdateStatus("模拟运行中");
};
btnStop.Click += delegate (object sender, EventArgs e)
{
updateTimer.Stop();
UpdateStatus("模拟已停止");
};
btnRandom.Click += delegate (object sender, EventArgs e)
{
SetRandomValue();
};
this.Controls.AddRange(new Control[] { btnStart, btnStop, btnRandom });
yPos += 40;
// 状态显示
lblStatus = new Label()
{
Text = "状态: 准备就绪",
Location = new Point(xPos, yPos),
Size = new Size(300, 20),
ForeColor = Color.Blue,
Font = new Font("Arial", 10, FontStyle.Bold)
};
this.Controls.Add(lblStatus);
}
// 修改颜色选择方法,移除透明色
private Color GetSelectedBackgroundColor(ComboBox cmb)
{
switch (cmb.Text)
{
case "黑色": return Color.Black;
case "深灰色": return Color.DarkGray;
case "深蓝色": return Color.DarkBlue;
case "深绿色": return Color.DarkGreen;
case "深红色": return Color.DarkRed;
case "深紫色": return Color.Purple;
default: return Color.Black;
}
}
private void AddLabel(string text, int x, int y)
{
var label = new Label()
{
Text = text,
Location = new Point(x, y),
AutoSize = true,
Font = new Font("Arial", 9)
};
this.Controls.Add(label);
}
private NumericUpDown CreateNumericUpDown(int x, int y, decimal min, decimal max, decimal value)
{
var nud = new NumericUpDown()
{
Location = new Point(x, y),
Size = new Size(60, 20),
Minimum = min,
Maximum = max,
DecimalPlaces = 1
};
// 先设置范围,再设置值
nud.Minimum = min;
nud.Maximum = max;
nud.Value = value;
this.Controls.Add(nud);
return nud;
}
private ComboBox CreateColorComboBox(int x, int y)
{
var cmb = new ComboBox()
{
Location = new Point(x, y),
Size = new Size(120, 20),
DropDownStyle = ComboBoxStyle.DropDownList
};
// 修改选项,移除透明色相关选项
if (x > 500) // 背景颜色下拉框
{
cmb.Items.AddRange(new object[] { "黑色", "深灰色", "深蓝色", "深绿色", "深红色", "深紫色" });
}
else // 指针颜色下拉框
{
cmb.Items.AddRange(new object[] { "红色", "蓝色", "绿色", "黄色", "紫色", "橙色" });
}
this.Controls.Add(cmb);
return cmb;
}
private Color GetSelectedColor(ComboBox cmb)
{
switch (cmb.Text)
{
case "红色": return Color.Red;
case "蓝色": return Color.Blue;
case "绿色": return Color.Green;
case "黄色": return Color.Yellow;
case "紫色": return Color.Purple;
case "橙色": return Color.Orange;
default: return Color.Red;
}
}
private void UpdateDashboardRange(object sender, EventArgs e)
{
dashboard.MinValue = (float)nudMinValue.Value;
dashboard.MaxValue = (float)nudMaxValue.Value;
trbValue.Minimum = (int)nudMinValue.Value;
trbValue.Maximum = (int)nudMaxValue.Value;
}
private void UpdateThresholds(object sender, EventArgs e)
{
dashboard.WarningValue = (float)nudWarningValue.Value;
dashboard.DangerValue = (float)nudDangerValue.Value;
}
private void UpdateStatus(string status)
{
lblStatus.Text = string.Format("状态: {0} - 当前值: {1:F1}", status, dashboard.CurrentValue);
}
private void SetupTimer()
{
updateTimer = new System.Timers.Timer(100);
updateTimer.Elapsed += OnTimerElapsed;
updateTimer.SynchronizingObject = this;
}
private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
// 模拟真实数据变化(带缓动效果)
float targetValue = 50 + (float)(Math.Sin(DateTime.Now.Ticks * 0.0000001) * 70 + random.NextDouble() * 20);
float currentValue = dashboard.CurrentValue;
float newValue = currentValue + (targetValue - currentValue) * 0.1f;
dashboard.CurrentValue = newValue;
nudCurrentValue.Value = (decimal)newValue;
trbValue.Value = (int)newValue;
UpdateStatus("模拟运行中");
}
private void SetRandomValue()
{
float randomValue = (float)(random.NextDouble() * (dashboard.MaxValue - dashboard.MinValue) + dashboard.MinValue);
dashboard.CurrentValue = randomValue;
nudCurrentValue.Value = (decimal)randomValue;
trbValue.Value = (int)randomValue;
}
protected override void OnFormClosing(FormClosingEventArgs e)
{
if (updateTimer != null)
{
updateTimer.Stop();
updateTimer.Dispose();
}
base.OnFormClosing(e);
}
}
}
三、效果演示
可以进行量程,警戒值等参数设置。拖动滑块速度显示和指针随之改变。点击模拟,则实时更新仪表盘控件数据。
