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