lgk 发表于 2026-11-3 15:11

纯原生 Windows 闹钟工具V1.2

# 闹钟 · 项目说明

- 当前版本:v1.2.0
- 最后更新:2026-11-03
- 程序形态:Windows 原生桌面应用(C# / WPF / .NET 10)
- 项目目录:`D:\Project\LobsterAI\闹钟软件`

---

## 软件图片












## 一、项目概览

一个纯原生 Windows 闹钟工具,不依赖 Electron、浏览器内核或第三方 UI 框架。核心目标是把「设闹钟 → 到点叫醒 → 关掉继续睡或起床」这条链路做得稳定、安静、不打扰。

交付形态:

1. 精简版 `dist\AlarmClock.exe`:约 286 KB,框架依赖单文件,需要 .NET 10 Desktop Runtime。
2. 自包含版 `dist\standalone\AlarmClock.exe`:约 66.6 MiB,内含运行时,双击即用。
3. 源码:`versions\vX.Y.Z\src\AlarmClock`,每个版本一份完整副本。

---

## 二、开发架构

### 2.1 技术选型

1. 语言与框架:C# 14 / WPF / .NET 10(`net10.0-windows`)。
2. UI:XAML + 自定义 ControlTemplate,无第三方控件库。
3. 音频:WPF `MediaPlayer`(支持 wav/mp3/wma 等,音量可调、可循环)。
4. 托盘:`System.Windows.Forms.NotifyIcon`(WPF 无原生托盘,与 WinForms 混用)。
5. 存储:`System.Text.Json`,本地 JSON 文件。
6. 系统集成:`Microsoft.Win32.Registry`(开机自启)、`RegisterHotKey`(全局快捷键)、`Mutex`(单实例)。

### 2.2 目录结构(v1.2.0)

```
闹钟软件/
├─ README.md                     快速开始
├─ CHANGELOG.md                  版本更新记录
├─ 项目说明.md                   本文件
├─ dist/
│├─ AlarmClock.exe             精简版(框架依赖)
│└─ standalone/
│   └─ AlarmClock.exe          自包含版
└─ versions/
   ├─ v1.0.0/                  首发版本(完整副本)
   ├─ v1.1.0/                  试听 + 体积优化
   ├─ v1.1.1/                  修复全球化崩溃
   └─ v1.2.0/                  当前版本:铃声库
      ├─ VERSION.md
      ├─ tools/make-icon.ps1
      └─ src/AlarmClock/
         ├─ AlarmClock.csproj
         ├─ app.manifest
         ├─ App.xaml / App.xaml.cs
         ├─ MainWindow.xaml / MainWindow.xaml.cs
         ├─ RingingWindow.xaml / RingingWindow.xaml.cs
         ├─ icon.ico
         ├─ Models/
         │├─ Alarm.cs
         │├─ AppSettings.cs
         │└─ RingRequest.cs
         ├─ Services/
         │├─ AlarmMath.cs
         │├─ AlarmScheduler.cs
         │├─ SoundService.cs
         │├─ StorageService.cs
         │├─ AutoStartService.cs
         │├─ ThemeService.cs
         │└─ TrayService.cs
         └─ Themes/
            ├─ Dark.xaml
            ├─ Light.xaml
            └─ Controls.xaml
```

### 2.3 分层与职责

| 文件                           | 行数 | 职责                                                       |
| ------------------------------ | ---- | ---------------------------------------------------------- |
| `Models/Alarm.cs`            | 195| 闹钟实体,INotifyPropertyChanged,时间/重复/状态等计算属性 |
| `Models/AppSettings.cs`      | 10   | 全局设置(主题、自启、默认稍后、暂停、铃声库)             |
| `Models/RingRequest.cs`      | 14   | 一次响铃请求,连接调度器与响铃窗口                         |
| `Services/AlarmMath.cs`      | 48   | 重复规则匹配、下次响铃时间计算、一次性闹钟日期             |
| `Services/AlarmScheduler.cs`   | 88   | 1 秒轮询,触发判定、稍后提醒、补提醒                     |
| `Services/SoundService.cs`   | 276| 内置铃声合成、播放/循环/渐强、试听、随机库抽取             |
| `Services/StorageService.cs`   | 95   | alarms.json / settings.json 读写、备份、导入导出         |
| `Services/AutoStartService.cs` | 46   | HKCU Run 注册表读写                                        |
| `Services/ThemeService.cs`   | 40   | 主题字典替换、系统深浅色判断                               |
| `Services/TrayService.cs`      | 72   | 托盘图标、右键菜单、气泡提示                               |
| `App.xaml.cs`                  | 82   | 启动装配、单实例、全局异常、退出清理                     |
| `MainWindow.xaml.cs`         | 955| 主界面、编辑抽屉、计时器、设置、与调度器接线               |
| `RingingWindow.xaml.cs`      | 77   | 全屏响铃窗口、快捷键、结果返回                           |
| `Themes/Controls.xaml`         | 410| 全部控件样式(按钮、开关、标签、滑块、滚动条等)         |

设计取向:不使用 MVVM 框架,采用「实体实现 INotifyPropertyChanged + 代码后置 + 服务类」的轻量结构。原因是这个规模下 MVVM 的抽象成本高于收益,而实体通知足以支撑数据绑定。

### 2.4 关键运行流程

**启动流程**

1. `Mutex` 检查单实例,重复启动直接提示并退出。
2. 读取 `settings.json` 与 `alarms.json`(损坏时备份为 `.bak` 并回退空数据)。
3. 应用主题字典;创建 `SoundService`,首次运行合成 3 个内置 WAV。
4. 创建主窗口:绑定闹钟集合与排序视图,初始化调度器、时钟、托盘、全局快捷键。
5. `Loaded` 后启动 1 秒时钟与调度器;若带 `--tray` 参数或设置为静默启动,则直接隐藏到托盘。

**调度循环**

1. 每 1 秒执行一次 `Tick`,全部在 UI 线程完成(数据量小,无需并发)。
2. 若闹钟处于「稍后提醒」,优先检查 `SnoozeUntil`,到点重新入队。
3. 否则检查 `NextRing`:为空则按重复规则计算;已到点则触发。
4. 触发后:一次性闹钟自动禁用;重复闹钟从「当前时间 + 30 秒」重新计算下一次,避免同一分钟重复触发。
5. 实际触发时间比预定时间晚于 90 秒时标记为「补提醒」,用于休眠/关机恢复后的场景。

**响铃流程**

1. 调度器触发 `Due` 事件,主窗口把请求放入队列(支持多个闹钟同时到点,逐个显示)。
2. 创建全屏置顶 `RingingWindow`,显示时间、标签、补提醒标记。
3. `SoundService.PlayLoop` 播放:渐强开启时约 5 秒从 3% 音量升到目标音量,播放结束自动循环。
4. 用户点「停止」或按 Esc 关闭;点「稍后提醒」或按空格则记录 `SnoozeUntil`。
5. 窗口关闭时立即停止声音,队列中还有请求就继续显示下一个。

**试听流程**

1. 编辑面板点「▶ 试听」,按当前选中铃声播放,按钮变为「■ 停止」。
2. 12 秒后自动停止并复位按钮;再次点击可提前停止。
3. 试听与响铃共用同一个 `MediaPlayer`,真正响铃会抢占试听。
4. 试听中拖动音量滑块会实时改变播放音量。

**随机铃声库**

1. 设置页选择文件夹,路径保存到 `settings.json` 的 `RingLibraryFolder`。
2. 闹钟铃声选「随机库」时,`SoundPath` 存为标签 `folder:random`。
3. 响铃前解析:扫描文件夹第一层,按扩展名过滤出音频文件,随机抽一首,并排除上一首避免连播。
4. 库为空或路径不存在时回退内置「晨光」,不会出现静音闹钟。

**主题切换**

1. 深色/浅色是两个同键名的 `ResourceDictionary`,切换时整体替换 `MergedDictionaries`。
2. 所有样式使用 `DynamicResource` 引用颜色,替换后立即生效。
3. 「跟随系统」读取 `HKCU\...\Themes\Personalize\AppsUseLightTheme`,仅在启动时判断。

**系统集成**

1. 开机自启写入 `HKCU\Software\Microsoft\Windows\CurrentVersion\Run`,值为 `"exe路径" --tray`。
2. 全局快捷键 `Ctrl+Alt+A` 通过 `RegisterHotKey` 注册,`WM_HOTKEY` 时呼出主窗口并打开新建抽屉。
3. 关闭主窗口不退出,隐藏到托盘;托盘双击打开,右键可暂停全部或退出。

### 2.5 数据模型

**Alarm 字段**

| 字段            | 类型      | 说明                                        |
| ----------------- | ----------- | ------------------------------------------- |
| `Id`            | string      | GUID,无短横线                              |
| `Hour` / `Minute` | int         | 24 小时制                                 |
| `Label`         | string      | 名称,空值显示为「闹钟」                  |
| `Repeat`          | enum      | Once / Daily / Weekdays / Weekends / Custom |
| `Days`            | DayOfWeek[] | 自定义星期时使用                            |
| `Enabled`         | bool      | 启停                                        |
| `AntiSnooze`      | bool      | 防贪睡,响铃时不显示稍后按钮                |
| `SnoozeMinutes`   | int         | 5 / 10 / 15 / 20                            |
| `SoundPath`       | string      | `builtin:晨光`、`folder:random` 或绝对路径|
| `Volume`          | double      | 0.05 – 1.0                                  |
| `FadeIn`          | bool      | 渐强                                        |
| `OnceDate`      | DateTime?   | 一次性闹钟的日期                            |
| `NextRing`      | DateTime?   | 下次响铃(持久化,用于补提醒)            |
| `SnoozeUntil`   | DateTime?   | 稍后提醒的到点时间                        |

**AppSettings 字段**

| 字段                   | 默认| 说明                   |
| ---------------------- | ----- | ---------------------- |
| `Theme`                | Dark| Dark / Light / System|
| `AutoStart`            | false | 开机自启               |
| `DefaultSnoozeMinutes` | 5   | 新建闹钟的默认稍后时长 |
| `StartMinimized`       | false | 启动即隐藏到托盘       |
| `PausedAll`            | false | 全部暂停               |
| `RingLibraryFolder`    | 空    | 铃声库文件夹绝对路径   |

### 2.6 线程与计时

1. 所有界面、调度、存储操作都在 WPF UI 线程,避免跨线程访问 UI。
2. 计时全部使用 `DispatcherTimer`:调度 1 秒、倒计时 200 毫秒、秒表 50 毫秒、渐强 90 毫秒、试听 12 秒。
3. `MediaPlayer` 在 UI 线程创建;响铃与试听互斥,切换时先 `Stop` 再 `Open`。
4. 无自建后台线程,进程常驻但空闲时 CPU 占用极低(每秒一次轻量遍历)。

### 2.7 界面结构

1. 左侧 84px 导航栏:闹钟 / 计时器 / 设置。
2. 顶部:当前时间(44px)、日期、下一个闹钟卡片。
3. 闹钟页:卡片列表(时间、名称、重复、下次时间、开关),空状态引导。
4. 编辑抽屉:右侧 464px 滑出面板,时间步进、名称、重复、铃声、音量、渐强、防贪睡、稍后提醒。
5. 计时器页:倒计时(预设 3×2 网格 + 自定义分钟)与秒表(计次列表)。
6. 设置页:外观、行为、铃声库、数据、关于。
7. 响铃窗口:无边框全屏、置顶、脉冲光环、超大时间、稍后/停止按钮。

---

## 三、功能清单

**闹钟**

1. 新建、编辑、删除、启停,列表按时间自动排序。
2. 重复规则:仅一次、每天、工作日、周末、自定义星期。
3. 跨天时间:任意 00:00–23:59。
4. 一次性闹钟响后自动关闭。
5. 错过补提醒:休眠、睡眠或关机后恢复,补一次提醒并标记。

**铃声**

1. 内置 3 种合成铃声:晨光、经典、脉冲(首次运行生成 WAV)。
2. 自定义单个音频文件(wav/mp3/wma/m4a 等)。
3. 铃声库文件夹 + 随机抽取,不连续重复。
4. 试听:循环播放、手动停止、12 秒自动停止。
5. 音量 5%–100%,可选渐强(约 5 秒)。
6. 空库自动回退内置铃声。

**提醒行为**

1. 全屏置顶响铃窗口,支持多闹钟排队。
2. 稍后提醒 5/10/15/20 分钟。
3. 防贪睡:响铃后只能手动停止。
4. 全部暂停:到点不响,恢复后按原规则继续。

**计时工具**

1. 倒计时:5/10/15/25/45/60 分钟预设,支持 1–600 分钟自定义,进度条显示。
2. 秒表:开始/暂停/继续、计次、重置,计次列表倒序。

**系统集成**

1. 托盘常驻,关闭窗口不退出。
2. 托盘菜单:打开、暂停全部/恢复全部、退出。
3. 托盘悬停显示下一个闹钟时间。
4. 开机自启(当前用户,静默启动)。
5. 全局快捷键 `Ctrl+Alt+A`。
6. 单实例保护。
7. 深色 / 浅色 / 跟随系统主题。
8. JSON 导入导出、打开数据目录。

---

## 四、快捷键

| 快捷键       | 场景         | 作用                     |
| ------------ | -------------- | ------------------------ |
| `Ctrl+Alt+A` | 全局         | 呼出主窗口并新建闹钟   |
| `↑` / `↓`    | 编辑面板时间框 | 小时/分钟加减 1          |
| 鼠标滚轮   | 编辑面板时间框 | 小时/分钟加减 1          |
| `Tab`      | 编辑面板       | 从小时跳到分钟         |
| `Ctrl+S`   | 编辑面板       | 保存                     |
| `Esc`      | 编辑面板       | 取消并关闭               |
| `空格`       | 响铃窗口       | 稍后提醒(防贪睡时无效) |
| `Esc`      | 响铃窗口       | 停止响铃               |

---

## 五、数据位置

| 内容   | 路径                                                         |
| -------- | ------------------------------------------------------------ |
| 闹钟数据 | `%APPDATA%\AlarmClock\alarms.json`                           |
| 全局设置 | `%APPDATA%\AlarmClock\settings.json`                         |
| 内置铃声 | `%APPDATA%\AlarmClock\sounds\晨光.wav`、`经典.wav`、`脉冲.wav` |
| 异常日志 | `%APPDATA%\AlarmClock\error.log`                           |
| 损坏备份 | `alarms.json.bak`(解析失败时生成)                        |

`alarms.json` 是数组,每个元素对应一个闹钟;枚举以字符串存储,便于阅读和手工修复。`settings.json` 是单个对象。两者都使用缩进格式,可直接编辑,但建议改完再启动程序以免被覆盖。

---

## 六、开发与构建

### 6.1 环境要求

1. 开发:.NET 10 SDK(含 Windows Desktop 工作负载)。
2. 运行精简版:.NET 10 Desktop Runtime。
3. 运行自包含版:无额外依赖。
4. 系统:64 位 Windows 10 / 11。

### 6.2 构建

```powershell
cd versions\v1.2.0\src\AlarmClock
dotnet build -c Release
```

### 6.3 发布精简版

```powershell
dotnet publish -c Release -r win-x64 --self-contained false `
-p:PublishSingleFile=true -o ..\..\..\..\dist
```

注意:框架依赖的单文件发布不能开启 `EnableCompressionInSingleFile`,否则会报 `NETSDK1176`。

### 6.4 发布自包含版

```powershell
dotnet publish -c Release -r win-x64 --self-contained true `
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true `
-p:EnableCompressionInSingleFile=true -o ..\..\..\..\dist\standalone
```

### 6.5 图标

```powershell
powershell -ExecutionPolicy Bypass -File versions\v1.2.0\tools\make-icon.ps1
```

脚本用 `System.Drawing` 画一个圆角珊瑚色方块 + 白色表针,输出多尺寸 PNG 压缩的 `icon.ico`(256/64/48/32/16)。`csproj` 通过 `<ApplicationIcon>` 引用,构建时嵌入 exe。

### 6.6 版本化约定

1. 每次改动都从最新版本目录复制出新的 `versions/vX.Y.Z`,不在旧版本上覆盖。
2. 新版本附 `VERSION.md`,说明改动、验证方式与已知限制。
3. 根目录 `CHANGELOG.md` 追加条目,最新版本在最上面。
4. 发布产物统一输出到 `dist`(精简版)与 `dist\standalone`(自包含版)。
5. 版本号语义:新增功能升次版本号,修复升修订号。

---

## 七、关于体积

| 形态         | 精确大小      | 显示大小         | 依赖                  |
| -------------- | --------------- | ------------------ | ----------------------- |
| 框架依赖单文件 | 286,387 字节    | 286 KB / 0.27 MiB| .NET 10 Desktop Runtime |
| 自包含单文件   | 69,821,117 字节 | 69.8 MB / 66.6 MiB | 无                      |

体积构成与结论:

1. 精简版只打包自身程序集(约 0.3 MB),WPF 与运行时由系统共享。
2. 自包含版把 .NET 运行时、WPF 框架程序集和本地库一起塞进 exe,压缩后仍有 66.6 MiB,这是 WPF 应用的下限量级。
3. WPF 不支持 `PublishTrimmed`(IL 裁剪)与 NativeAOT,无法像控制台程序那样压到几 MB。
4. 曾尝试 `InvariantGlobalization` 去掉 ICU 数据,体积几乎没变(此前「省 3 MB」是 MB/MiB 单位误读),却导致 WPF 在中文输入法下崩溃,v1.1.1 已移除。结论:不要为了体积牺牲全球化支持。
5. 因此采用「双版本」策略:日常用精简版,给没有运行时的机器用自包含版。

---

## 八、注意事项

1. 精简版在未安装 .NET 10 Desktop Runtime 的机器上会弹出运行时下载提示,这是 apphost 的默认行为。
2. 自定义铃声与铃声库的解码依赖 Windows 自带解码器;flac/ogg 在部分精简系统上可能无声,但不会崩溃。
3. 铃声库只扫描所选文件夹的第一层,不递归子目录。
4. 响铃窗口只在主显示器全屏显示,多显示器场景下副屏不受影响。
5. 「跟随系统」主题只在启动时判断,运行中不监听系统主题变化。
6. 程序为单实例;重复启动会提示查看托盘,不会开第二个进程。
7. 响铃需要系统音量未静音;程序不修改系统音量。
8. 系统休眠/睡眠会暂停调度器计时,恢复后通过 `NextRing` 比对触发补提醒,最多补一次,不会连续轰炸。
9. 删除闹钟、导入覆盖等操作都会弹确认框;导入会覆盖当前全部闹钟。
10. 数据在 `%APPDATA%` 下,重装或换机前建议先「导出备份」。
11. 修改 `settings.json` 时请先退出程序,否则退出时可能被内存中的设置覆盖。
12. 首次启动自包含版会有短暂解压过程(单文件自解压),属正常现象。

---

## 九、版本历史

### v1.2.0(2026-11-03)铃声库

新增:

1. 全局铃声库文件夹设置,支持选择、打开、清空,显示曲目数。
2. 闹钟铃声新增「随机库」,每次响铃随机抽一首。
3. 随机不连播:排除上一首后再抽。
4. 库空或路径失效回退内置「晨光」。
5. 试听支持随机库;编辑面板实时显示库状态。

说明:随机库是全局设置,暂不支持每个闹钟独立文件夹;只扫描第一层目录。

### v1.1.1(2026-11-03)修复崩溃

修复:

1. 打开编辑面板、焦点进入时间输入框时报 `CultureNotFoundException`。
2. 根因:v1.1.0 开启 `InvariantGlobalization`,WPF 读取系统输入语言(中文 LCID 2052)时无法解析。
3. 处理:移除该开关,恢复完整全球化支持;体积无实质变化。

说明:这是一次典型的「优化引入回归」,也纠正了此前对体积收益的误判。

### v1.1.0(2026-11-03)试听与瘦身

新增:

1. 铃声试听按钮:循环播放、手动停止、12 秒自动结束。
2. 试听音量跟随滑块实时变化;切换铃声、关闭面板、响铃时自动停止。

优化:

1. 默认发布改为框架依赖单文件,从 69.8 MB 降到 286 KB。
2. 新增自包含单文件版本,供无运行时环境使用。

### v1.0.0(2026-11-03)首个版本

1. 闹钟增删改查与启停,按时间排序。
2. 重复规则:仅一次、每天、工作日、周末、自定义星期。
3. 全屏响铃,内置 3 种合成铃声,支持自定义音频文件。
4. 稍后提醒与防贪睡。
5. 音量调节、渐强音量。
6. 托盘常驻与托盘菜单。
7. 错过补提醒。
8. 倒计时与秒表(番茄钟预设、计次)。
9. 深色/浅色/跟随系统主题。
10. 开机自启。
11. JSON 导入导出、打开数据目录。
12. 全局快捷键、单实例保护。
13. 单文件自包含发布与自绘图标。

### 演进小结

| 版本   | 主题       | 关键风险            |
| ------ | ---------- | --------------------- |
| v1.0.0 | 从零到可用 | 调度边界、休眠恢复    |
| v1.1.0 | 体验与体积 | 单文件发布方式差异    |
| v1.1.1 | 稳定性修复 | 全球化开关与 WPF 冲突 |
| v1.2.0 | 铃声个性化 | 库路径失效、解码兼容|

---

## 十、后续可做

1. 节假日/调休日历,支持「法定工作日」重复规则。
2. 多显示器全屏响铃,覆盖所有屏幕。
3. 每个闹钟独立的铃声库文件夹。
4. 渐强时长可调(当前固定约 5 秒)。
5. 托盘菜单快速暂停单条闹钟。
6. 闹钟分组与搜索。
7. 响铃时系统音量联动(渐强到系统音量上限)。


## 下载地址

https://llii.lanzout.com/b00v0gc3cb
密码:8nbt      

cybultimate 发表于 2026-11-3 16:57

这玩意估计用的人真不多,比起手机,像我这种经常坐电脑前的人我都不想用win的提醒功能。。。

MengWo09 发表于 2026-11-3 17:20

求一个求一个

饮食协会 发表于 2026-11-3 17:34

分享链接 里面怎么是空的? 没有软件哦

Autorun 发表于 2026-11-3 17:38

链接是空的。。。

feifu363 发表于 2026-11-3 19:01

梦畅、心意闹钟还在用,体积小功能强,运行效率高资源占用低。

jws2016 发表于 2026-11-3 19:13

没有文件

lxc66 发表于 2026-11-3 19:16

啊?请问是出于什么原因要做一个win版的闹钟呢?真心求问。。

13915720231 发表于 2026-11-3 19:31

连接空的,忘记传了?

shenlong2006 发表于 2026-11-3 20:37

啥也没有
页: [1] 2
查看完整版本: 纯原生 Windows 闹钟工具V1.2