Windows 任务栏托盘日历应用:显示今天的日期和当天日程(含截止时间),可前后翻日、查看未来日程。 日程由本地 AI agent 直接读写数据文件来管理,无手动录入界面,保存后 ~1.5 秒自动刷新。
Win11 特性:真亚克力材质(壁纸模糊可见,透明度可调,自动跟随系统深浅色主题)、圆角窗口、平滑惯性滚动。 零依赖:仅需 Windows 自带的 PowerShell(推荐 PowerShell 7,Windows PowerShell 5.1 也可运行)。
第一次用? 解压到任意目录(路径别含特殊字符),双击
启动日历.vbs即可。 托盘上会出现一枚日历图标,左键点它就开关小窗。schedule.json里预置了 3 条示例日程,可以直接删。
| 操作 | 方式 |
|---|---|
| 启动 | 双击 启动日历.vbs(后台静默运行,重复双击不会重复启动) |
| 打开/关闭小窗 | 左键点击托盘图标切换;或右键 →「打开日历」/「关闭日历」(正开着的那条会自动置灰,一眼看出状态) |
| 自动收起 | 小窗失焦、或按 Esc |
| 翻日 / 回今天 | 小窗右上角 ‹ › 按钮 / 今天 按钮 |
| 查看未来日程 | 小窗右下角切换到 「即将到来」 视图(从明天开始,按日期分组) |
| 开机自启 | 托盘图标 右键 → 开机自启(菜单项带 ✓ 和「已开启/未开启」状态后缀,点击即时切换) |
| 退出 | 托盘右键 → 退出 |
其他细节:
- 材质:默认桌面亚克力(玻璃扩展 +
SetWindowCompositionAttribute带 tint,可实时透出身后的窗口与壁纸,Chrome / Terminal 同款)。深浅色主题经WM_SETTINGCHANGE广播 +SystemEvents偏好事件即时跟随,不做轮询。若需其他观感,config.json可切"system"/"mica"/false - 滚动:列表带惯性与边缘阻尼,滚轮即指即滚
- 视图切换按钮:右下角「即将到来」,复刻 Win11 开始菜单「全部」按钮的容器观感(圆角/描边/内边距按系统按钮像素实测取值,随深浅色换肤,文字居中)
- 托盘图标:线条风(白描边圆角方框 + 头部横线 + 当天日期),与任务栏上 WLAN / 音量 / 电池那批系统图标同一路数;轮廓比例取自
Segoe Fluent Icons的日历字形 U+E787 - 日程开始前 10 分钟托盘气泡提醒(点气泡可直接打开小窗)
- 日程卡片左侧色条 = 日程
color;已过期的日程整卡变灰 - 状态行实时显示:
进行中 · X 分钟后截止/X 小时后开始 · 截止 HH:mm/ 全天日程显示今天/还有 X 天 - 小窗失焦自动收起,Esc 关弹窗;滚轮即指即滚(无需先点击列表)
- 调试排错:双击
debug-run.bat(带控制台运行,错误直接可见);日志在app.log。要截图渲染界面、自动弹出、跑材质自检,用DevTools.ps1(文件头有用法)
运行只需前两行,其余是可选工具与开发文档。
| 文件 | 作用 |
|---|---|
CalendarTray.ps1 |
主应用(托盘 + 弹窗 + 轮询刷新)。正式版不带任何参数启动 |
schedule.json |
日程数据文件(AI 读写的唯一入口) |
启动日历.vbs |
静默启动器 —— 双击即用,推荐;开机自启指向的也是它 |
manage.ps1 |
命令行日程管理工具(AI 也可用) |
config.json |
应用配置:acrylic 材质模式——"accent"(默认,桌面亚克力,带 tint 可调透光度)/ "system"(DWMSBT_TRANSIENTWINDOW,无 tint,部分机器上呈恒定浅灰底)/ "mica"(壁纸采样)/ false(实底) |
DevTools.ps1 |
开发者工具(截图渲染 / 自动弹出 / 材质自检 / 几何自检),见文件头注释 |
debug-run.bat |
带控制台的启动器(看报错用) |
亚克力实现笔记.md |
材质实现记录,想改材质前先读 |
app.log(运行日志,自动滚动保留 120 行)与app.pid(当前实例进程号) 在首次运行后自动生成,退出时app.pid会被删除。这两个文件不必手动维护。
AI agent 有两种等价方式管理日程,均无需重启应用,保存后 ~1.5 秒内界面自动刷新。
文件结构:
{
"events": [
{
"id": "evt-001",
"title": "团队每日站会",
"start": "2026-09-09T09:30:00",
"end": "2026-09-09T09:45:00",
"location": "会议室 A",
"notes": "同步进展与今日计划",
"color": "#2D7DFA"
}
]
}字段说明:
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
id |
建议 | string | 唯一标识,如 evt-001。删除/修改时用它定位 |
title |
✅ | string | 日程标题(卡片主文字) |
start |
✅ | string | 开始时间,YYYY-MM-DDTHH:mm:ss;纯日期 YYYY-MM-DD 表示全天 |
end |
否 | string | 结束/截止时间。缺省 = start(用作「截止时刻」) |
allDay |
否 | bool | 全天日程(纯日期 start 会自动视为全天) |
location |
否 | string | 地点(卡片第一行显示) |
notes |
否 | string | 备注(悬停卡片时的 tooltip 里显示) |
color |
否 | string | 色条颜色 #RRGGBB,缺省蓝色 #2D7DFA |
规则:
- 增:向
events数组追加一个对象(记得给不重复的id) - 删:移除对应对象;改:直接改字段值
- 日期必须用 ISO 格式(
2026-09-09T14:00:00),不要用09/09/2026这类本地格式 - JSON 写坏不会闪退:应用会在底部状态栏红字提示错误行,修好即自动恢复
- 保存时用 UTF-8 编码(中文标题)
# 列出未来 14 天日程(-Days N 可调)
pwsh -File manage.ps1 list -Days 14
# 添加(End 可省略;-AllDay 全天;时间写 "2026-09-09 14:00" 即可)
pwsh -File manage.ps1 add -Title "产品评审" -Start "2026-09-10 14:00" -End "15:30" -Location "会议室 B" -Color "#7C5CFC"
# 删除(-Id 支持完整 id 或标题片段模糊匹配)
pwsh -File manage.ps1 remove -Id evt-002
# 移动(默认保持时长,end 自动跟着平移)
pwsh -File manage.ps1 move -Id "评审" -Start "2026-09-11 10:00"
# 修改字段
pwsh -File manage.ps1 edit -Id evt-002 -Title "新标题" -Location "线上" -Notes "带文档"- 改动前先读
schedule.json确认现状(避免 id 冲突 / 时间重叠) - 优先直接编辑 JSON(可一次批量增删改),单条微调用 manage.ps1
- 改完无需通知用户「刷新」——应用自己会刷新,直接说「已添加」即可
- 给用户的日程建议使用语义化颜色:红色=截止/紧急、绿色=健康/个人、紫色=会议、橙色=外出、蓝色=默认工作
托盘看不到图标? 打开 Windows 设置 → 个性化 → 任务栏 → 其他系统托盘图标,或在「溢出区」找;确认 app.log 里有 [启动] 记录。
修改 schedule.json 后没刷新? 确认保存的是 CalendarTray\schedule.json(应用每 1.5 秒轮询该文件的时间戳和大小)。
如何确认应用在跑? app.pid 里有进程号;或看 app.log 最后是否有 [启动] 且无新 [退出]。
开机自启在哪里? shell:startup 下的「任务栏日历.lnk」,托盘右键可随时开关。
这几条是实测结论,改错任何一条都会让亚克力"时好时坏"乃至完全不出现:
GlassSheet(负边距扩展框架)必须早于Show()。窗口显示之后再设,DWM 不再采纳,材质整个不出现。因此它只在HandleCreated里调,不可放进换肤路径。- tint 必须晚于
Show()+Activate()。提前施加会被随后的合成覆盖,表现为不透明。见Show-Popup里的Set-MaterialTint。 - tint 常量必须走字符串解析:
[uint32]'0xB8F5F5F5',不能写[uint32]0xB8F5F5F5。后者超出 Int32 范围,PowerShell 会解析成负 Int32 并抛异常;该异常曾被catch吞掉,导致 tint 静默失效、窗口退回不透明——这是"时好时坏"最主要的真凶。 - 弹窗是否在屏幕上用
$script:IsOpen判断,不要用坐标与$OffscreenX比较。坐标一旦被改成其它屏幕外值,所有判断会集体失灵。 - 主题跟随走事件,不要加轮询兜底:
WM_SETTINGCHANGE广播(WheelRouter.OnSettingChange)+SystemEvents.UserPreferenceChanged双通道,二者都调用幂等的Sync-SystemTheme。 accent与system两条路径不要同时启用:Apply-Material会先关掉另一条,避免互相覆盖。- 要判断材质是否真的生效,用窗内像素标准差,不要用亮度阈值:标准差 > 2 表示透出了身后内容,≈ 0 表示均匀实底。浅色壁纸下亮度判据会误报(实测把正确的 237 判成"失败")。
- 弹窗与视图切换目前没有动画:开合是瞬时的(
Show-Popup/Hide-Popup直接摆位)。 历史上做过一版「从任务栏上沿长出来」的逐帧动画,因反复调不出满意效果已整段移除 ——Set-PopupProgress/Step-Anim/Start-PopupAnim/Get-Bezier/ListAlpha这些名字 只存在于旧文档里,代码中已无。要重做请从零写,别照着 README 的历史描述找。 - 保留的动效只有列表滚动:惯性 + 边缘阻尼,靠
$sl.AnimTimer(15ms 一拍,见Scroll-ListBy)。 - 绘制层取色一律经
C $colorHex,且C()必须返回字符串。返回Color对象会让FromHtml解析失败、绘制中断,.NET 画出红叉占位符。 ClearPanel/New-TextLabel的绘制不清屏,所以不能靠逐控件改 alpha 做交叉淡化(会残留上一帧的鬼影)。Refresh-Ui有签名缓存:数据/日期/视图没变就跳过重建。凡是影响布局的输入 (如列表的宽高)都必须进签名,否则窗口尺寸变化后会跳过重建、内容区一片空白。