C# GDI+数码管数字控件
调用方法
int zhi = 15;private void button1_Click(object sender, EventArgs e){if (++zhi > 19){zhi = 0;}lcdDisplayControl1.DisplayText = zhi.ToString();}
运行效果
控件代码
using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;namespace WindowsFormsApp1
{public class LcdDisplayControl : Control{private string _displayText = "0";private Color _digitColor = Color.LightGreen;private Color _backgroundColor = Color.Black;private const float SEGMENT_WIDTH_RATIO = 0.15f; //每个发光段的宽度比例private const float DIGIT_HEIGHT_RATIO = 0.8f; //数字显示区域的高度比例private const float SEGMENT_GAP_RATIO = 0.05f; //段之间的间隙比例private float _padding = 2f;private Color _shadowColor = Color.FromArgb(30, Color.LightGreen); // 默认投影颜色 private float _shadowOffset = 1.5f; // 默认投影偏移量 private bool _enableGlassEffect = true;private Color _glassHighlightColor = Color.FromArgb(40, Color.White);private float _glassEffectHeight = 0.4f; // 玻璃效果占控件高度的比例 private Timer _animationTimer;private double _currentValue = 0;private double _targetValue = 0;private bool _isAnimating = false;private int _animationDuration = 1000; // 默认动画持续时间(毫秒) private DateTime _animationStartTime;private string _originalFormat = "0"; // 保存显示格式 public float Padding{get => _padding;set{if (_padding != value){_padding = Math.Max(0, value);Invalidate();}}}public int AnimationDuration{get => _animationDuration;set{if (_animationDuration != value && value > 0){_animationDuration = value;}}}public bool EnableGlassEffect{get => _enableGlassEffect;set{if (_enableGlassEffect != value){_enableGlassEffect = value;Invalidate();}}}public Color GlassHighlightColor{get => _glassHighlightColor;set{if (_glassHighlightColor != value){_glassHighlightColor = value;Invalidate();}}}public Color ShadowColor{get => _shadowColor;set{if (_shadowColor != value){_shadowColor = value;Invalidate();}}}public float ShadowOffset{get => _shadowOffset;set{if (_shadowOffset != value){_shadowOffset = Math.Max(0, value); // 确保偏移量不为负数 Invalidate();}}}public LcdDisplayControl(){SetStyle(ControlStyles.DoubleBuffer |ControlStyles.AllPaintingInWmPaint |ControlStyles.UserPaint |ControlStyles.ResizeRedraw, true);ForeColor = _digitColor;EnableGlassEffect = true; // 默认启用玻璃效果 _animationTimer = new Timer();_animationTimer.Interval = 16; // 约60fps _animationTimer.Tick += AnimationTimer_Tick;}public string DisplayText{get => _displayText;set{if (_displayText != value){// 尝试解析新值 if (double.TryParse(value, out double newValue)){// 保存显示格式 _originalFormat = value.Contains(".") ?"F" + (value.Length - value.IndexOf('.') - 1) : "0";// 开始动画 StartAnimation(newValue);}else{// 如果不是数字,直接设置 _displayText = value;Invalidate();}}}}public Color DigitColor{get => _digitColor;set{if (_digitColor != value){_digitColor = value;Invalidate();}}}private void StartAnimation(double targetValue){_targetValue = targetValue;_currentValue = double.TryParse(_displayText, out double currentValue) ?currentValue : 0;if (_currentValue == _targetValue)return;_animationStartTime = DateTime.Now;_isAnimating = true;_animationTimer.Start();}private void AnimationTimer_Tick(object sender, EventArgs e){var elapsed = (DateTime.Now - _animationStartTime).TotalMilliseconds;var progress = Math.Min(elapsed / _animationDuration, 1.0);// 使用缓动函数使动画更自然 progress = EaseOutCubic(progress);// 计算当前值 _currentValue = _currentValue + (_targetValue - _currentValue) * progress;// 更新显示 _displayText = _currentValue.ToString(_originalFormat);Invalidate();// 检查动画是否完成 if (progress >= 1.0){_animationTimer.Stop();_isAnimating = false;_currentValue = _targetValue;_displayText = _targetValue.ToString(_originalFormat);Invalidate();}}// 缓动函数 private double EaseOutCubic(double t){return 1 - Math.Pow(1 - t, 3);}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);Graphics g = e.Graphics;g.SmoothingMode = SmoothingMode.HighQuality;g.InterpolationMode = InterpolationMode.HighQualityBicubic;g.PixelOffsetMode = PixelOffsetMode.HighQuality;g.CompositingQuality = CompositingQuality.HighQuality;// 绘制背景和边框 using (var bgBrush = new SolidBrush(_backgroundColor)){g.FillRectangle(bgBrush, ClientRectangle);}// 计算实际显示区域(考虑内边距和边框) float effectivePadding = _padding;float displayAreaWidth = Width - (effectivePadding * 2);float displayAreaHeight = Height - (effectivePadding * 2);// 计算单个数字的大小 float digitWidth = displayAreaWidth / _displayText.Length;float digitHeight = displayAreaHeight * 0.8f;// 起始位置(考虑内边距和边框) float x = effectivePadding;float y = effectivePadding + (displayAreaHeight - digitHeight) / 2;// 绘制数字 for (int i = 0; i < _displayText.Length; i++){if (_displayText[i] == '.'){DrawDecimalPoint(g, x, y, digitWidth, digitHeight);x += digitWidth * 0.3f;}else{DrawDigit(g, _displayText[i], x, y, digitWidth, digitHeight);x += digitWidth;}}// 如果启用玻璃效果,绘制玻璃效果 if (_enableGlassEffect){DrawGlassEffect(g);}}// 玻璃效果绘制方法 private void DrawGlassEffect(Graphics g){float glassHeight = Height * _glassEffectHeight;// 创建渐变画笷 using (var path = new GraphicsPath()){path.AddRectangle(new RectangleF(0, 0, Width, glassHeight));// 创建渐变 using (var brush = new LinearGradientBrush(new PointF(0, 0),new PointF(0, glassHeight),Color.FromArgb(60, _glassHighlightColor),Color.FromArgb(10, _glassHighlightColor))){g.FillPath(brush, path);}// 添加微弱的边缘高光 float highlightThickness = 1.0f;using (var highlightBrush = new LinearGradientBrush(new RectangleF(0, 0, Width, highlightThickness),Color.FromArgb(100, _glassHighlightColor),Color.FromArgb(0, _glassHighlightColor),LinearGradientMode.Vertical)){g.FillRectangle(highlightBrush, 0, 0, Width, highlightThickness);}}}private void DrawDigit(Graphics g, char digit, float x, float y, float width, float height){bool[] segments = GetSegments(digit);float segmentWidth = width * SEGMENT_WIDTH_RATIO;float segmentLength = width * 0.8f;float gap = width * SEGMENT_GAP_RATIO;// 水平段 if (segments[0]) DrawHorizontalSegment(g, x + gap, y, segmentLength, segmentWidth); // 顶段 if (segments[3]) DrawHorizontalSegment(g, x + gap, y + height / 2, segmentLength, segmentWidth); // 中段 if (segments[6]) DrawHorizontalSegment(g, x + gap, y + height - segmentWidth, segmentLength, segmentWidth); // 底段 // 垂直段 if (segments[1]) DrawVerticalSegment(g, x, y + gap, segmentWidth, height / 2 - gap); // 左上 if (segments[2]) DrawVerticalSegment(g, x + segmentLength, y + gap, segmentWidth, height / 2 - gap); // 右上 if (segments[4]) DrawVerticalSegment(g, x, y + height / 2 + gap, segmentWidth, height / 2 - gap); // 左下 if (segments[5]) DrawVerticalSegment(g, x + segmentLength, y + height / 2 + gap, segmentWidth, height / 2 - gap); // 右下 }private void DrawHorizontalSegment(Graphics g, float x, float y, float length, float width){using (var path = new GraphicsPath()){// 创建水平段的路径 path.AddLine(x + width / 2, y, x + length - width / 2, y);path.AddLine(x + length, y + width / 2, x + length - width / 2, y + width);path.AddLine(x + width / 2, y + width, x, y + width / 2);path.CloseFigure();// 绘制阴影效果 using (var shadowBrush = new SolidBrush(_shadowColor)){var shadowPath = (GraphicsPath)path.Clone();var shadowMatrix = new Matrix();shadowMatrix.Translate(_shadowOffset, _shadowOffset);shadowPath.Transform(shadowMatrix);g.FillPath(shadowBrush, shadowPath);shadowPath.Dispose();}// 绘制主体 using (var brush = new SolidBrush(_digitColor)){g.FillPath(brush, path);}// 如果启用玻璃效果,添加额外的光泽 if (_enableGlassEffect){using (var glassBrush = new LinearGradientBrush(new RectangleF(x, y, length, width),Color.FromArgb(40, Color.White),Color.FromArgb(10, Color.White),LinearGradientMode.Vertical)){g.FillPath(glassBrush, path);}}// 添加发光边缘 using (var pen = new Pen(Color.FromArgb(100, _digitColor), 0.5f)){g.DrawPath(pen, path);}}}private void DrawVerticalSegment(Graphics g, float x, float y, float width, float length){using (var path = new GraphicsPath()){path.AddLine(x, y + width / 2, x + width / 2, y);path.AddLine(x + width, y + width / 2, x + width / 2, y + length);path.AddLine(x, y + length - width / 2, x, y + width / 2);path.CloseFigure();// 绘制阴影 using (var shadowBrush = new SolidBrush(_shadowColor)){var shadowPath = (GraphicsPath)path.Clone();var shadowMatrix = new Matrix();shadowMatrix.Translate(_shadowOffset, _shadowOffset);shadowPath.Transform(shadowMatrix);g.FillPath(shadowBrush, shadowPath);shadowPath.Dispose();}// 绘制主体 using (var brush = new SolidBrush(_digitColor)){g.FillPath(brush, path);}// 如果启用玻璃效果,添加额外的光泽 if (_enableGlassEffect){using (var glassBrush = new LinearGradientBrush(new RectangleF(x, y, width, length),Color.FromArgb(40, Color.White),Color.FromArgb(10, Color.White),LinearGradientMode.Vertical)){g.FillPath(glassBrush, path);}}// 添加发光边缘 using (var pen = new Pen(Color.FromArgb(100, _digitColor), 0.5f)){g.DrawPath(pen, path);}}}private void DrawDecimalPoint(Graphics g, float x, float y, float width, float height){float dotSize = width * 0.2f;// 绘制阴影效果 using (var shadowBrush = new SolidBrush(_shadowColor)){g.FillEllipse(shadowBrush,x + _shadowOffset,y + height - dotSize + _shadowOffset,dotSize,dotSize);}// 绘制主体 using (var brush = new SolidBrush(_digitColor)){g.FillEllipse(brush, x, y + height - dotSize, dotSize, dotSize);}// 添加发光边缘 using (var pen = new Pen(Color.FromArgb(100, _digitColor), 0.5f)){g.DrawEllipse(pen, x, y + height - dotSize, dotSize, dotSize);}}private bool[] GetSegments(char digit){// 7段显示的状态表 [顶, 左上, 右上, 中, 左下, 右下, 底] switch (digit){case '0': return new bool[] { true, true, true, false, true, true, true };case '1': return new bool[] { false, false, true, false, false, true, false };case '2': return new bool[] { true, false, true, true, true, false, true };case '3': return new bool[] { true, false, true, true, false, true, true };case '4': return new bool[] { false, true, true, true, false, true, false };case '5': return new bool[] { true, true, false, true, false, true, true };case '6': return new bool[] { true, true, false, true, true, true, true };case '7': return new bool[] { true, false, true, false, false, true, false };case '8': return new bool[] { true, true, true, true, true, true, true };case '9': return new bool[] { true, true, true, true, false, true, true };default: return new bool[] { false, false, false, false, false, false, false };}}protected override void Dispose(bool disposing){if (disposing){if (_animationTimer != null){_animationTimer.Stop();_animationTimer.Dispose();}}base.Dispose(disposing);}}
}
参考链接
C# GDI+ 自定义液晶数字显示控件实现https://mp.weixin.qq.com/s?__biz=MzUxMjI3OTQzMQ==&mid=2247492775&idx=2&sn=4d9ebea27a83f5d8b126f2a12ab814ff&chksm=f898d37124d498cd3679d8eeb087628128d88d5aad24894436e18c92ac88b0c8bb87dab626d4&mpshare=1&scene=1&srcid=1227wTdlchamy68RzROrTh1n&sharer_shareinfo=91591cbc57360386ce01226fefa68fea&sharer_shareinfo_first=ced9494296615bca82d9118cef9b2a63&exportkey=n_ChQIAhIQ%2BOKdOkcv%2FxioQG8f08%2F7QBKfAgIE97dBBAEAAAAAAD1%2BOc5nK1QAAAAOpnltbLcz9gKNyK89dVj0XeVuyql%2F1aB8a7B5UUEJ50Jp43nndJjF0zdyTORUnAgO0mKKprVb6%2FtFZovUk3Zb3Rs27dOnI%2FMrKVUz6p7jURoFUhTBmK%2B%2B5%2BdUm6sLkPUwLSHmrRpDm96WBI%2F4%2BjyXSDEWceHct1KQz%2BQwZGLrrP79wUcpYKcYFrm6k22sox5Yl9Z0gwB1Hm32kegC58sCv5JlOm7deiL2YPL9DK3Jy%2BTNNHBNp9CnejYgbEjCHpPqasDEZCntntqKoqZPcR6xr7WAXm2DpBjBxqAhIfzT0BpUArzrlVnB1g4ZKHpteq1Y4p30CgfdA4fuWw9rdsT1X%2BKXHQfdfJnG&acctmode=0&pass_ticket=til6Grkg7Hy%2FLLLcFHsrar09TbMKp9qdr5Vnsoq6563Z%2FVtuuVASoekDIseEXV%2B8&wx_header=0#rd特此记录
anlog
2024年12月27日
相关文章:

C# GDI+数码管数字控件
调用方法 int zhi 15;private void button1_Click(object sender, EventArgs e){if (zhi > 19){zhi 0;}lcdDisplayControl1.DisplayText zhi.ToString();} 运行效果 控件代码 using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using …...

在交叉编译中,常见的ELF(elf)到底是什么意思?
ELF 是 Executable and Linkable Format 的缩写,中文翻译为“可执行与可链接格式”。它是一种通用的文件格式,主要用于存储可执行文件、目标文件(编译后的中间文件)、动态库(.so 文件)以及内存转储文件&…...
Unity开发AR之Vuforia-MultiTarget笔记
前言 在增强现实(AR)技术蓬勃发展的今天,越来越多的开发者开始探索如何将AR应用于各种场景中。Vuforia作为一个领先的AR开发平台,为开发者提供了强大的工具和功能,使得创建AR体验变得更加简单和直观。本文将为您介绍Vuforia的基本概念、特点,以及如何配置和使用MultiTar…...
深入解析 Oracle 的聚合函数 ROLLUP
目录 深入解析 Oracle 的聚合函数 ROLLUP一、ROLLUP 函数概述二、ROLLUP 函数语法三、ROLLUP 实例详解(一)基础分组聚合(二)引入 ROLLUP 函数(三)ROLLUP 与 NULL 值(四)多列复杂分组…...

Wend看源码-Java-集合学习(List)
摘要 本篇文章深入探讨了基于JDK 21版本的Java.util包中提供的多样化集合类型。在Java中集合共分类为三种数据结构:List、Set和Queue。本文将详细阐述这些数据类型的各自实现,并按照线程安全性进行分类,分别介绍非线程安全与线程安全的实现方…...

【软件】教务系统成绩提交工具使用步骤
【软件】教务系统成绩提交工具使用步骤 零、快速开始 安装 与大多数软件一样,安装步骤很简单,一直点击“下一步”即可快速完成安装,安装完成后,在桌面会有一个软件图标,双击即可打开软件主界面。 导入成绩到Excel中…...

IPsec协议,网络安全的秘密
IPsec概述 IPsec是一组基于网络层的安全协议,是保护IP数据包在网络传输过程中保持安全、隐秘以及真实。通过对IP数据包进行一些加密、认证,来防止数据在传输过程中被窃取、篡改甚至伪造,IPsec在企业内部网络的通信、远程办公、云服务连接等场…...
浅谈下Spring MVC的执行流程
什么是Spring MVC Spring MVC是一个基于Java的Web框架,用于构建Web应用程序。 它是Spring Framework的一部分,它提供了模型-视图-控制器(MVC)架构。 支持RESTful风格的URL请求,易于与其他视图技术集成,如…...

khadas edge2安装ubuntu22.04与ubuntu20.04 docker镜像
khadas edge2安装ubuntu22.04与ubuntu20.04 docker镜像 一、资源准备1.1 镜像文件1.2 刷机工具1.3 ubuntu20.04 docker镜像(具备demon无人机所需各种驱动) 二、开始刷机(安装ubuntu22.04系统)2.1 进入刷机状态2.2 刷机 三、docker…...

GitLab 服务变更提醒:中国大陆、澳门和香港用户停止提供服务(GitLab 服务停止)
目录 前言 一. 变更详情 1. 停止服务区域 2. 邮件通知 3. 新的服务提供商 4. 关键日期 5. 行动建议 二. 迁移指南 三. 注意事项 四. 相关推荐 前言 近期,许多位于中国大陆、澳门和香港的 GitLab 用户收到了一封来自 GitLab 官方的重要通知。根据这封邮件…...
主成分分析是线性降维方法
主成分分析是线性降维方法 主成分分析(PCA)是一种常用的线性降维方法。它通过线性变换将原始数据映射到新的坐标系中,使得数据在新坐标系中的第一个坐标(第一个主成分)具有最大的方差,以此类推,…...

Webpack在Vue CLI中的应用
webpack 作为目前最流行的项目打包工具,被广泛使用于项目的构建和开发过程中,其实说它是打包工具有点大材小用了,我个人认为它是一个集前端自动化、模块化、组件化于一体的可拓展系统,你可以根据自己的需要来进行一系列的配置和安…...

继承超详细介绍
一 、继承 1 继承的概念 继承是面向对象程序设计使得代码可以复用的最重要手段,它使得我们可以在原有类的特性的基础上进行扩展,增加方法和属性(成员函数与成员变量),这样产生新的类,叫作派生类。继承呈现了…...
wordpress调用指定ID分类下浏览最多的内容
要在WordPress中调用指定ID分类下浏览最多的内容,你可以通过以下方法实现: <?php $post_num 8; // 设置调用条数 $wdpidproduct 2; // 假设这是你要查询的分类ID $args array(post_password > ,post_status > publish, // wodepress.comca…...

18.springcloud_openfeign之扩展组件二
文章目录 一、前言二、子容器默认组件FeignClientsConfigurationDecoder的注入Contract约定 对注解的支持对类上注解的支持对方法上注解的支持对参数上注解的支持MatrixVariablePathVariableRequestParamRequestHeaderSpringQueryMapRequestPartCookieValue FormattingConversi…...
FreePBX修改IP地址和端口以及添加SSL证书开启HTTPS访问
最近给单位部署了freepbx网络电话系统,我的系统是安装在ibm x3650 m4物理机上的,iso镜像下载后直接用Rufus烧录到U盘,服务器上先做好了raid1,插上U盘重启服务器开撸。安装过程略过了,在虚拟机上安装就不用那么麻烦。 …...
运算符 - 算术、关系、逻辑运算符
引言 在编程中,运算符是用于执行特定操作的符号。C 提供了多种类型的运算符,包括算术运算符、关系运算符和逻辑运算符等。理解这些运算符及其用法对于编写高效且无误的代码至关重要。本文将详细介绍 C 中的这三种基本运算符,并通过实例帮助读…...

大模型-ChatGLM2-6B模型部署与微调记录
大模型-ChatGLM2-6B模型部署与微调记录 模型权重下载: 登录魔塔社区:https://modelscope.cn/models/ZhipuAI/chatglm2-6b 拷贝以下代码执行后,便可快速权重下载到本地 # 备注:最新模型版本要求modelscope > 1.9.0 # pip insta…...

RDFS—RDF模型属性扩展解析
目录 前言1. 什么是RDFS?1.1 RDFS的核心概念1.2 RDFS与RDF的区别 2. RDFS的基础概念2.1 类(Class)2.2 属性(Property)2.3 关系(Relation)2.4 定义域(Domain)2.5 值域&…...

pyqt和pycharm环境搭建
安装 python安装: https://www.python.org/downloads/release/python-3913/ python3.9.13 64位(记得勾选Path环境变量) pycharm安装: https://www.jetbrains.com/pycharm/download/?sectionwindows community免费版 换源: pip config se…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...