当前位置: 首页 > news >正文

开源 C# 快速构建(五)自定义控件--仪表盘

开源 C# 快速构建(五)自定义控件--仪表盘

        文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

 相关链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

开源 C# 快速开发(八)通讯--Tcp服务器端

开源 C# 快速开发(九)通讯--Tcp客户端

开源 C# 快速开发(十)通讯--http客户端

推荐链接:

开源 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 测试窗体。

1. 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 方法 - 指针绘制


2. 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. 技术亮点
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);}}#endregionprotected 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);}}
}

三、效果演示

可以进行量程,警戒值等参数设置。拖动滑块速度显示和指针随之改变。点击模拟,则实时更新仪表盘控件数据。

http://www.hskmm.com/?act=detail&tid=22270

相关文章:

  • 2025中医师承培训、考试、认证机构权威推荐榜:名师传承与临床实践口碑之选
  • 电子文件分类整理与双向同步 2025年10月1日
  • C++版搜索与图论算法 - 详解
  • 62. 不同路径
  • 达成设计卓越:全面解析 IC 设计中的验证之道
  • Typora 笔记迁移 Obsidian 图片链接转换
  • Java 运行 Word 文档标签并赋值:从基础到实战
  • 词云组件
  • 2025 年超声波清洗机品牌最新权威推荐排行榜:龙门式 / 悬挂式 / 全自动等多类型设备厂家 TOP3 精选,助力企业精准选购
  • 树的统一迭代法
  • 2025 年冷却塔品牌最新推荐排行榜:玻璃钢冷却塔、闭式冷却塔、方型逆流式冷却塔优质厂家 TOP3 精选,赋能企业选购
  • DailyPaper-2025-9-30
  • Powershell 管理 后台/计划 作业(六)
  • 32. 最长有效括号
  • java17及以上版本如何抵御TemplatesImpl注入
  • 详细介绍:【C++实战(53)】C++11线程库:开启多线程编程新世界
  • 将图片某个区域批量填充白色(jsx代码)
  • 《初等数论(第四版,北京大学出版社,潘承洞,潘承彪著)》阅读笔记+心得
  • 完整教程:Word和WPS文字中的自动编号和文字间距过大怎么办?
  • markdown笔记文件批量打上时间戳
  • 251001
  • 微服务调整中心高可用设计:从踩坑到落地的实战指南(二)
  • NOIP2025模拟赛27
  • NOIP2025模拟赛28
  • 十月数据结构题没做
  • NOIP2025模拟赛30
  • 2025西安品牌新房,西安刚需新房,陕西优质新房住宅推荐,地建嘉信臻境,超2000㎡高端会所,满足多元化生活需求
  • 2025年未央区高端楼盘,西咸新区品质楼盘,西安高新品牌楼盘住宅口碑推荐,地建嘉信臻境周边配套丰富,教育医疗商业齐全
  • 2025西安高端新房,西安优质新房,西安品牌新房住宅推荐,地建嘉信臻境,沣东文商板块门户,享双地铁便利
  • 2025年西安洋房楼盘,陕西优质楼盘,西咸新区现房楼盘住宅口碑推荐,地建嘉信臻境超2000㎡高端会所,功能多样