forms实现快读阅读器

forms实现快读阅读器

主要功能包括:
​​1.文本自动分块显示​​:按设定的速度逐词显示文本内容。
​​2.阅读控制​​:开始/停止按钮以及回车键控制。
​​3.界面自定义​​:包括字体、颜色(前景色和背景色)的设置。
​​4.暗黑模式​​:支持暗黑主题,并有相应的渲染器。
​​5.全屏模式​​:通过F11或按钮切换全屏。
​​6.速度调节​​:通过WPM(每分钟字数)数值调节器控制显示速度。
​​7.循环阅读​​:复选框控制是否循环阅读。
​​8.设置持久化​​:保存用户的设置(如字体、颜色、速度等)到配置文件。
​​9.文件自动加载​​:从固定路径加载文本文件。
​​10.错误处理​​:文件不存在或内容为空时的提示。
说明:
C:\Users\wangrusheng\AppData\Roaming\WinFormsApp38\settings.json
这个目录下,有一个json配置文件 主要配置字体,字体颜色,背景颜色,阅读速度等,第一次运行会自动生成
效果图:
在这里插入图片描述

step1:
C:\Users\wangrusheng\RiderProjects\WinFormsApp38\WinFormsApp38\Form1.cs

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Newtonsoft.Json;namespace WinFormsApp38
{public partial class Form1 : Form{private const string FixedFilePath = @"C:\Users\wangrusheng\Downloads\ages.txt";private Settings settings;private System.Windows.Forms.Timer timer;private List<string> tokens;private int currentIndex;private FormWindowState lastWindowState;private Color currentForeground;private Color currentBackground;// 控件声明private Label lblText;private ToolStrip toolStrip;private ToolStripButton btnFullScreen;private ToolStripButton btnColors;private ToolStripButton btnFont;private ToolStripButton btnStart;private NumericUpDown numWPM;private CheckBox chkRepeat;public Form1(){InitializeComponent();InitializeDynamicComponents();settings = Settings.Load();LoadSettings();SetupEventHandlers();ApplyDarkTheme();}private void InitializeDynamicComponents(){// 主标签初始化lblText = new Label{Dock = DockStyle.Fill,TextAlign = ContentAlignment.MiddleCenter,Font = new Font("微软雅黑", 24)};// 工具栏初始化toolStrip = new ToolStrip{Renderer = new DarkToolStripRenderer(),GripStyle = ToolStripGripStyle.Hidden};// 工具栏按钮btnFullScreen = new ToolStripButton("全屏 (F11)");btnColors = new ToolStripButton("颜色");btnFont = new ToolStripButton("字体");btnStart = new ToolStripButton("开始 (Enter)");// 速度控件numWPM = new NumericUpDown{Minimum = 50,Maximum = 1000,Value = 150,Width = 80,DecimalPlaces = 0,ForeColor = Color.White,BackColor = Color.FromArgb(45, 45, 45)};// 循环复选框chkRepeat = new CheckBox{Text = "循环阅读",AutoSize = true,ForeColor = Color.White,BackColor = Color.FromArgb(45, 45, 45),FlatStyle = FlatStyle.Flat};// 添加工具栏项toolStrip.Items.AddRange(new ToolStripItem[]{btnFullScreen,btnColors,btnFont,new ToolStripSeparator(),new ToolStripLabel("速度:") { ForeColor = Color.White },new ToolStripControlHost(numWPM),new ToolStripControlHost(chkRepeat),new ToolStripSeparator(),btnStart});// 窗体设置Controls.Add(lblText);Controls.Add(toolStrip);Text = "快速阅读器";Size = new Size(1200, 600);KeyPreview = true;// WindowState = FormWindowState.Maximized; 自动全屏功能FormBorderStyle = FormWindowState.Maximized == WindowState ? FormBorderStyle.None : FormBorderStyle.Sizable;DoubleBuffered = true;// 定时器timer = new System.Windows.Forms.Timer { Interval = 60000 / 150 };}private void LoadSettings(){currentForeground = settings.ForegroundColor;currentBackground = settings.BackgroundColor;lblText.Font = settings.TextFont;numWPM.Value = settings.WPM;chkRepeat.Checked = settings.Repeat;UpdateLabelAppearance();}private void ApplyDarkTheme(){// 强制使用暗黑主题色currentForeground = Color.White;currentBackground = Color.FromArgb(30, 30, 30);// 主窗体颜色BackColor = currentBackground;ForeColor = currentForeground;// 工具栏样式toolStrip.BackColor = Color.FromArgb(45, 45, 45);toolStrip.ForeColor = Color.White;// 工具栏按钮样式foreach (ToolStripItem item in toolStrip.Items){if (item is ToolStripButton btn){btn.BackColor = Color.FromArgb(45, 45, 45);btn.ForeColor = Color.White;}}// 数值控件numWPM.BackColor = Color.FromArgb(60, 60, 60);numWPM.ForeColor = Color.White;numWPM.BorderStyle = BorderStyle.FixedSingle;// 复选框chkRepeat.BackColor = Color.FromArgb(60, 60, 60);chkRepeat.ForeColor = Color.White;chkRepeat.FlatAppearance.CheckedBackColor = Color.FromArgb(30, 30, 30);UpdateLabelAppearance(); // 强制更新标签颜色}private void SetupEventHandlers(){btnStart.Click += BtnStart_Click;btnFont.Click += BtnFont_Click;btnColors.Click += BtnColors_Click;btnFullScreen.Click += BtnFullScreen_Click;numWPM.ValueChanged += NumWPM_ValueChanged;timer.Tick += Timer_Tick;KeyDown += Form1_KeyDown;// 自定义绘制事件numWPM.Paint += (s, e) => ControlPaint.DrawBorder(e.Graphics, numWPM.ClientRectangle, Color.Gray, ButtonBorderStyle.Solid);chkRepeat.Paint += (s, e) => {e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(60, 60, 60)), e.ClipRectangle);TextRenderer.DrawText(e.Graphics, chkRepeat.Text, chkRepeat.Font, new Point(20, 0), chkRepeat.Checked ? Color.Lime : Color.White);};}private void UpdateLabelAppearance(){lblText.BackColor = currentBackground;lblText.ForeColor = currentForeground;}// [事件处理方法保持不变,与原始代码相同]// ... 包括 BtnStart_Click, BtnFont_Click 等其他事件处理方法 ...private void BtnStart_Click(object sender, EventArgs e){if (timer.Enabled){timer.Stop();btnStart.Text = "开始 (Enter)";}else{try{string text = File.ReadAllText(FixedFilePath);tokens = new List<string>(text.Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries));currentIndex = 0;timer.Interval = 60000 / (int)numWPM.Value;timer.Start();btnStart.Text = "停止 (Enter)";}catch (Exception ex){MessageBox.Show($"读取文件失败: {ex.Message}");}}}private void BtnFont_Click(object sender, EventArgs e){using (FontDialog fontDialog = new FontDialog()){fontDialog.Font = lblText.Font;if (fontDialog.ShowDialog() == DialogResult.OK){lblText.Font = fontDialog.Font;settings.TextFont = fontDialog.Font;}}}private void BtnColors_Click(object sender, EventArgs e){// 前景色using (ColorDialog colorDialog = new ColorDialog()){colorDialog.Color = currentForeground;if (colorDialog.ShowDialog() == DialogResult.OK){currentForeground = colorDialog.Color;lblText.ForeColor = currentForeground;settings.ForegroundColor = currentForeground;}}// 背景色using (ColorDialog colorDialog = new ColorDialog()){colorDialog.Color = currentBackground;if (colorDialog.ShowDialog() == DialogResult.OK){currentBackground = colorDialog.Color;lblText.BackColor = currentBackground;settings.BackgroundColor = currentBackground;}}}private void NumWPM_ValueChanged(object sender, EventArgs e){settings.WPM = (int)numWPM.Value;timer.Interval = 60000 / (int)numWPM.Value;}private void Timer_Tick(object sender, EventArgs e){if (currentIndex < tokens.Count){lblText.Text = tokens[currentIndex];currentIndex++;}else if (chkRepeat.Checked){currentIndex = 0;}else{timer.Stop();btnStart.Text = "开始";}}private void ToggleFullscreen(){if (WindowState == FormWindowState.Maximized){WindowState = lastWindowState;FormBorderStyle = FormBorderStyle.Sizable;}else{lastWindowState = WindowState;WindowState = FormWindowState.Maximized;FormBorderStyle = FormBorderStyle.None;}}private void BtnFullScreen_Click(object sender, EventArgs e){ToggleFullscreen();}private void Form1_KeyDown(object sender, KeyEventArgs e){if (e.KeyCode == Keys.F11){ToggleFullscreen();}else if (e.KeyCode == Keys.Enter){BtnStart_Click(sender, e);}}// 修改保存触发点protected override void OnFormClosing(FormClosingEventArgs e){settings.ForegroundColor = currentForeground;settings.BackgroundColor = currentBackground;settings.Save();base.OnFormClosing(e);}// 暗黑主题渲染器private class DarkToolStripRenderer : ToolStripProfessionalRenderer{public DarkToolStripRenderer() : base(new DarkColorTable()) {RoundedEdges = false;}protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e){if (e.Item.Selected){e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(60, 60, 60)), e.Item.ContentRectangle);}else{base.OnRenderButtonBackground(e);}}}private class DarkColorTable : ProfessionalColorTable{public override Color ToolStripDropDownBackground => Color.FromArgb(45, 45, 45);public override Color MenuItemSelected => Color.FromArgb(60, 60, 60);public override Color MenuItemBorder => Color.FromArgb(30, 30, 30);public override Color MenuBorder => Color.FromArgb(45, 45, 45);public override Color ToolStripBorder => Color.FromArgb(45, 45, 45);public override Color ImageMarginGradientBegin => Color.FromArgb(45, 45, 45);public override Color ImageMarginGradientMiddle => Color.FromArgb(45, 45, 45);public override Color ImageMarginGradientEnd => Color.FromArgb(45, 45, 45);public override Color MenuItemPressedGradientBegin => Color.FromArgb(45, 45, 45);public override Color MenuItemPressedGradientMiddle => Color.FromArgb(45, 45, 45);public override Color MenuItemPressedGradientEnd => Color.FromArgb(45, 45, 45);public override Color ButtonSelectedBorder => Color.FromArgb(60, 60, 60);public override Color ButtonSelectedGradientBegin => Color.FromArgb(60, 60, 60);public override Color ButtonSelectedGradientMiddle => Color.FromArgb(60, 60, 60);public override Color ButtonSelectedGradientEnd => Color.FromArgb(60, 60, 60);public override Color CheckBackground => Color.FromArgb(30, 30, 30);public override Color CheckPressedBackground => Color.FromArgb(60, 60, 60);public override Color CheckSelectedBackground => Color.FromArgb(60, 60, 60);}}// [保留Settings类代码,与原始代码相同]public class Settings{// 序列化用的中间结构public class SerializableFont{public string FontFamily { get; set; }public float FontSize { get; set; }public FontStyle FontStyle { get; set; }}// 将Color转换为字符串表示public string ForegroundColorHex { get; set; }public string BackgroundColorHex { get; set; }// 字体使用可序列化的中间类型public SerializableFont TextFontData { get; set; }public int WPM { get; set; } = 66;public bool Repeat { get; set; }[JsonIgnore] // 忽略实际使用的Font类型public Font TextFont{get => new Font(TextFontData.FontFamily,TextFontData.FontSize,TextFontData.FontStyle);set => TextFontData = new SerializableFont{FontFamily = value.FontFamily.Name,FontSize = value.Size,FontStyle = value.Style};}[JsonIgnore]public Color ForegroundColor{get => ColorTranslator.FromHtml(ForegroundColorHex);set => ForegroundColorHex = ColorTranslator.ToHtml(value);}[JsonIgnore]public Color BackgroundColor{get => ColorTranslator.FromHtml(BackgroundColorHex);set => BackgroundColorHex = ColorTranslator.ToHtml(value);}private static string ConfigPath => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"WinFormsApp38","settings.json");public void Save(){try{var dir = Path.GetDirectoryName(ConfigPath);if (!Directory.Exists(dir))Directory.CreateDirectory(dir);File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(this));}catch (Exception ex){MessageBox.Show($"保存设置失败: {ex.Message}");}}public static Settings Load(){try{if (File.Exists(ConfigPath)){var content = File.ReadAllText(ConfigPath);return JsonConvert.DeserializeObject<Settings>(content);}}catch (Exception ex){MessageBox.Show($"加载设置失败: {ex.Message}");}// 返回默认设置var defaults = new Settings{ForegroundColor = Color.White,BackgroundColor = Color.FromArgb(30, 30, 30), // 改为暗黑背景色TextFont = new Font("微软雅黑", 24)};defaults.Save(); // 创建默认配置文件return defaults;}}}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/75805.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PowerBI 条形图显示数值和百分比

数据表: 三个度量值 销售额 VAR Sales SUM(销量表[销售量]) RETURNIF(ISBLANK(sales), 0, sales) //希望Y轴显示所有产品(没有记录显示0)就加这个代码&#xff0c;不希望显示就不加//注意, 因为Y轴显示的产品&#xff0c;会被筛选&#xff0c;所以用ALLSELECTED来获取当前筛…

python: audioFlux XXCC 提取梅尔频率倒谱系数 MFCC

承上一篇&#xff1a;python&#xff1a;audioFlux 使用教程 XXCC: 倒谱系数&#xff0c;支持所有频谱类型. 可以提取梅尔频率倒谱系数&#xff08;MFCC&#xff09; Cepstrum coefficients, supports all spectrum types. 以下是使用 audioflux 库中 XXCC 类计算倒谱系数…

为 docker 拉取镜像配置代理

为 Docker 配置代理&#xff0c;有 两个层面 的操作&#xff1a;(1) Docker 守护进程&#xff08;用于拉取镜像等操作&#xff09;&#xff0c;(2) Docker 容器内部&#xff08;容器内应用的网络流量&#xff09;。 我们这篇文章着重于前者&#xff0c;以下是详细步骤&#xff…

最新的es版本忘记密码,重置密码

刚刚安装了最新的es版本,就忘了密码,怎么重置密码呢? 一、进入es的斌目录 #进入es文件/bin 目录 ./elasticsearch-reset-password -u elastic 二 、输入对应的密码 然后再次访问 我的是去掉了ssl的访问 三、如果报错:解决 [main] WARN

cursor如何集成MCP服务

本文主要介绍 Cursor IDE 是如何通过 Model Context Protocol (MCP) 服务来增强其功能的。本文将重点介绍两个核心 MCP 服务的集成&#xff1a;GitHub MCP 服务和 Filesystem MCP 服务。 MCP 服务简介 MCP&#xff08;Model Context Protocol&#xff09;是一个允许 IDE 与各…

Linux LED驱动(gpio子系统)

0. gpio子系统 gpio子系统是linux内核当中用于管理GPIO资源的一套系统&#xff0c;它提供了很多GPIO相关的API接口&#xff0c;驱动程序中使用GPIO之前需要向gpio子系统申请。 gpio子系统的主要目的就是方便驱动开发者使用gpio&#xff0c;驱动开发者在设备树中添加gpio相关信息…

go中new和make有什么异同?

相同点&#xff1a;都是给变量分配内存 不同点&#xff1a; 作用类型不同。new通常给int、string、数组类型的变量分配内存&#xff0c;而make通常给slice、map、channel分配内存。返回值类型不同。new返回指向变量的指针&#xff0c;make返回的是变量本身new分配内存空间后&…

C/C++基础知识点

随着工作中琐事越来越多&#xff0c;静下来好好敲代码的时间越来越少&#xff0c;基础知识虽然简单&#xff0c;但常看常新&#xff0c;并记录下来共勉。 一、基础知识点 1. 内存区域中数据管理 在C和C中&#xff0c;内存分为多个区域&#xff0c;每个区域负责存储不同类型的…

消息中间件kafka,rabbitMQ

在分布式系统中,消息中间件是实现不同组件之间异步通信的关键技术。Kafka 和 RabbitMQ 是两个非常流行的消息中间件系统,它们各自有着不同的特点和应用场景。下面将分别介绍 Kafka 和 RabbitMQ,并讨论它们在消息队列中的使用。 一、Kafka (Apache Kafka) 主要特点: 高吞吐…

2k1000LA , 调试串口改成通信串口, uart.

客户的问题解决了&#xff0c;但是 调试串口 改成通信串口的问题&#xff0c;并没有解决&#xff0c;我走的其他的路径。 先准备一些资料。 以备以后使用。 网上的资料。 总结&#xff1a; 实际上 有几种思路了。 1 就是更改 设备树的 chosen 节点&#xff0c; 瑞芯微又单独…

springboot集成spring-cloud-context手动刷新并读取更新后的配置文件

背景 springboot单体项目在运行过程需要刷新springboot配置文件值&#xff0c;比如某个接口限流阈值&#xff0c;新增某个账户等场景。分布式设计的可以直接引入一些持久化中间件比如redis等&#xff0c;也可以用相关配置中心中间件如nacos等。处于成本等场景单体项目可以考虑①…

proteus8.17 环境配置

Proteus介绍 Proteus 8.17 是一款功能强大的电子设计自动化&#xff08;EDA&#xff09;软件&#xff0c;广泛应用于电子电路设计、仿真和分析。以下是其主要特点和新功能&#xff1a; ### 主要功能 - **电路仿真**&#xff1a;支持数字和模拟电路的仿真&#xff0c;包括静态…

手机端可部署的开源大模型; 通义千问2.5训练和推理需要的内存和外存

手机端可部署的开源大模型 目录 手机端可部署的开源大模型Qwen2.5 0.5B 7b 推理采用手机内存需要多少Qwen2.5 0.5B不同量化精度下的内存需求Qwen2.5 7B不同量化精度下的内存需求通义千问2.5训练和推理需要的内存和外存推理阶段1. Qwen2.5 - 7B2. Qwen2.5 - 14B3. Qwen2.5 - 72B…

【uniapp-兼容性处理】swiper在iOS上偶发出现后几张图片白屏情况

【日期】2025-04-14 【问题】 swiper在iOS上偶发出现后几张图片白屏情况 swiper内部的几个swiper-item垂直排列&#xff0c;各自进行滚动&#xff0c;样式方面兼容性出现问题 【原因】&#xff1a; 原代码&#xff1a;&#xff08;不应在swiper-item添加style属性&#xf…

SpringBoot连接MQTT客户端

引入依赖 <dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.client.mqttv3</artifactId><version>1.2.2</version> </dependency> 启动类 SpringBootApplication public class AxiosDemoApplic…

HTML:网页的骨架 — 入门详解教程

HTML&#xff1a;网页的骨架 — 入门详解教程 HTML&#xff08;HyperText Markup Language&#xff0c;超文本标记语言&#xff09;是构建网页的基础语言&#xff0c;负责定义网页的结构和内容。无论是简单的个人博客&#xff0c;还是复杂的企业网站&#xff0c;HTML都是不可或…

212、【图论】字符串接龙(Python)

题目描述 题目链接&#xff1a;110. 字符串接龙 代码实现 import collectionsn int(input()) beginStr, endStr input().split() strList [input() for _ in range(n)]deque collections.deque() # 使用队列遍历结点 deque.append([beginStr, 1]) # 存储当前字符串和遍…

操作系统导论——第19章 分页:快速地址转换(TLB)

使用分页作为核心机制来实现虚拟内存&#xff0c;可能会带来较高的性能开销。使用分页&#xff0c;就要将内存地址空间切分成大量固定大小的单元&#xff08;页&#xff09;&#xff0c;并且需要记录这些单元的地址映射信息。因为这些映射信息一般存储在物理内存中&#xff0c;…

使用Apache POI(Java)创建docx文档和表格

1、引入poi 依赖组件 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.0.0</version> </dependency> <dependency><groupId>org.apache.poi</groupId>&…

python cv2 安装

在Python中安装opencv-python&#xff08;即OpenCV库&#xff09;&#xff0c;通常有两种方法&#xff1a;使用pip命令或通过conda&#xff08;如果你使用的是Anaconda或Miniconda&#xff09;。以下是详细的步骤&#xff1a; 方法1&#xff1a;使用pip 打开你的命令行界面&am…