折腾笔记[43]-基于csharp的时钟

摘要

基于csharp的时钟.

代码

  1. 工程定义
    clock.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <RootNamespace>exp76_eink_display</RootNamespace>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>

    <!-- 应用程序图标 -->
    <ApplicationIcon>clock.ico</ApplicationIcon>
    
    <!-- 版本信息 -->
    <Version>2026.02.15.1120</Version>
    <FileVersion>2026.02.15.1120</FileVersion>
    <AssemblyVersion>2026.02.15.1120</AssemblyVersion>
    
    <!-- 作者信息 -->
    <Authors>qsbye</Authors>
    <Company>ByeIO</Company>
    
    <!-- 单文件发布配置 -->
    <PublishSingleFile>true</PublishSingleFile>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
    <PublishReadyToRun>true</PublishReadyToRun>
    
  </PropertyGroup>

</Project>
  1. 主程序
    Program.cs
namespace exp76_eink_display;

static class Program
{
    /// <summary>
    ///  程序主入口
    /// </summary>
    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();
        Application.Run(new Clock());
    }    
}

Clock.cs

// 文件: Clock.cs
// 功能: 墨水屏时钟

// 标准库
using System;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Windows.Forms;

namespace exp76_eink_display
{
    public partial class Clock : Form
    {
        #region 常量定义
        // 字体比例系数
        private const float HOUR_FONT_RATIO = 0.25f;    // 小时字体占屏幕高度比例
        private const float MINUTE_FONT_RATIO = 0.25f;  // 分钟字体占屏幕高度比例
        #endregion 常量定义

        #region UI控件
        // 顶部导航栏
        private Panel topPanel;
        private Button btnSettings;
        private Panel settingsPanel;
        private CheckBox chkAutoStart;
        private Button btnCloseSettings;
        private bool isSettingsOpen = false;

        // 时间显示标签
        private Label labelHour;    // 小时标签
        private Label labelMinute;  // 分钟标签
        
        // 右键菜单
        private ContextMenuStrip contextMenu;
        #endregion UI控件

        #region 开机自启相关
        private string startupFolderPath;
        private string shortcutPath;
        private string appPath;
        #endregion 开机自启相关

        #region 构造方法
        public Clock()
        {
            InitializeComponent();
            InitializeCustomComponents();
            InitializeAutoStart();
            InitializeContextMenu();
            
            // 窗体加载时居中显示时间
            this.Load += Clock_Load;
            // 窗体大小改变时重新居中
            this.Resize += Clock_Resize;
            // 定时器触发更新时间
            this.timer1.Tick += Timer1_Tick;
            // 双击退出全屏
            // this.DoubleClick += Clock_DoubleClick;
            // 按键退出(ESC键)
            this.KeyPreview = true;
            this.KeyDown += Clock_KeyDown;
        }
        #endregion 构造方法

        #region 初始化方法
        /// <summary>
        /// 初始化自定义UI组件
        /// </summary>
        private void InitializeCustomComponents()
        {
            // 移除原有labelTime(由设计器添加)
            if (this.labelTime != null)
            {
                this.Controls.Remove(this.labelTime);
                this.labelTime.Dispose();
                this.labelTime = null;
            }

            // 创建小时标签(上半部分)
            labelHour = new Label
            {
                Name = "labelHour",
                AutoSize = true,
                TextAlign = ContentAlignment.MiddleCenter,
                ForeColor = Color.Black,
                BackColor = Color.Transparent
            };

            // 创建分钟标签(下半部分,斜体)
            labelMinute = new Label
            {
                Name = "labelMinute",
                AutoSize = true,
                TextAlign = ContentAlignment.MiddleCenter,
                ForeColor = Color.Black,
                BackColor = Color.Transparent
            };

            // 添加标签到窗体
            this.Controls.Add(labelHour);
            this.Controls.Add(labelMinute);
            labelHour.BringToFront();
            labelMinute.BringToFront();

            // 创建顶部导航栏
            topPanel = new Panel
            {
                Name = "topPanel",
                Height = 40,
                Dock = DockStyle.Top,
                BackColor = Color.FromArgb(240, 240, 240),
                Visible = false // 默认隐藏,非全屏时显示
            };

            // 创建设置按钮
            btnSettings = new Button
            {
                Name = "btnSettings",
                Text = "⚙ 设置",
                Height = 30,
                Top = 5,
                Left = 10,
                FlatStyle = FlatStyle.Flat,
                BackColor = Color.White,
                Cursor = Cursors.Hand,
                // 启用自动大小
                AutoSize = true,           
                // 或 GrowOnly
                AutoSizeMode = AutoSizeMode.GrowAndShrink  
            };
            btnSettings.FlatAppearance.BorderColor = Color.LightGray;
            btnSettings.Click += BtnSettings_Click;

            topPanel.Controls.Add(btnSettings);
            this.Controls.Add(topPanel);

            // 创建设置面板(下拉菜单样式)
            settingsPanel = new Panel
            {
                Name = "settingsPanel",
                Height = 100,
                Top = 45,
                Left = 10,
                BackColor = Color.White,
                BorderStyle = BorderStyle.FixedSingle,
                Visible = false,
                // 启用自动大小
                AutoSize = true,           
                // 或 GrowOnly
                AutoSizeMode = AutoSizeMode.GrowAndShrink  
            };

            // 开机自启勾选框
            chkAutoStart = new CheckBox
            {
                Name = "chkAutoStart",
                Text = "开机自启",
                AutoSize = true,
                Top = 15,
                Left = 15,
                Checked = false
            };
            chkAutoStart.CheckedChanged += ChkAutoStart_CheckedChanged;

            // 关闭设置按钮
            btnCloseSettings = new Button
            {
                Name = "btnCloseSettings",
                Text = "关闭",
                Height = 25,
                Top = 55,
                Left = 120,
                FlatStyle = FlatStyle.Flat,
                // 启用自动大小
                AutoSize = true,           
                // 或 GrowOnly
                AutoSizeMode = AutoSizeMode.GrowAndShrink  
            };
            btnCloseSettings.Click += (s, e) => { settingsPanel.Visible = false; isSettingsOpen = false; };

            settingsPanel.Controls.Add(chkAutoStart);
            settingsPanel.Controls.Add(btnCloseSettings);
            this.Controls.Add(settingsPanel);
            settingsPanel.BringToFront();
        }

        /// <summary>
        /// 初始化开机自启功能
        /// </summary>
        private void InitializeAutoStart()
        {
            startupFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
            
            // 使用 Process 获取实际的可执行文件路径,而不是 DLL 路径
            appPath = Process.GetCurrentProcess().MainModule.FileName;
            
            string appName = Path.GetFileNameWithoutExtension(appPath);
            shortcutPath = Path.Combine(startupFolderPath, appName + ".lnk");
            chkAutoStart.Checked = File.Exists(shortcutPath);
        }

        /// <summary>
        /// 初始化右键菜单
        /// </summary>
        private void InitializeContextMenu()
        {
            // 创建右键菜单
            contextMenu = new ContextMenuStrip();
            
            // 添加"退出全屏"菜单项
            ToolStripMenuItem menuExitFullScreen = new ToolStripMenuItem
            {
                Name = "menuExitFullScreen",
                Text = "退出全屏",
                // 初始状态下非全屏,禁用该选项
                Enabled = false  
            };
            menuExitFullScreen.Click += MenuExitFullScreen_Click;

            // 添加"进入全屏"菜单项
            ToolStripMenuItem menuEnterFullScreen = new ToolStripMenuItem
            {
                Name = "menuEnterFullScreen",
                Text = "进入全屏",
                // 初始状态下非全屏,禁用该选项
                Enabled = false  
            };
            menuEnterFullScreen.Click += MenuEnterFullScreen_Click;
            
            // 添加分隔线
            ToolStripSeparator separator = new ToolStripSeparator();
            
            // 添加"退出程序"菜单项
            ToolStripMenuItem menuExit = new ToolStripMenuItem
            {
                Name = "menuExit",
                Text = "退出程序"
            };
            menuExit.Click += (s, e) => this.Close();
            
            // 将菜单项添加到右键菜单
            contextMenu.Items.Add(menuExitFullScreen);
            contextMenu.Items.Add(menuEnterFullScreen);
            contextMenu.Items.Add(separator);
            contextMenu.Items.Add(menuExit);
            
            // 将右键菜单关联到窗体和标签控件
            this.ContextMenuStrip = contextMenu;
            labelHour.ContextMenuStrip = contextMenu;
            labelMinute.ContextMenuStrip = contextMenu;
        }
        #endregion 初始化方法

        #region 事件处理方法
        /// <summary>
        /// 设置按钮点击事件
        /// </summary>
        private void BtnSettings_Click(object sender, EventArgs e)
        {
            isSettingsOpen = !isSettingsOpen;
            settingsPanel.Visible = isSettingsOpen;
        }

        /// <summary>
        /// 开机自启选项变更事件
        /// </summary>
        private void ChkAutoStart_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if (chkAutoStart.Checked)
                {
                    CreateStartupShortcut();
                    // MessageBox.Show("已添加到开机自启", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    RemoveStartupShortcut();
                    // MessageBox.Show("已取消开机自启", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"操作失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                chkAutoStart.CheckedChanged -= ChkAutoStart_CheckedChanged;
                chkAutoStart.Checked = !chkAutoStart.Checked;
                chkAutoStart.CheckedChanged += ChkAutoStart_CheckedChanged;
            }
        }

        /// <summary>
        /// 退出全屏菜单点击事件
        /// </summary>
        private void MenuExitFullScreen_Click(object sender, EventArgs e)
        {
            ExitFullScreen();
        }

        /// <summary>
        /// 进入全屏菜单点击事件
        /// </summary>
        private void MenuEnterFullScreen_Click(object sender, EventArgs e)
        {
            EnterFullScreen();
        }

        /// <summary>
        /// 窗体加载事件
        /// </summary>
        private void Clock_Load(object sender, EventArgs e)
        {
            UpdateTime();
            AdjustFontSize();
            CenterLabels();
            UpdateTopPanelVisibility();
            UpdateContextMenuState();
        }

        /// <summary>
        /// 窗体大小改变事件
        /// </summary>
        private void Clock_Resize(object sender, EventArgs e)
        {
            AdjustFontSize();
            CenterLabels();
            UpdateTopPanelVisibility();
            UpdateContextMenuState();
        }

        /// <summary>
        /// 定时器触发事件
        /// </summary>
        private void Timer1_Tick(object sender, EventArgs e)
        {
            UpdateTime();
            if (DateTime.Now.Second == 0)
            {
                AdjustFontSize();
                CenterLabels();
            }
        }

        /// <summary>
        /// 双击窗体事件(切换全屏)
        /// </summary>
        private void Clock_DoubleClick(object sender, EventArgs e)
        {
            ToggleFullScreen();
        }

        /// <summary>
        /// 键盘按下事件
        /// </summary>
        private void Clock_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                this.Close();
            }
        }
        #endregion 事件处理方法

        #region 功能方法
        /// <summary>
        /// 创建开机自启快捷方式
        /// </summary>
        private void CreateStartupShortcut()
        {
            Type shellType = Type.GetTypeFromProgID("WScript.Shell");
            dynamic shell = Activator.CreateInstance(shellType);
            dynamic shortcut = shell.CreateShortcut(shortcutPath);
            
            shortcut.TargetPath = appPath;
            shortcut.WorkingDirectory = Path.GetDirectoryName(appPath);
            shortcut.Description = "E-ink Clock 开机自启";
            shortcut.Save();

            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shortcut);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(shell);
        }

        /// <summary>
        /// 移除开机自启快捷方式
        /// </summary>
        private void RemoveStartupShortcut()
        {
            if (File.Exists(shortcutPath))
            {
                File.Delete(shortcutPath);
            }
        }

        /// <summary>
        /// 更新顶部导航栏可见性
        /// </summary>
        private void UpdateTopPanelVisibility()
        {
            bool isFullScreen = this.WindowState == FormWindowState.Maximized && this.FormBorderStyle == FormBorderStyle.None;
            
            if (topPanel != null)
            {
                topPanel.Visible = !isFullScreen;
            }
            
            if (isFullScreen && settingsPanel != null)
            {
                settingsPanel.Visible = false;
                isSettingsOpen = false;
            }
        }

        /// <summary>
        /// 更新右键菜单状态
        /// </summary>
        private void UpdateContextMenuState()
        {
            if (contextMenu == null) return;
            
            bool isFullScreen = this.WindowState == FormWindowState.Maximized && this.FormBorderStyle == FormBorderStyle.None;
            
            // 查找"退出全屏"菜单项并更新状态
            ToolStripMenuItem menuExitFullScreen = contextMenu.Items.Find("menuExitFullScreen", false).FirstOrDefault() as ToolStripMenuItem;
            if (menuExitFullScreen != null)
            {
                menuExitFullScreen.Enabled = isFullScreen;
                // 非全屏时隐藏该选项
                menuExitFullScreen.Visible = isFullScreen;  
            }

            // 查找"进入全屏"菜单项并更新状态
            ToolStripMenuItem menuEnterFullScreen = contextMenu.Items.Find("menuEnterFullScreen", false).FirstOrDefault() as ToolStripMenuItem;
            if (menuEnterFullScreen != null)
            {
                menuEnterFullScreen.Enabled = !isFullScreen;
                // 全屏时隐藏该选项
                menuEnterFullScreen.Visible = !isFullScreen;  
            }
        }

        /// <summary>
        /// 切换全屏状态
        /// </summary>
        private void ToggleFullScreen()
        {
            if (this.WindowState == FormWindowState.Maximized && this.FormBorderStyle == FormBorderStyle.None)
            {
                ExitFullScreen();
            }
            else
            {
                EnterFullScreen();
            }
        }

        /// <summary>
        /// 进入全屏模式
        /// </summary>
        private void EnterFullScreen()
        {
            this.WindowState = FormWindowState.Maximized;
            this.FormBorderStyle = FormBorderStyle.None;
            
            UpdateTopPanelVisibility();
            UpdateContextMenuState();
            AdjustFontSize();
            CenterLabels();
        }

        /// <summary>
        /// 退出全屏模式
        /// </summary>
        private void ExitFullScreen()
        {
            this.WindowState = FormWindowState.Normal;
            this.FormBorderStyle = FormBorderStyle.Sizable;
            
            UpdateTopPanelVisibility();
            UpdateContextMenuState();
            AdjustFontSize();
            CenterLabels();
        }

        /// <summary>
        /// 更新时间显示
        /// </summary>
        private void UpdateTime()
        {
            DateTime now = DateTime.Now;
            // 上半部分显示小时
            labelHour.Text = now.ToString("HH");
            // 下半部分显示分钟(斜体)
            labelMinute.Text = now.ToString("mm");
        }

        /// <summary>
        /// 调整字体大小
        /// </summary>
        private void AdjustFontSize()
        {
            int navHeight = (topPanel != null && topPanel.Visible) ? topPanel.Height : 0;
            int margin = 20;
            
            int availableWidth = this.ClientSize.Width - margin * 2;
            int availableHeight = this.ClientSize.Height - navHeight - margin * 2;
            
            if (availableWidth <= 0 || availableHeight <= 0)
                return;

            // 屏幕分为上下两半
            int halfHeight = availableHeight / 2;

            // 计算小时字体大小(占上半部分的70%高度)
            float hourFontSize = halfHeight * HOUR_FONT_RATIO * 2;
            hourFontSize = Math.Max(Math.Min(hourFontSize, 400f), 40f);

            // 计算分钟字体大小(占下半部分的60%高度)
            float minuteFontSize = halfHeight * MINUTE_FONT_RATIO * 2;
            minuteFontSize = Math.Max(Math.Min(minuteFontSize, 350f), 30f);

            // 应用字体:小时粗体,分钟粗体+斜体
            labelHour.Font = new Font("Microsoft YaHei", hourFontSize, FontStyle.Bold);
            labelMinute.Font = new Font("Microsoft YaHei", minuteFontSize, FontStyle.Bold | FontStyle.Italic);
        }

        /// <summary>
        /// 居中显示标签
        /// </summary>
        private void CenterLabels()
        {
            int navHeight = (topPanel != null && topPanel.Visible) ? topPanel.Height : 0;
            int clientHeight = this.ClientSize.Height - navHeight;
            int halfHeight = clientHeight / 2;

            // 水平居中
            labelHour.Left = (this.ClientSize.Width - labelHour.Width) / 2;
            labelMinute.Left = (this.ClientSize.Width - labelMinute.Width) / 2;

            // 垂直分布:小时在上半部分居中,分钟在下半部分居中
            labelHour.Top = navHeight + (halfHeight - labelHour.Height) / 2;
            labelMinute.Top = navHeight + halfHeight + (halfHeight - labelMinute.Height) / 2;
        }
        #endregion 功能方法
    }
}

Clock.Designer.cs

namespace exp76_eink_display;

partial class Clock
{
    /// <summary>
    /// 必需的设计器变量。
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// 清理所有正在使用的资源。
    /// </summary>
    /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows 窗体设计器生成的代码

    /// <summary>
    /// 设计器支持所需的方法 - 请勿使用代码编辑器修改此方法的内容。
    /// </summary>
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
        this.labelTime = new System.Windows.Forms.Label();
        this.timer1 = new System.Windows.Forms.Timer(this.components);
        
        // 设置窗体
        this.AutoScaleMode = AutoScaleMode.Font;
        this.BackColor = System.Drawing.Color.White;
        this.FormBorderStyle = FormBorderStyle.None;
        this.WindowState = FormWindowState.Maximized;
        this.ClientSize = new Size(800, 450);
        this.Text = "电子时钟";
        
        // 设置时间标签
        this.labelTime.AutoSize = true;
        this.labelTime.Font = new System.Drawing.Font("Microsoft YaHei", 120F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point);
        this.labelTime.ForeColor = System.Drawing.Color.Black;
        this.labelTime.Location = new System.Drawing.Point(0, 0);
        this.labelTime.Name = "labelTime";
        this.labelTime.Size = new System.Drawing.Size(0, 265);
        this.labelTime.TabIndex = 0;
        this.labelTime.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
        
        // 添加控件到窗体
        this.Controls.Add(this.labelTime);
        
        // 设置定时器
        this.timer1.Interval = 1000;
        this.timer1.Enabled = true;
    }

    #endregion

    private System.Windows.Forms.Label labelTime;
    private System.Windows.Forms.Timer timer1;
}

效果

时钟运行
ezgif-3ead29215809a303
posted @ 2026-02-15 14:03  qsBye  阅读(16)  评论(0)    收藏  举报