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

C# 桌面时钟(透明窗体、定时提醒、开机启动)

项目结构

DesktopClock/
├── Properties/
│   ├── AssemblyInfo.cs
│   └── Resources.resx
├── Forms/
│   ├── MainForm.cs
│   ├── MainForm.Designer.cs
│   ├── SettingsForm.cs
│   └── AlarmForm.cs
├── Classes/
│   ├── AlarmManager.cs
│   ├── RegistryHelper.cs
│   └── Win32API.cs
├── Icons/
│   ├── clock.ico
│   └── alarm.ico
└── Program.cs

代码实现

1. 主程序入口(Program.cs)

using System;
using System.Windows.Forms;
using DesktopClock.Properties;namespace DesktopClock
{internal static class Program{/// <summary>/// 应用程序的主入口点/// </summary>[STAThread]static void Main(){// 处理高DPI设置Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);// 检查是否已经运行bool createdNew;using (var mutex = new System.Threading.Mutex(true, "DesktopClock_UniqueMutex", out createdNew)){if (createdNew){// 首次运行LoadSettings();// 启动主窗体Application.Run(new MainForm());}else{// 程序已经在运行MessageBox.Show("桌面时钟已经在运行中!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}}}private static void LoadSettings(){// 加载用户设置if (Settings.Default.UpgradeRequired){Settings.Default.Upgrade();Settings.Default.UpgradeRequired = false;Settings.Default.Save();}}}
}

2. 主窗体(MainForm.cs)

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using DesktopClock.Classes;
using DesktopClock.Properties;
using System.Drawing.Drawing2D;
using System.Media;namespace DesktopClock
{public partial class MainForm : Form{// 私有字段private bool isDragging = false;private Point dragStartPoint;private AlarmManager alarmManager;private System.Windows.Forms.Timer updateTimer;private System.Windows.Forms.Timer secondTimer;private NotifyIcon trayIcon;private ContextMenuStrip trayMenu;// 窗体透明度级别private float[] opacityLevels = { 0.3f, 0.5f, 0.7f, 0.9f, 1.0f };private int currentOpacityIndex = 3; // 默认0.9// 时钟样式private ClockStyle currentStyle = ClockStyle.Digital;private Font clockFont;private Color clockColor = Color.Lime;private Color shadowColor = Color.Black;private bool showShadow = true;private bool showSeconds = true;private bool showDate = true;private bool showWeek = true;// 时钟位置private FormPosition savedPosition = new FormPosition();public MainForm(){InitializeComponent();InitializeComponents();LoadSettings();InitializeTrayIcon();// 启动时钟StartClocks();}private void InitializeComponents(){// 设置窗体属性this.FormBorderStyle = FormBorderStyle.None;this.BackColor = Color.Black;this.TransparencyKey = Color.Black;this.TopMost = true;this.ShowInTaskbar = false;this.StartPosition = FormStartPosition.Manual;// 设置窗体大小this.ClientSize = new Size(300, 150);// 创建定时器updateTimer = new System.Windows.Forms.Timer();updateTimer.Interval = 1000; // 1秒更新updateTimer.Tick += UpdateTimer_Tick;secondTimer = new System.Windows.Forms.Timer();secondTimer.Interval = 100; // 0.1秒更新(用于秒动画)secondTimer.Tick += SecondTimer_Tick;// 创建闹钟管理器alarmManager = new AlarmManager();alarmManager.AlarmTriggered += AlarmManager_AlarmTriggered;}private void LoadSettings(){// 加载窗体位置savedPosition = Settings.Default.FormPosition;if (savedPosition != null && savedPosition.IsValid()){this.Location = savedPosition.Location;this.Size = savedPosition.Size;}else{// 默认位置:屏幕右上角this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Right - this.Width - 20,20);}// 加载透明度设置currentOpacityIndex = Settings.Default.OpacityLevel;if (currentOpacityIndex >= 0 && currentOpacityIndex < opacityLevels.Length){this.Opacity = opacityLevels[currentOpacityIndex];}else{this.Opacity = 0.9f;}// 加载时钟样式currentStyle = (ClockStyle)Settings.Default.ClockStyle;showSeconds = Settings.Default.ShowSeconds;showDate = Settings.Default.ShowDate;showWeek = Settings.Default.ShowWeek;clockColor = Settings.Default.ClockColor;// 加载字体try{clockFont = new Font(Settings.Default.FontName, Settings.Default.FontSize);}catch{clockFont = new Font("Arial", 24);}// 加载开机启动设置UpdateStartupMenuItem();}private void SaveSettings(){Settings.Default.FormPosition = new FormPosition(this.Location, this.Size);Settings.Default.OpacityLevel = currentOpacityIndex;Settings.Default.ClockStyle = (int)currentStyle;Settings.Default.ShowSeconds = showSeconds;Settings.Default.ShowDate = showDate;Settings.Default.ShowWeek = showWeek;Settings.Default.ClockColor = clockColor;Settings.Default.FontName = clockFont.Name;Settings.Default.FontSize = clockFont.Size;Settings.Default.Save();}private void InitializeTrayIcon(){// 创建托盘图标trayIcon = new NotifyIcon();trayIcon.Icon = Resources.clock_icon;trayIcon.Text = "桌面时钟";trayIcon.Visible = true;trayIcon.MouseClick += TrayIcon_MouseClick;// 创建托盘菜单trayMenu = new ContextMenuStrip();// 添加菜单项var styleMenu = new ToolStripMenuItem("时钟样式");styleMenu.DropDownItems.Add("数字时钟", null, (s, e) => ChangeClockStyle(ClockStyle.Digital));styleMenu.DropDownItems.Add("模拟时钟", null, (s, e) => ChangeClockStyle(ClockStyle.Analog));styleMenu.DropDownItems.Add("简约时钟", null, (s, e) => ChangeClockStyle(ClockStyle.Minimal));trayMenu.Items.Add(styleMenu);trayMenu.Items.Add(new ToolStripSeparator());trayMenu.Items.Add("设置透明度", null, (s, e) => ChangeOpacity());trayMenu.Items.Add("更改颜色...", null, (s, e) => ChangeColor());trayMenu.Items.Add(new ToolStripSeparator());trayMenu.Items.Add("显示/隐藏秒针", null, (s, e) => ToggleShowSeconds());trayMenu.Items.Add("显示/隐藏日期", null, (s, e) => ToggleShowDate());trayMenu.Items.Add("显示/隐藏星期", null, (s, e) => ToggleShowWeek());trayMenu.Items.Add(new ToolStripSeparator());// 闹钟管理var alarmMenu = new ToolStripMenuItem("闹钟管理");alarmMenu.DropDownItems.Add("添加闹钟...", null, (s, e) => AddAlarm());alarmMenu.DropDownItems.Add("查看闹钟列表", null, (s, e) => ShowAlarms());trayMenu.Items.Add(alarmMenu);trayMenu.Items.Add(new ToolStripSeparator());// 开机启动startupMenuItem = new ToolStripMenuItem("开机启动");startupMenuItem.Click += StartupMenuItem_Click;trayMenu.Items.Add(startupMenuItem);trayMenu.Items.Add(new ToolStripSeparator());trayMenu.Items.Add("退出", null, (s, e) => ExitApplication());trayIcon.ContextMenuStrip = trayMenu;}private ToolStripMenuItem startupMenuItem;private void UpdateStartupMenuItem(){bool isStartup = RegistryHelper.IsAppSetToStartup("DesktopClock");startupMenuItem.Checked = isStartup;startupMenuItem.Text = isStartup ? "开机启动 ✓" : "开机启动";}private void StartClocks(){updateTimer.Start();secondTimer.Start();}private void UpdateTimer_Tick(object sender, EventArgs e){// 检查闹钟alarmManager.CheckAlarms();// 强制重绘this.Invalidate();}private void SecondTimer_Tick(object sender, EventArgs e){// 只用于模拟时钟的秒针动画if (currentStyle == ClockStyle.Analog){this.Invalidate();}}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);Graphics g = e.Graphics;g.SmoothingMode = SmoothingMode.AntiAlias;g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;// 根据当前样式绘制时钟switch (currentStyle){case ClockStyle.Digital:DrawDigitalClock(g);break;case ClockStyle.Analog:DrawAnalogClock(g);break;case ClockStyle.Minimal:DrawMinimalClock(g);break;}}private void DrawDigitalClock(Graphics g){DateTime now = DateTime.Now;// 准备文本string timeText = now.ToString(showSeconds ? "HH:mm:ss" : "HH:mm");string dateText = now.ToString("yyyy-MM-dd");string weekText = GetChineseWeekDay(now.DayOfWeek);// 计算文本大小SizeF timeSize = g.MeasureString(timeText, clockFont);SizeF dateSize = showDate ? g.MeasureString(dateText, clockFont) : SizeF.Empty;SizeF weekSize = showWeek ? g.MeasureString(weekText, clockFont) : SizeF.Empty;// 计算总高度float totalHeight = timeSize.Height;if (showDate) totalHeight += dateSize.Height + 5;if (showWeek) totalHeight += weekSize.Height + 5;// 计算开始位置(垂直居中)float startY = (this.ClientSize.Height - totalHeight) / 2;float currentY = startY;// 绘制时间(带阴影效果)if (showShadow){DrawTextWithShadow(g, timeText, clockFont, new PointF((this.ClientSize.Width - timeSize.Width) / 2, currentY),clockColor, shadowColor, 2);}else{using (Brush brush = new SolidBrush(clockColor)){g.DrawString(timeText, clockFont, brush,(this.ClientSize.Width - timeSize.Width) / 2, currentY);}}currentY += timeSize.Height + 5;// 绘制日期if (showDate){if (showShadow){DrawTextWithShadow(g, dateText, clockFont,new PointF((this.ClientSize.Width - dateSize.Width) / 2, currentY),clockColor, shadowColor, 2);}else{using (Brush brush = new SolidBrush(clockColor)){g.DrawString(dateText, clockFont, brush,(this.ClientSize.Width - dateSize.Width) / 2, currentY);}}currentY += dateSize.Height + 5;}// 绘制星期if (showWeek){if (showShadow){DrawTextWithShadow(g, weekText, clockFont,new PointF((this.ClientSize.Width - weekSize.Width) / 2, currentY),clockColor, shadowColor, 2);}else{using (Brush brush = new SolidBrush(clockColor)){g.DrawString(weekText, clockFont, brush,(this.ClientSize.Width - weekSize.Width) / 2, currentY);}}}}private void DrawAnalogClock(Graphics g){DateTime now = DateTime.Now;int centerX = this.ClientSize.Width / 2;int centerY = this.ClientSize.Height / 2;int radius = Math.Min(centerX, centerY) - 20;// 绘制表盘using (Pen pen = new Pen(clockColor, 2)){g.DrawEllipse(pen, centerX - radius, centerY - radius, radius * 2, radius * 2);}// 绘制刻度for (int i = 0; i < 60; i++){double angle = i * 6 * Math.PI / 180;int length = (i % 5 == 0) ? 10 : 5;int width = (i % 5 == 0) ? 2 : 1;int x1 = (int)(centerX + (radius - 5) * Math.Sin(angle));int y1 = (int)(centerY - (radius - 5) * Math.Cos(angle));int x2 = (int)(centerX + (radius - 5 - length) * Math.Sin(angle));int y2 = (int)(centerY - (radius - 5 - length) * Math.Cos(angle));using (Pen pen = new Pen(clockColor, width)){g.DrawLine(pen, x1, y1, x2, y2);}}// 绘制数字for (int i = 1; i <= 12; i++){double angle = (i * 30 - 90) * Math.PI / 180;int numberRadius = radius - 25;int x = (int)(centerX + numberRadius * Math.Cos(angle));int y = (int)(centerY + numberRadius * Math.Sin(angle));string num = i.ToString();SizeF size = g.MeasureString(num, new Font(clockFont.FontFamily, 12));using (Brush brush = new SolidBrush(clockColor)){g.DrawString(num, new Font(clockFont.FontFamily, 12), brush,x - size.Width / 2, y - size.Height / 2);}}// 绘制时针double hourAngle = (now.Hour % 12 + now.Minute / 60.0) * 30 * Math.PI / 180;int hourHandLength = (int)(radius * 0.5);int hourX = (int)(centerX + hourHandLength * Math.Sin(hourAngle));int hourY = (int)(centerY - hourHandLength * Math.Cos(hourAngle));using (Pen pen = new Pen(clockColor, 4)){g.DrawLine(pen, centerX, centerY, hourX, hourY);}// 绘制分针double minuteAngle = (now.Minute + now.Second / 60.0) * 6 * Math.PI / 180;int minuteHandLength = (int)(radius * 0.7);int minuteX = (int)(centerX + minuteHandLength * Math.Sin(minuteAngle));int minuteY = (int)(centerY - minuteHandLength * Math.Cos(minuteAngle));using (Pen pen = new Pen(clockColor, 3)){g.DrawLine(pen, centerX, centerY, minuteX, minuteY);}// 绘制秒针(如果显示)if (showSeconds){double secondAngle = (now.Second + now.Millisecond / 1000.0) * 6 * Math.PI / 180;int secondHandLength = (int)(radius * 0.8);int secondX = (int)(centerX + secondHandLength * Math.Sin(secondAngle));int secondY = (int)(centerY - secondHandLength * Math.Cos(secondAngle));using (Pen pen = new Pen(Color.Red, 1)){g.DrawLine(pen, centerX, centerY, secondX, secondY);}// 绘制秒针尖端using (Brush brush = new SolidBrush(Color.Red)){g.FillEllipse(brush, secondX - 3, secondY - 3, 6, 6);}}// 绘制中心点using (Brush brush = new SolidBrush(clockColor)){g.FillEllipse(brush, centerX - 4, centerY - 4, 8, 8);}// 绘制日期(如果显示)if (showDate){string dateText = now.ToString("MM/dd");SizeF size = g.MeasureString(dateText, new Font(clockFont.FontFamily, 10));using (Brush brush = new SolidBrush(clockColor)){g.DrawString(dateText, new Font(clockFont.FontFamily, 10), brush,centerX - size.Width / 2, centerY + radius / 2);}}}private void DrawMinimalClock(Graphics g){DateTime now = DateTime.Now;// 只显示小时和分钟,使用大字体string timeText = now.ToString("HH:mm");using (Font largeFont = new Font(clockFont.FontFamily, 36, FontStyle.Bold)){SizeF timeSize = g.MeasureString(timeText, largeFont);if (showShadow){DrawTextWithShadow(g, timeText, largeFont,new PointF((this.ClientSize.Width - timeSize.Width) / 2, 20),clockColor, shadowColor, 3);}else{using (Brush brush = new SolidBrush(clockColor)){g.DrawString(timeText, largeFont, brush,(this.ClientSize.Width - timeSize.Width) / 2, 20);}}}}private void DrawTextWithShadow(Graphics g, string text, Font font, PointF location, Color textColor, Color shadowColor, int shadowOffset){// 绘制阴影using (Brush shadowBrush = new SolidBrush(shadowColor)){g.DrawString(text, font, shadowBrush,location.X + shadowOffset, location.Y + shadowOffset);}// 绘制文本using (Brush textBrush = new SolidBrush(textColor)){g.DrawString(text, font, textBrush, location);}}private string GetChineseWeekDay(DayOfWeek day){switch (day){case DayOfWeek.Sunday: return "星期日";case DayOfWeek.Monday: return "星期一";case DayOfWeek.Tuesday: return "星期二";case DayOfWeek.Wednesday: return "星期三";case DayOfWeek.Thursday: return "星期四";case DayOfWeek.Friday: return "星期五";case DayOfWeek.Saturday: return "星期六";default: return "";}}// 鼠标事件处理protected override void OnMouseDown(MouseEventArgs e){base.OnMouseDown(e);if (e.Button == MouseButtons.Left){isDragging = true;dragStartPoint = new Point(e.X, e.Y);this.Cursor = Cursors.SizeAll;}else if (e.Button == MouseButtons.Right){// 显示上下文菜单trayMenu.Show(this, e.Location);}}protected override void OnMouseMove(MouseEventArgs e){base.OnMouseMove(e);if (isDragging){Point newLocation = this.Location;newLocation.Offset(e.X - dragStartPoint.X, e.Y - dragStartPoint.Y);this.Location = newLocation;}}protected override void OnMouseUp(MouseEventArgs e){base.OnMouseUp(e);if (e.Button == MouseButtons.Left){isDragging = false;this.Cursor = Cursors.Default;// 保存新位置SaveSettings();}}protected override void OnMouseDoubleClick(MouseEventArgs e){base.OnMouseDoubleClick(e);if (e.Button == MouseButtons.Left){// 双击切换样式currentStyle = (ClockStyle)(((int)currentStyle + 1) % 3);this.Invalidate();SaveSettings();}}// 闹钟事件private void AlarmManager_AlarmTriggered(object sender, AlarmEventArgs e){// 在主线程中显示提醒this.Invoke(new Action(() =>{ShowAlarmNotification(e.Alarm);}));}private void ShowAlarmNotification(Alarm alarm){// 播放提示音SystemSounds.Exclamation.Play();// 显示通知if (trayIcon.Visible){trayIcon.ShowBalloonTip(5000, "闹钟提醒", $"{alarm.Name}\n{alarm.Time:HH:mm}", ToolTipIcon.Info);}// 显示提醒窗口using (var alarmForm = new AlarmForm(alarm)){alarmForm.ShowDialog();}}// 菜单功能private void ChangeClockStyle(ClockStyle style){currentStyle = style;this.Invalidate();SaveSettings();}private void ChangeOpacity(){currentOpacityIndex = (currentOpacityIndex + 1) % opacityLevels.Length;this.Opacity = opacityLevels[currentOpacityIndex];SaveSettings();}private void ChangeColor(){using (ColorDialog dialog = new ColorDialog()){dialog.Color = clockColor;dialog.FullOpen = true;if (dialog.ShowDialog() == DialogResult.OK){clockColor = dialog.Color;this.Invalidate();SaveSettings();}}}private void ToggleShowSeconds(){showSeconds = !showSeconds;SaveSettings();this.Invalidate();}private void ToggleShowDate(){showDate = !showDate;SaveSettings();this.Invalidate();}private void ToggleShowWeek(){showWeek = !showWeek;SaveSettings();this.Invalidate();}private void AddAlarm(){using (var alarmForm = new AlarmForm()){if (alarmForm.ShowDialog() == DialogResult.OK){alarmManager.AddAlarm(alarmForm.Alarm);SaveAlarms();}}}private void ShowAlarms(){using (var alarmsForm = new AlarmsForm(alarmManager)){alarmsForm.ShowDialog();SaveAlarms();}}private void StartupMenuItem_Click(object sender, EventArgs e){bool isStartup = RegistryHelper.IsAppSetToStartup("DesktopClock");if (isStartup){RegistryHelper.RemoveFromStartup("DesktopClock");}else{RegistryHelper.SetAppToStartup("DesktopClock", Application.ExecutablePath);}UpdateStartupMenuItem();}private void SaveAlarms(){Settings.Default.Alarms = alarmManager.SerializeAlarms();Settings.Default.Save();}private void TrayIcon_MouseClick(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){this.Visible = !this.Visible;}}private void ExitApplication(){SaveSettings();SaveAlarms();updateTimer.Stop();secondTimer.Stop();trayIcon.Visible = false;Application.Exit();}protected override void OnFormClosing(FormClosingEventArgs e){if (e.CloseReason == CloseReason.UserClosing){e.Cancel = true;this.Hide();trayIcon.ShowBalloonTip(1000, "桌面时钟", "时钟已隐藏到系统托盘", ToolTipIcon.Info);}base.OnFormClosing(e);}// 时钟样式枚举private enum ClockStyle{Digital = 0,Analog = 1,Minimal = 2}}// 窗体位置序列化类[Serializable]public class FormPosition{public Point Location { get; set; }public Size Size { get; set; }public FormPosition() { }public FormPosition(Point location, Size size){Location = location;Size = size;}public bool IsValid(){return Location.X >= 0 && Location.Y >= 0 && Size.Width > 0 && Size.Height > 0;}}
}

3. 主窗体设计器(MainForm.Designer.cs)

namespace DesktopClock
{partial class MainForm{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.components = new System.ComponentModel.Container();this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(300, 150);this.Name = "MainForm";this.Text = "桌面时钟";}#endregion}
}

4. 闹钟管理器(AlarmManager.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.IO;namespace DesktopClock.Classes
{public class AlarmManager{private List<Alarm> alarms = new List<Alarm>();private System.Windows.Forms.Timer checkTimer;public event EventHandler<AlarmEventArgs> AlarmTriggered;public AlarmManager(){checkTimer = new System.Windows.Forms.Timer();checkTimer.Interval = 1000; // 每秒检查一次checkTimer.Tick += CheckTimer_Tick;checkTimer.Start();}public void AddAlarm(Alarm alarm){alarms.Add(alarm);}public void RemoveAlarm(Alarm alarm){alarms.Remove(alarm);}public List<Alarm> GetAlarms(){return new List<Alarm>(alarms);}public void CheckAlarms(){DateTime now = DateTime.Now;foreach (var alarm in alarms.Where(a => a.IsEnabled)){if (alarm.ShouldTrigger(now)){OnAlarmTriggered(alarm);if (!alarm.Repeat){alarm.IsEnabled = false;}}}}private void CheckTimer_Tick(object sender, EventArgs e){CheckAlarms();}protected virtual void OnAlarmTriggered(Alarm alarm){AlarmTriggered?.Invoke(this, new AlarmEventArgs(alarm));}public string SerializeAlarms(){try{var serializer = new XmlSerializer(typeof(List<Alarm>));using (var writer = new StringWriter()){serializer.Serialize(writer, alarms);return writer.ToString();}}catch{return string.Empty;}}public void DeserializeAlarms(string xml){try{if (!string.IsNullOrEmpty(xml)){var serializer = new XmlSerializer(typeof(List<Alarm>));using (var reader = new StringReader(xml)){var deserialized = (List<Alarm>)serializer.Deserialize(reader);alarms = deserialized ?? new List<Alarm>();}}}catch{alarms = new List<Alarm>();}}}[Serializable]public class Alarm{public string Name { get; set; }public DateTime Time { get; set; }public bool IsEnabled { get; set; }public bool Repeat { get; set; }public DayOfWeek[] RepeatDays { get; set; }public DateTime LastTriggered { get; set; }public Alarm(){Name = "新闹钟";Time = DateTime.Now;IsEnabled = true;Repeat = false;RepeatDays = new DayOfWeek[0];}public bool ShouldTrigger(DateTime currentTime){if (!IsEnabled) return false;// 检查是否在触发时间范围内(允许±1分钟)if (Math.Abs((currentTime - Time).TotalMinutes) <= 1){// 防止重复触发(同一分钟内只触发一次)if ((currentTime - LastTriggered).TotalMinutes < 1)return false;if (Repeat){if (RepeatDays.Length == 0 || RepeatDays.Contains(currentTime.DayOfWeek)){LastTriggered = currentTime;return true;}}else{LastTriggered = currentTime;return true;}}return false;}}public class AlarmEventArgs : EventArgs{public Alarm Alarm { get; }public AlarmEventArgs(Alarm alarm){Alarm = alarm;}}
}

5. 闹钟设置窗体(AlarmForm.cs)

using System;
using System.Windows.Forms;
using DesktopClock.Classes;namespace DesktopClock
{public partial class AlarmForm : Form{public Alarm Alarm { get; private set; }private CheckBox[] dayCheckboxes = new CheckBox[7];private string[] dayNames = { "周一", "周二", "周三", "周四", "周五", "周六", "周日" };public AlarmForm() : this(null) { }public AlarmForm(Alarm existingAlarm){InitializeComponent();InitializeDayCheckboxes();if (existingAlarm != null){Alarm = existingAlarm;LoadAlarmData();}else{Alarm = new Alarm();timePicker.Value = DateTime.Now.AddMinutes(1);}}private void InitializeComponent(){this.Text = "设置闹钟";this.Size = new System.Drawing.Size(350, 300);this.FormBorderStyle = FormBorderStyle.FixedDialog;this.MaximizeBox = false;this.MinimizeBox = false;this.StartPosition = FormStartPosition.CenterScreen;// 名称标签var nameLabel = new Label{Text = "闹钟名称:",Location = new System.Drawing.Point(20, 20),Size = new System.Drawing.Size(80, 20)};// 名称文本框var nameTextBox = new TextBox{Location = new System.Drawing.Point(100, 20),Size = new System.Drawing.Size(200, 20)};nameTextBox.TextChanged += (s, e) => Alarm.Name = nameTextBox.Text;// 时间标签var timeLabel = new Label{Text = "提醒时间:",Location = new System.Drawing.Point(20, 50),Size = new System.Drawing.Size(80, 20)};// 时间选择器timePicker = new DateTimePicker{Location = new System.Drawing.Point(100, 50),Size = new System.Drawing.Size(100, 20),Format = DateTimePickerFormat.Time,ShowUpDown = true};timePicker.ValueChanged += (s, e) => Alarm.Time = timePicker.Value;// 重复复选框var repeatCheckBox = new CheckBox{Text = "重复",Location = new System.Drawing.Point(20, 80),Size = new System.Drawing.Size(60, 20)};repeatCheckBox.CheckedChanged += (s, e) =>{Alarm.Repeat = repeatCheckBox.Checked;panelDays.Enabled = repeatCheckBox.Checked;};// 重复日期面板panelDays = new Panel{Location = new System.Drawing.Point(20, 110),Size = new System.Drawing.Size(300, 60),Enabled = false};// 启用复选框var enabledCheckBox = new CheckBox{Text = "启用闹钟",Location = new System.Drawing.Point(20, 180),Size = new System.Drawing.Size(100, 20),Checked = true};enabledCheckBox.CheckedChanged += (s, e) => Alarm.IsEnabled = enabledCheckBox.Checked;// 按钮var okButton = new Button{Text = "确定",Location = new System.Drawing.Point(150, 220),Size = new System.Drawing.Size(80, 30),DialogResult = DialogResult.OK};var cancelButton = new Button{Text = "取消",Location = new System.Drawing.Point(240, 220),Size = new System.Drawing.Size(80, 30),DialogResult = DialogResult.Cancel};// 添加控件this.Controls.AddRange(new Control[]{nameLabel, nameTextBox, timeLabel, timePicker,repeatCheckBox, panelDays, enabledCheckBox,okButton, cancelButton});this.AcceptButton = okButton;this.CancelButton = cancelButton;}private void InitializeDayCheckboxes(){for (int i = 0; i < 7; i++){dayCheckboxes[i] = new CheckBox{Text = dayNames[i],Location = new System.Drawing.Point(i * 40, 10),Size = new System.Drawing.Size(40, 20),Tag = (DayOfWeek)((i + 1) % 7) // 周日是0,调整为最后};int index = i; // 捕获变量dayCheckboxes[i].CheckedChanged += (s, e) =>{UpdateRepeatDays();};panelDays.Controls.Add(dayCheckboxes[i]);}}private void LoadAlarmData(){// 查找并设置控件foreach (Control ctrl in this.Controls){if (ctrl is TextBox && ctrl.Name.Contains("name")){((TextBox)ctrl).Text = Alarm.Name;}else if (ctrl is DateTimePicker){((DateTimePicker)ctrl).Value = Alarm.Time;}else if (ctrl is CheckBox checkBox){if (checkBox.Text == "重复"){checkBox.Checked = Alarm.Repeat;}else if (checkBox.Text == "启用闹钟"){checkBox.Checked = Alarm.IsEnabled;}}}// 设置重复日期if (Alarm.RepeatDays != null){foreach (var checkbox in dayCheckboxes){checkbox.Checked = Alarm.RepeatDays.Contains((DayOfWeek)checkbox.Tag);}}}private void UpdateRepeatDays(){var selectedDays = new List<DayOfWeek>();foreach (var checkbox in dayCheckboxes){if (checkbox.Checked){selectedDays.Add((DayOfWeek)checkbox.Tag);}}Alarm.RepeatDays = selectedDays.ToArray();}private DateTimePicker timePicker;private Panel panelDays;}
}

参考代码 C# 桌面时钟(透明窗体,定时提醒,开机启动) www.youwenfan.com/contentcnt/49380.html

6. 闹钟列表窗体(AlarmsForm.cs)

using System;
using System.Windows.Forms;
using DesktopClock.Classes;
using System.Drawing;namespace DesktopClock
{public partial class AlarmsForm : Form{private AlarmManager alarmManager;private ListView listView;public AlarmsForm(AlarmManager manager){alarmManager = manager;InitializeComponent();LoadAlarms();}private void InitializeComponent(){this.Text = "闹钟列表";this.Size = new Size(500, 300);this.FormBorderStyle = FormBorderStyle.FixedDialog;this.MaximizeBox = false;this.MinimizeBox = false;this.StartPosition = FormStartPosition.CenterScreen;// 列表视图listView = new ListView{View = View.Details,FullRowSelect = true,GridLines = true,Location = new Point(10, 10),Size = new Size(460, 200)};// 添加列listView.Columns.Add("名称", 150);listView.Columns.Add("时间", 100);listView.Columns.Add("重复", 80);listView.Columns.Add("状态", 80);listView.Columns.Add("重复日期", 150);// 按钮var addButton = new Button{Text = "添加",Location = new Point(10, 220),Size = new Size(80, 30)};addButton.Click += AddButton_Click;var editButton = new Button{Text = "编辑",Location = new Point(100, 220),Size = new Size(80, 30)};editButton.Click += EditButton_Click;var deleteButton = new Button{Text = "删除",Location = new Point(190, 220),Size = new Size(80, 30)};deleteButton.Click += DeleteButton_Click;var toggleButton = new Button{Text = "启用/禁用",Location = new Point(280, 220),Size = new Size(80, 30)};toggleButton.Click += ToggleButton_Click;var closeButton = new Button{Text = "关闭",Location = new Point(370, 220),Size = new Size(80, 30),DialogResult = DialogResult.Cancel};this.Controls.AddRange(new Control[]{listView, addButton, editButton,deleteButton, toggleButton, closeButton});this.CancelButton = closeButton;}private void LoadAlarms(){listView.Items.Clear();foreach (var alarm in alarmManager.GetAlarms()){var item = new ListViewItem(alarm.Name);item.SubItems.Add(alarm.Time.ToString("HH:mm"));item.SubItems.Add(alarm.Repeat ? "是" : "否");item.SubItems.Add(alarm.IsEnabled ? "启用" : "禁用");string daysText = "";if (alarm.RepeatDays != null && alarm.RepeatDays.Length > 0){foreach (var day in alarm.RepeatDays){daysText += GetDayAbbreviation(day) + " ";}}item.SubItems.Add(daysText);item.Tag = alarm;listView.Items.Add(item);}}private string GetDayAbbreviation(DayOfWeek day){switch (day){case DayOfWeek.Sunday: return "日";case DayOfWeek.Monday: return "一";case DayOfWeek.Tuesday: return "二";case DayOfWeek.Wednesday: return "三";case DayOfWeek.Thursday: return "四";case DayOfWeek.Friday: return "五";case DayOfWeek.Saturday: return "六";default: return "";}}private void AddButton_Click(object sender, EventArgs e){using (var alarmForm = new AlarmForm()){if (alarmForm.ShowDialog() == DialogResult.OK){alarmManager.AddAlarm(alarmForm.Alarm);LoadAlarms();}}}private void EditButton_Click(object sender, EventArgs e){if (listView.SelectedItems.Count > 0){var alarm = (Alarm)listView.SelectedItems[0].Tag;using (var alarmForm = new AlarmForm(alarm)){if (alarmForm.ShowDialog() == DialogResult.OK){LoadAlarms();}}}}private void DeleteButton_Click(object sender, EventArgs e){if (listView.SelectedItems.Count > 0){if (MessageBox.Show("确定要删除这个闹钟吗?", "确认删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes){var alarm = (Alarm)listView.SelectedItems[0].Tag;alarmManager.RemoveAlarm(alarm);LoadAlarms();}}}private void ToggleButton_Click(object sender, EventArgs e){if (listView.SelectedItems.Count > 0){var alarm = (Alarm)listView.SelectedItems[0].Tag;alarm.IsEnabled = !alarm.IsEnabled;LoadAlarms();}}}
}

7. 注册表助手(RegistryHelper.cs)

using System;
using Microsoft.Win32;
using System.Security;
using System.Windows.Forms;namespace DesktopClock.Classes
{public static class RegistryHelper{private const string RUN_REGISTRY_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";public static bool SetAppToStartup(string appName, string appPath){try{using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RUN_REGISTRY_KEY, true)){if (key != null){key.SetValue(appName, $"\"{appPath}\"");return true;}}}catch (SecurityException ex){MessageBox.Show($"权限不足: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}catch (UnauthorizedAccessException ex){MessageBox.Show($"访问被拒绝: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}catch (Exception ex){MessageBox.Show($"设置失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}return false;}public static bool RemoveFromStartup(string appName){try{using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RUN_REGISTRY_KEY, true)){if (key != null){key.DeleteValue(appName, false);return true;}}}catch (Exception ex){MessageBox.Show($"删除失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}return false;}public static bool IsAppSetToStartup(string appName){try{using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RUN_REGISTRY_KEY, false)){if (key != null){return key.GetValue(appName) != null;}}}catch{// 忽略错误}return false;}public static string GetStartupAppPath(string appName){try{using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RUN_REGISTRY_KEY, false)){if (key != null){return key.GetValue(appName)?.ToString();}}}catch{// 忽略错误}return null;}}
}

8. 设置类(Settings.cs)

using System;
using System.Drawing;
using System.Configuration;namespace DesktopClock.Properties
{internal sealed partial class Settings : ApplicationSettingsBase{private static Settings defaultInstance = (Settings)Synchronized(new Settings());public static Settings Default{get { return defaultInstance; }}[UserScopedSetting][DefaultSettingValue("true")]public bool UpgradeRequired{get { return (bool)this["UpgradeRequired"]; }set { this["UpgradeRequired"] = value; }}[UserScopedSetting]public FormPosition FormPosition{get { var value = this["FormPosition"];return value as FormPosition ?? new FormPosition();}set { this["FormPosition"] = value; }}[UserScopedSetting][DefaultSettingValue("3")]public int OpacityLevel{get { return (int)this["OpacityLevel"]; }set { this["OpacityLevel"] = value; }}[UserScopedSetting][DefaultSettingValue("0")]public int ClockStyle{get { return (int)this["ClockStyle"]; }set { this["ClockStyle"] = value; }}[UserScopedSetting][DefaultSettingValue("true")]public bool ShowSeconds{get { return (bool)this["ShowSeconds"]; }set { this["ShowSeconds"] = value; }}[UserScopedSetting][DefaultSettingValue("true")]public bool ShowDate{get { return (bool)this["ShowDate"]; }set { this["ShowDate"] = value; }}[UserScopedSetting][DefaultSettingValue("true")]public bool ShowWeek{get { return (bool)this["ShowWeek"]; }set { this["ShowWeek"] = value; }}[UserScopedSetting][DefaultSettingValue("Lime")]public Color ClockColor{get { return (Color)this["ClockColor"]; }set { this["ClockColor"] = value; }}[UserScopedSetting][DefaultSettingValue("Arial")]public string FontName{get { return (string)this["FontName"]; }set { this["FontName"] = value; }}[UserScopedSetting][DefaultSettingValue("24")]public float FontSize{get { return (float)this["FontSize"]; }set { this["FontSize"] = value; }}[UserScopedSetting][DefaultSettingValue("")]public string Alarms{get { return (string)this["Alarms"]; }set { this["Alarms"] = value; }}}
}

9. 项目配置文件(App.config)

<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"><section name="DesktopClock.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /></sectionGroup></configSections><startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup><userSettings><DesktopClock.Properties.Settings><setting name="UpgradeRequired" serializeAs="String"><value>True</value></setting><setting name="FormPosition" serializeAs="String"><value /></setting><setting name="OpacityLevel" serializeAs="String"><value>3</value></setting><setting name="ClockStyle" serializeAs="String"><value>0</value></setting><setting name="ShowSeconds" serializeAs="String"><value>True</value></setting><setting name="ShowDate" serializeAs="String"><value>True</value></setting><setting name="ShowWeek" serializeAs="String"><value>True</value></setting><setting name="ClockColor" serializeAs="String"><value>Lime</value></setting><setting name="FontName" serializeAs="String"><value>Arial</value></setting><setting name="FontSize" serializeAs="String"><value>24</value></setting><setting name="Alarms" serializeAs="String"><value /></setting></DesktopClock.Properties.Settings></userSettings>
</configuration>

使用说明

1. 编译和运行

# 使用Visual Studio
1. 打开DesktopClock.sln
2. 编译项目 (F6)
3. 运行 (F5)# 使用命令行
msbuild DesktopClock.csproj
DesktopClock.exe

2. 功能操作

操作 功能
左键拖拽 移动时钟位置
右键单击 显示设置菜单
双击时钟 切换时钟样式
托盘图标右键 显示完整菜单
托盘图标左键 显示/隐藏时钟

3. 时钟样式

  1. 数字时钟:显示时间、日期、星期
  2. 模拟时钟:传统表盘样式
  3. 简约时钟:只显示小时和分钟

4. 闹钟功能

  • 支持单次和重复闹钟
  • 可设置重复日期
  • 闹钟触发时显示提示和播放声音
  • 支持系统托盘通知

配置说明

1. 透明度级别

// 5个级别:30%, 50%, 70%, 90%, 100%
private float[] opacityLevels = { 0.3f, 0.5f, 0.7f, 0.9f, 1.0f };

2. 开机启动

  • 通过修改注册表实现
  • 路径:HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
  • 键名:DesktopClock

3. 数据存储

  • 设置存储在:%LOCALAPPDATA%\DesktopClock
  • 闹钟数据序列化为XML格式

扩展功能建议

  1. 天气显示:集成天气API显示实时天气
  2. 倒计时:添加倒计时功能
  3. 世界时钟:显示多个时区时间
  4. 屏幕边缘吸附:自动吸附到屏幕边缘
  5. 主题皮肤:支持多种主题颜色
  6. 语音报时:整点语音播报
  7. 快捷键:自定义快捷键操作
http://www.jsqmd.com/news/665452/

相关文章:

  • Lattice CrossLinkNx实战:如何将设计固化到SPI Flash(含JTAG2SPI烧录避坑指南)
  • Git 2.27+ 新警告别慌!3分钟搞懂 pull.rebase 和 pull.ff 到底怎么选(附保姆级配置命令)
  • 别再只会用action了!手把手教你用el-upload的http-request实现自定义文件上传(附完整前后端代码)
  • 有实力的冷库公司怎么选,探讨湖南雪源制冷冷库公司口碑与价格 - 工业推荐榜
  • 免费在线SVG路径编辑器终极指南:零基础快速上手矢量图形编辑
  • MQTTnet 5.0实战:如何用最新特性打造物联网消息系统(附.NET 6+代码示例)
  • Bilibili-Evolved:个性化你的B站体验,解锁高效浏览新姿势
  • 米哈游游戏启动器终极指南:如何用Starward一站式管理你的游戏世界
  • LabVIEW比例流量阀自动测试系统开发
  • 从嵌入式到FPGA:一个RISC-V爱好者的Verilog入门避坑指南
  • 【C++】中INI配置文件读取技术详解
  • Windows 11 高效部署 PyTorch 1.7.1:从 CUDA 环境配置到安装验证全攻略
  • 探讨有实力的钢格板加工厂,哪家专业又靠谱 - 工业品牌热点
  • B站评论区成分检测器:3秒读懂评论者,智能标注让互动更有价值
  • Unity中MoveTowards()的隐藏玩法:结合协程控制UI渐变、物体平滑移动的完整配置流程
  • 抖音内容高效采集:从单视频到批量下载的全流程技术指南
  • Windows驱动管理专业指南:DriverStore Explorer实用教程
  • 2024年最新IntelliJ IDEA插件安装避坑指南:从MybatisCodeHelper到Rainbow Brackets
  • 3分钟快速上手:用Mem Reduct彻底解决Windows内存卡顿问题
  • AtCoder Beginner Contest 454 D 题解
  • 从‘一刀切’到精细化:实战firewall-cmd管理开发、测试、生产环境的SSH访问策略
  • 泉盛UV-K5/K6终极刷机指南:LOSEHU固件功能全面解锁教程
  • 番茄小说下载器:打造个人离线小说图书馆的终极解决方案
  • 手把手教程:5分钟用ollama部署Yi-Coder-1.5B代码助手
  • APP广告网站端口是非标准的
  • 专业指南:如何为Windows 11 24H2 LTSC系统完整恢复微软商店功能
  • 早晚通勤没空做怎么瘦?2026上班族营养减脂早晚代餐红黑榜,精准控卡护代谢 - GrowthUME
  • PowerPaint-V1功能体验:极速图像消除与智能填充,真正语义级的图像理解
  • 免费解锁鸣潮120帧:WaveTools游戏优化工具箱完全教程
  • 3分钟掌握音乐自由:Unlock Music Electron终极解密指南