☰
WinDynamicDesktop 动态壁纸完整指南:macOS Mojave 动态桌面在 Windows 上的移植实现、主题格式与日出日落调度机制
2026/10/15 3:43:08 网站建设 项目流程
  • 桌面应用

【免费下载链接】WinDynamicDesktop

Port of macOS Mojave Dynamic Desktop feature to Windows

项目地址:https://gitcode.com/gh_mirrors/wi/WinDynamicDesktop
点击查看免费下载

导读

WinDynamicDesktop 是一款将 macOS Mojave 独有的 Dynamic Desktop(动态桌面)特性移植到 Windows 10/11 的开源桌面工具,它以用户所在位置推算日出与日落时间,并据此在一天 24 小时内循环切换多张壁纸图片,让桌面壁纸像 macOS 一样随天色自然变化。本文以项目官方 README 为骨架,结合仓库源码(主题加载、调度器、脚本引擎、配置体系等)逐层展开,读完你将掌握动态壁纸的完整工作原理、theme.json主题格式与校验规则、日出日落调度的三种位置模式与内部时间分段算法,以及如何用 PowerShell 脚本扩展程序行为、如何编辑settings.json配置文件。

项目定位:从 macOS Mojave 移植到 Windows 的 Dynamic Desktop

在 macOS Mojave 中,Apple 首次引入了"动态桌面"特性:系统根据一天中时间的变化自动更换桌面壁纸,呈现从清晨、白天、黄昏到夜晚的连续视觉效果。WinDynamicDesktop 正是该特性的 Windows 移植版,其 README 明确写道:

Port of macOS Mojave Dynamic Desktop feature to Windows 10 and 11. Available on GitHub and the Microsoft Store.

程序核心逻辑由 C# 编写,目标框架为net10.0-windows10.0.19041.0,同时产出win-x86、win-x64、win-arm64三种运行时架构(见 WinDynamicDesktop.csproj)。项目同时提供桌面版(WinExe)与 UWP 打包版(uwp/ 目录中的Package.appxmanifest与WinDynamicDesktop.Package.wapproj),通过 UwpDesktop.cs 中的GetHelper()在两种运行形态之间自动选择底层实现:桌面版调用DesktopHelper,UWP 版调用UwpHelper。

获取与安装方式

根据 README 与仓库配套脚本,项目提供以下分发渠道:

渠道说明
GitHub Releases直接下载安装包,由 scripts/package.ps1 与 Inno Setup 脚本 scripts/installer.iss 构建
Microsoft StoreUWP 版本,应用 ID9NM8N7DQ3Z5F,可访问 Windows 位置 API
Chocolatey包名windynamicdesktop,打包元数据见 scripts/windynamicdesktop.nuspec
WinGet包名t1m0thyj.WinDynamicDesktop

若需从源码获取,可执行git clone https://gitcode.com/gh_mirrors/wi/WinDynamicDesktop后参照 WinDynamicDesktop.sln 使用 Visual Studio 打开解决方案构建。README 特别提示:项目主要面向 Windows 11 开发,但理论上支持 Windows 7 及以上版本;Windows Insider 预览版不作为官方支持对象。

从源码结构看,安装器在安装完成后会通过{app}\WinDynamicDesktop.pth文件记录用户数据目录(scripts/installer.iss),程序启动时(Program.cs 的FindCwd())会读取该文件并把当前工作目录切换到用户数据目录,从而保证themes、scripts、settings.json等数据与程序本体隔离,便于升级与卸载。

核心工作原理:壁纸如何"动态"起来

动态壁纸的本质是一个时间驱动的壁纸切换调度器。一次完整的工作循环由以下模块协作完成,调用链可以概括为:

位置 → 日出/日落与太阳时角计算 → 划分时间分段 → 计算当前图片与下次更新时间 → 切换壁纸

调度中枢 EventScheduler

EventScheduler.cs 是整套机制的调度中枢。其Run()方法(EventScheduler.cs)在每次触发时执行:

  1. 检查位置与主题是否就绪(LaunchSequence.IsLocationReady()/IsThemeReady());
  2. 调用SunriseSunsetService.GetSolarData()获取当天太阳数据;
  3. 逐个显示器计算当前应显示的壁纸与下次切换时刻;
  4. 调用ScriptManager.RunScripts()把本次事件参数传给 PowerShell 脚本;
  5. 用System.Timers.Timer精准调度下一次切换。

调度器通过订阅多个 Windows 系统事件保证切换的及时性(EventScheduler.cs):

  • DisplaySettingsChanged:显示器数量/分辨率变化时重建显示列表;
  • PowerModeChanged:从睡眠/休眠恢复后立即刷新壁纸;
  • SessionSwitch:用户解锁会话时刷新;
  • TimeChanged:系统时间被手动修改时重新计算。

此外还有一个每 60 秒触发一次的后台定时器作为兜底(EventScheduler.cs),当"主定时器错过触发点"时由它补上,这也是 5.7.0 版本修复"PC 从睡眠恢复时壁纸不刷新"问题的关键机制(见 CHANGELOG.md)。

时间分段模型:四个时段

在正常地区(非极昼/极夜),一天被划分为四个时间分段(枚举DaySegment,见 SolarScheduler.cs):

分段起止时间点使用的图片列表
Sunrise(日出)Dawn → GoldenHourEndsunriseImageList
Day(白天)GoldenHourEnd → GoldenHourdayImageList
Sunset(日落)GoldenHour → DusksunsetImageList
Night(夜晚)Dusk → 次日 DawnnightImageList

这些时间点由SunriseSunsetService基于天文计算得出(SunriseSunset.cs):日出/日落采用地平线下 -0.833 度的标准定义,民用曙暮光(civil twilight)为 -6 度,黄金时刻(golden hour)为地平线上 +6 度。GetAllImageTimes()会把每个分段的图片按时间均匀铺开(SolarScheduler.cs),例如 5 张白天图片就均匀分布在 GoldenHourEnd 到 GoldenHour 之间。

极昼极夜与民用极昼的边界处理

在高纬度地区会出现太阳不落(极昼)或不开(极夜)的情况。SunriseSunsetService通过枚举PolarPeriod(SunriseSunset.cs)区分五种状态:None、PolarDay、PolarNight、CivilPolarDay、CivilPolarNight,并用SunCalcNet.SunCalc.GetSunPosition计算正午太阳高度角来判断(SunriseSunset.cs)。极昼时程序改为只在白天分段内按正午(solarNoon)对称铺图,让正午显示最亮的图片;极夜时则只走夜晚分段。这套边界行为有专门测试覆盖,例如 test/SunCalcTests.cs 验证了北极斯瓦尔巴群岛的CivilPolarDay场景(日出 01:55、日没次日 00:35、正午 12:56)。

外观模式:Automatic / Light / Dark

托盘菜单提供三种外观模式(枚举AppearanceMode,SolarScheduler.cs),对应设置项appearanceMode:

  • Automatic(自动):白天用dayImageList,夜晚用nightImageList;
  • Light(浅色):始终显示白天图片;
  • Dark(深色):始终显示夜晚图片。

该值由托盘菜单写入并通过SolarScheduler.SetAppearanceMode()(SolarScheduler.cs)立即触发调度器重跑,无需重启。

主题系统:从内置 macOS 主题到自定义主题

README 的 Themes 一节介绍了三种主题来源:内置 macOS 主题、在线主题库(windd.info/themes 收录数百个主题)、自制主题。主题选择界面截图如下:

主题清单的加载

ThemeManager.Initialize()(ThemeManager.cs)启动时扫描themes目录下所有theme.json,结合内置主题清单(DefaultThemes.GetDefaultThemes(),数据来自嵌入资源 Properties/Resources.resx 中的 YAML)与 Windows 11 系统自带壁纸(DefaultThemes.cs 的Windows_11主题,直接复用%SystemRoot%\Web\Wallpaper\Windows\img*.jpg),构建出可选择的主题列表。首次运行且未选主题时,程序会默认聚焦到内置的Mojave_Desert主题(ThemeDialog.cs)。

theme.json:主题的核心数据结构

自制主题的本质,是提供一个符合规范的主题目录,内含一张theme.json描述文件与若干壁纸图片。仓库中 ThemeLoader.cs 的ThemeConfig类完整定义了 JSON 字段结构:

字段类型说明
themeIdstring主题唯一标识,同时也是themes下的目录名
displayNamestring主题显示名;缺省时用themeId替换下划线展示(ThemeManager.cs)
imageFilenamestring图片文件名模板,用*通配图片编号,如img*.jpg
imageCreditsstring图片版权署名(非内置主题在界面中展示)
dayHighlight/nightHighlightint?白天/夜晚的高光图片编号(用于预览与高亮)
sunriseImageListint[]日出分段图片编号列表
dayImageListint[]白天分段图片编号列表(必填)
sunsetImageListint[]日落分段图片编号列表
nightImageListint[]夜晚分段图片编号列表(必填)

校验规则见 ThemeJsonValidator.cs:ValidateQuick要求imageFilename、dayImageList、nightImageList三者非空;ValidateFull进一步检查目录中确实存在与模板匹配的图片,且四个分段引用的每一个图片编号都能解析出实际文件(把imageFilename中的*替换成编号后File.Exists)。官方还提供.ddw Theme Creator在线可视化编辑器辅助生成主题包。

主题的导入、下载与删除

Select Theme窗口支持三种导入途径:

  1. 文件导入:通过"Import"按钮或直接把.ddw、.zip、.json文件拖入窗口(ThemeDialog.cs 与拖放事件 ThemeDialog.cs);
  2. ZIP 解压:ThemeLoader.ExtractTheme()(ThemeLoader.cs)从压缩包中提取唯一的 JSON 为theme.json,再解出其余图片,任一环节失败都会触发RollbackInstall回滚删除整个主题目录;
  3. 本地目录复制:ThemeLoader.CopyLocalTheme()(ThemeLoader.cs)将本地theme.json及其匹配图片复制进themes/<themeId>。

对于未下载的在线主题,DownloadDialog会按 YAML 中记录的多个备用镜像 URL 依次下载 ZIP(DownloadDialog.cs),下载后同样走ExtractTheme流程,并在任务栏进度条上同步显示进度。删除主题时,若主题正被某个显示器使用则会被拒绝(ThemeDialogUtils.cs);"永久删除"会在RemoveTheme时直接清掉主题目录(ThemeManager.cs)。

主题随机切换(Shuffle)

README 虽未单独成节,但源码展示了完整的主题洗牌能力:托盘菜单可开启"收藏主题随机"或"全部主题随机",随机周期支持每小时、每 12 小时、每天、每 2 天、每周、每月六档(枚举ShufflePeriod,ThemeShuffler.cs)。ThemeShuffler.MaybeShuffleWallpaper()(ThemeShuffler.cs)在调度器每次运行时先判断"是否到洗牌时刻",再通过GetNextTheme从shuffleHistory历史记录中排除最近用过的主题以避免重复。该能力在 Windows 10/11 多显示器场景下分别作用于每块屏幕的主题。

调度系统:位置、日出日落与自定义时间

README 的 Schedule 一节说明"为 24 小时内的壁纸循环选择一套调度方案"。配置入口是Configure Schedule窗口(截图如下),其核心是位置模式选择:

三种位置模式

ScheduleDialog(ScheduleDialog.cs)会把选择结果写入settings.json的locationMode字段:

locationMode模式实现
0手动输入城市名调用 LocationIQ 搜索 API 将地名转换为经纬度(LocationManager.cs),转换成功后弹出确认框并显示推算出的日出日落时间
1Windows 位置服务仅 UWP 版本可用,调用UwpLocation.UpdateGeoposition()获取系统定位;无权限时自动回退(LocationManager.cs)
-1手动指定日出/日落时间用户直接填写sunriseTime、sunsetTime与sunriseSunsetDuration(日出/日落过渡分钟数)

SunriseSunsetService.GetSolarData()(SunriseSunset.cs)会根据locationMode分流:手动模式直接构造太阳数据,其余模式用经纬度 +GeoTimeZone+TimeZoneConverter换算时区后,交给SunCalcNet做天文计算。

手动时间模式下的分段推导

当用户选择手动指定日出日落时,GetUserProvidedSolarData()(SunriseSunset.cs)会基于sunriseSunsetDuration推导出四个分段节点:设half = sunriseSunsetDuration * 30秒,则 Dawn = 日出 − half、GoldenHourEnd = 日出 + half、GoldenHour = 日落 − half、Dusk = 日落 + half。例如过渡时长设为 30 分钟、日出 6:00、日落 18:00,则日出分段为 5:30–6:30,日落分段为 17:30–18:30。

调度结果在源码中的体现

SolarScheduler.CalcNextUpdateTime()(SolarScheduler.cs)负责把"当前时刻"映射为"当前图片编号 + 下次更新时间":它先由GetDaySegmentData判断当前处于哪个分段,再把该分段的时长均分给对应图片列表,最后返回图片编号与下一次切换时刻。EventScheduler.HandleDisplayEvent(EventScheduler.cs)拿到编号后把imageFilename模板中的*替换为编号,拼出完整路径调用UwpDesktop.GetHelper().SetWallpaper()或SetLockScreen()。

脚本扩展:用 PowerShell 改变程序行为

README 的 Scripts 一节指出"用 PowerShell 脚本扩展 WinDynamicDesktop 行为"。这是项目的另一大特色:原本内置的"更改系统/应用主题色、自动亮度"等功能被移出核心后,全部以脚本形式提供(见 ConfigMigrator.cs 中 4.0 版本的迁移说明),用户也可以在社区脚本仓库分享自定义脚本。

脚本的发现与执行

ScriptManager.Initialize()(ScriptManager.cs)启动时创建scripts目录;执行阶段,RunScripts()(ScriptManager.cs)枚举该目录下所有*.ps1文件,逐个以隐藏窗口方式调用pwsh.exe(若存在)或powershell.exe(ScriptManager.cs),命令行为:

pwsh.exe -NoProfile -ExecutionPolicy Bypass -File "<脚本名>"

脚本入参格式

每次调度器运行时,程序会把本次事件参数序列化为 JSON 写入脚本的标准输入(stdin)。ScriptArgs(ScriptManager.cs)定义了 JSON 字段:

{ "daySegment2": 0, "daySegment4": 3, "themeMode": 0, "imagePaths": ["C:/path/to/themes/Mojave_Desert/img1.jpg"] }
字段类型含义
daySegment2int0 = 白天,1 = 夜晚(二分法分段)
daySegment4int四分段编号:0 日出 / 1 白天 / 2 日落 / 3 夜晚
themeModeint外观模式:0 自动 / 1 浅色 / 2 深色
imagePathsstring[]本次各显示器实际设置的壁纸路径

脚本通过读取 stdin 拿到该 JSON 后即可实现自定义逻辑(如同步 Windows 深色模式、调整显示器亮度等)。需要说明的是:脚本仅在参数变化或强制刷新时触发(lastArgs去重,ScriptManager.cs);若脚本退出码非 0 或输出了错误信息,程序会弹出"Script Error"警告(ScriptManager.cs)。脚本开关位于托盘菜单"More Options → Enable PowerShell scripts"。

配置与数据文件:settings.json 与目录布局

所有用户设置持久化在settings.json中。JsonConfig(JsonConfig.cs)负责加载与保存:属性变更后触发 1 秒防抖自动保存,写入时先落盘为settings.json.tmp再原子替换,避免配置损坏;若 JSON 已损坏,程序会询问是否重置为默认设置(JsonConfig.cs)。配置文件损坏恢复、旧版本字段迁移(如settings.conf→settings.json、themeName→activeThemes)由 ConfigMigrator.cs 完成。

AppConfig(JsonConfig.cs)中的核心字段一览:

分类字段说明
调度locationMode位置模式(0 手动位置 / 1 Windows 位置 / -1 手动时间)
调度location用户输入的城市名
调度latitude/longitude经纬度
调度sunriseTime/sunsetTime手动模式的日出/日落时刻(格式T)
调度sunriseSunsetDuration日出日落过渡时长(分钟)
主题activeThemes各显示器使用的主题 ID 数组;首元素为null时按显示器分别指派
主题appearanceMode0 自动 / 1 浅色 / 2 深色
主题themeShuffleMode十位为随机范围(0 关 / 1 收藏 / 2 全部),个位为随机周期
主题favoriteThemes收藏主题 ID 列表
主题lockScreenTheme/lockScreenDisplayIndex锁屏主题与"锁屏跟随显示器"的索引(-1表示不跟随)
通用language界面语言代码
通用autoUpdateCheck每周自动检查更新(桌面版)
通用hideTrayIcon隐藏托盘图标
通用fullScreenPause全屏应用运行时暂停切换
通用enableScripts启用 PowerShell 脚本
通用debugLogging详细日志开关

托盘菜单"More Options → Edit configuration file / Reload configuration file"可直接编辑并热重载该文件(TrayMenu.cs)。

运行期数据目录布局为:themes/<themeId>/theme.json + 图片、scripts/*.ps1、settings.json、WinDynamicDesktop.log。多语言方面,仓库内置 50 余种语言的.mo翻译文件(见 src/locale/),支持从 POEditor 平台获取在线翻译(poeditor:前缀语言代码,见 Localization.cs)。

已知问题与使用限制

README 的 Known Issues 与 Limitations 章节如实披露了当前版本的边界,撰写时一并列出以免误导:

  • 壁纸适配在多显示器下可能不被记忆(Microsoft Store 版本):与系统壁纸拉伸/平铺等适配设置相关;
  • 壁纸偶尔卡住不更新:多见于长时间睡眠/休眠后,5.7.0 已通过双定时器兜底缓解(CHANGELOG.md);
  • 无法在多个虚拟桌面(Virtual Desktops)上分别显示不同图片:Windows 虚拟桌面属于系统级特性,壁纸 API 无法按虚拟桌面区分;
  • 锁屏更换受 Windows Spotlight 影响:当系统开启 Windows Spotlight 时无法设置锁屏图,需在"设置 → 个性化 → 锁屏"中切换为图片模式(ThemeDialogUtils.cs);
  • Windows Insider 构建未经官方测试。

附:资源与声明要点

README 同时列出以下周边资源与声明,供读者按需查阅:

  • 官方 Wiki(Get Help)收录了常见问题与自定义主题创建指南;
  • 翻译协作基于 POEditor 平台进行;
  • .ddw Theme Creator是社区提供的在线主题创作工具;
  • 免责声明要点:内置壁纸图片版权归属 Apple 公司;输入位置时使用 LocationIQ API 换算经纬度(UWP 版授权后使用 Windows 位置 API,位置数据匿名且不会未经同意保存——该承诺同时写入 Chocolatey 包描述 scripts/windynamicdesktop.nuspec);应用图标来自 Roundicons(CC 3.0 BY 许可)。

结语

从 README 出发可以看到,WinDynamicDesktop 的技术魅力不止于"换壁纸"这一表象:SolarScheduler的太阳时角计算、ThemeJsonValidator的主题包校验、ScriptManager的 stdin JSON 协议、JsonConfig的原子化配置持久化,共同构成了一套可扩展、可验证的动态壁纸工程实践。无论你想直接使用它获得 macOS 般的桌面体验,还是想借theme.json格式与 PowerShell 脚本协议构建自己的壁纸/桌面自动化生态,本文梳理的源码路径都可以作为你的第一份地图。

说明:文中所有功能描述均以当前仓库(版本 5.7.0,见 WinDynamicDesktop.csproj 与 CHANGELOG.md)为准;涉及界面截图的两张图片分别对应 Select Theme 与 Configure Timing 窗口,取自 images/ 目录。

  • 桌面应用

【免费下载链接】WinDynamicDesktop

Port of macOS Mojave Dynamic Desktop feature to Windows

项目地址:https://gitcode.com/gh_mirrors/wi/WinDynamicDesktop
点击查看免费下载
上一篇:Linux 内核 CPUFreq 子系统全解析:核心接口、驱动开发指南与 sysfs 统计
下一篇:ESP-IDF 错误码(esp_err_t)完全参考:通用错误码、组件错误码基址与错误码到字符串的转换机制

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询