Files
2026-07-13 10:23:41 +00:00

12 KiB
Raw Permalink Blame History

Note

本文档由 WeHub 基于上游 README 翻译整理,属于社区翻译,非官方中文文档。
English · 原始项目 · 上游 README
原作者、版权与许可证归属以原始项目及本仓库 LICENSE 文件为准。

PeekDesktop 👀

点击空白桌面壁纸(或空白任务栏区域)即可显示桌面 — 就像 macOS Sonoma 一样。

PeekDesktop 将 macOS Sonoma 的「点击壁纸显示桌面」功能带到了 Windows 10 和 11。默认情况下,它使用资源管理器(Explorer)原生的 Show Desktop 行为,同时还包含可选的 Fly Away 实验性样式,以及托盘开关:Require Double-ClickPeek on Desktop ClickPeek on Taskbar Click。你可以正常点击或拖动桌面图标,而不会意外触发 peek。完成后,点击任意窗口、任务栏或壁纸,一切就会回到原来的位置。

PeekDesktop 演示:点击壁纸时窗口最小化

下载

📥 下载最新版本

使用 Winget 安装

PeekDesktop 在发布带标签的版本时,会以 Hanselman.PeekDesktop 的形式提交到 Windows Package Manager 社区仓库。社区清单被接受后,可使用以下命令安装:

winget install Hanselman.PeekDesktop

下载发行版

File Platform
PeekDesktop-vX.Y.Z-win-x64.zip Intel/AMD(大多数 PC
PeekDesktop-vX.Y.Z-win-arm64.zip ARM64Surface Pro X、骁龙等)

无需安装程序。下载 zip 文件,解压后运行 PeekDesktop.exe。发行版构建为 self-contained(自包含),因此无需单独安装 .NET。它驻留在系统托盘中,并会 自动更新 — 有新版本可用时,会下载、验证代码签名,并原地重启。

文档

  • 工程深入剖析 - 架构、Shell 内部机制、实验、调试工作流、未公开 API 说明及发行版权衡
  • 自动更新器 - 原地自动更新系统的工作原理、安全模型、交换流程与测试

工作原理

  1. 点击空白桌面壁纸或空白任务栏区域(不是图标或任务栏按钮)-> 显示你的桌面
  2. 停留在桌面上 -> 点击或拖动图标、右键点击并重新排列,同时窗口保持隐藏
  3. 再次点击任意应用、任务栏或空白壁纸 -> 所有窗口恢复到原来的确切位置

就这么简单。开箱即用。

Peek 样式

  • Show Desktop (Explorer) — 默认且推荐的模式。使用 Explorer 原生的 Show Desktop 行为。
  • Fly Away (Experimental) — 将窗口动画移出屏幕。有趣,但在与外部窗口管理(Win+D、任务栏)配合时存在已知怪癖。适合追求视觉效果,但若 Shell 在后台改变了窗口状态,可能会出现混乱。

底层原理

PeekDesktop 使用轻量级 Windows API

  • SetWindowsHookEx(WH_MOUSE_LL) — 底层鼠标钩子,用于检测桌面点击
  • WindowFromPoint — 识别光标下方的窗口
  • MSAA hit-testing (AccessibleObjectFromPoint) — 区分空白壁纸与桌面图标
  • UI Automation hit-testing — 分类空白任务栏空间,不会在「开始」、固定应用或托盘按钮上触发
  • Taskbar Show Desktop button click — 主要路径,不受键盘重映射影响(PowerToys 等)
  • Win+D SendInput — 任务栏按钮不可用时的备用方案
  • EnumWindows + WINDOWPLACEMENT — 捕获每个窗口的精确位置和状态(包括最大化)
  • SetWinEventHook(EVENT_SYSTEM_FOREGROUND) — 监视你切换回应用的时刻
  • SetWindowPlacement — 将窗口恢复到之前的精确位置

无需管理员权限。空闲时占用 < 5 MB 内存。

系统托盘

右键点击托盘图标可查看选项:

  • Enabled — 开启/关闭 peek 功能
  • 🔁 Start with Windows — 登录时自动启动
  • 🖱️ Require Double-Click — 可选择在桌面上双击以触发 peek
  • 🎮 Pause While Gaming / Full-Screen — 默认开启,适用于独占全屏和已知的游戏全屏应用
  • 🖥️ Peek on Desktop Click — 默认开启;关闭后仅通过任务栏激活
  • 📌 Peek on Taskbar Click — 可选择在空白任务栏空间触发 peek
  • 🪟 Restore All Windows on App Switch — 默认开启;在 Explorer show desktop 模式下,通过任务栏/Alt+Tab 切换应用时,会在所选应用背后恢复所有隐藏窗口
  • 👀 Peek Style — 在 Explorer 与 fly-away 模式之间切换
  • About — 版本信息
  • ⬇️ Check for Updates — 自动下载并安装较新版本
  • 🔄 Auto-Check for Updates — 默认开启;启动时静默检查更新
  • Exit — 退出 PeekDesktop

当 Windows 处于深色模式时,托盘菜单也会在操作系统支持的情况下跟随系统主题。

新特性

  • 小型 Native AOT 单文件构建,同时支持 x64 和 ARM64
  • Peek on Taskbar Click — 可选择在空白任务栏空间触发
  • 仅任务栏激活 — 禁用桌面点击 peek,同时保持任务栏 peek 启用
  • 深色托盘菜单支持 — 在可用时跟随 Windows 深色模式
  • Taskbar button Show Desktop — 绕过键盘重映射器(PowerToys Keyboard Manager 等)
  • Pause While Gaming / Full-Screen — 在游戏过程中避免干扰
  • Require Double-Click — 桌面 peek 的可选双击触发
  • 原地自动更新器 — 自动下载、验证 Authenticode 签名、交换并重启

macOS Sonoma 与 PeekDesktop 对比

Feature macOS Sonoma PeekDesktop
点击壁纸以 peek
点击应用后恢复
再次点击壁纸后恢复
点击/拖动图标不会触发 peek
可访问桌面图标
精确恢复窗口位置
系统托盘控制
多显示器支持
随系统启动 Login Items Registry
平滑动画 Fly Away 模式

从源码构建

Requirements: .NET 10 SDK

git clone https://github.com/shanselman/PeekDesktop.git
cd PeekDesktop
dotnet build src/PeekDesktop/PeekDesktop.csproj

运行

dotnet run --project src/PeekDesktop/PeekDesktop.csproj

# Run the P/Invoke safety harness (invalid handles + stress/leak checks)
dotnet run --project src/PeekDesktop.InteropHarness/PeekDesktop.InteropHarness.csproj -- 10000

# Windows-friendly wrapper script
.\test.ps1 -Iterations 10000

# Verbose mode (prints per-test timing + leak probe diagnostics)
.\test.ps1 -Iterations 10000 -VerboseOutput

发布自包含单文件 exe

# For Intel/AMD
dotnet publish src/PeekDesktop/PeekDesktop.csproj -c Release -r win-x64 --self-contained -p:PublishSingleFile=true

# For ARM64
dotnet publish src/PeekDesktop/PeekDesktop.csproj -c Release -r win-arm64 --self-contained -p:PublishSingleFile=true

发行版打包

发行版构建使用 .NET Native AOT — exe 是完全原生二进制文件,不依赖 .NET 运行时。当前发行版以自包含单文件可执行文件形式发布,同时支持 x64 和 ARM64。早期实验也曾使用 PublishAotCompressed (LZMA),但当前构建更注重兼容性和可预测的启动行为。

架构

src/PeekDesktop/
├── Program.cs             # Entry point, single-instance mutex
├── DesktopPeek.cs         # Core state machine (Idle ↔ Peeking)
├── MouseHook.cs           # WH_MOUSE_LL global mouse hook
├── FocusWatcher.cs        # EVENT_SYSTEM_FOREGROUND monitor
├── WindowTracker.cs       # Enumerate, minimize, and restore windows
├── DesktopDetector.cs     # Identify desktop windows, icons, taskbar
├── Win32MessageLoop.cs    # Win32 message loop + TaskbarCreated recovery
├── Win32TrayIcon.cs       # Shell_NotifyIcon wrapper
├── Win32Menu.cs           # Win32 popup menu wrapper
├── Win32Icon.cs           # Programmatic icon via CreateIconIndirect
├── WinHttp.cs             # WinHTTP wrapper (replaces HttpClient)
├── TrayIcon.cs            # Tray icon business logic + menu wiring
├── AppUpdater.cs          # In-place auto-updater (download, verify, swap, restart)
├── AppDiagnostics.cs      # Logging via Trace/DebugView
├── Settings.cs            # Hand-written UTF-8 JSON persistence + autostart
└── NativeMethods.cs       # Win32 P/Invoke declarations

贡献

欢迎 PR!当前状态与后续计划:

  • 点击空白壁纸以 peek
  • 点击空白任务栏区域以 peek(可选开启)
  • 点击应用或任务栏后恢复
  • 再次点击壁纸后恢复
  • 点击或拖动桌面图标不会触发 peek
  • peek 时右键桌面图标(上下文菜单保持打开)
  • peek 时桌面图标仍可使用
  • 精确恢复窗口位置
  • 基于 GitHub release 的更新检查
  • 可与 PowerToys Keyboard Manager 配合使用(键盘重映射)
  • 流畅的最小化/恢复动画(滑动/淡入淡出)
  • 快捷键支持(例如,用 Ctrl+F12 切换 peek
  • 按显示器 peek(仅最小化被点击显示器上的窗口)
  • 排除特定应用不被最小化

.NET Native AOT — 体积优化之路 💾

PeekDesktop 展示了 .NET Native AOT 应用可以做得多小。从一个标准的 WinForms 应用出发,我们系统性地移除了每一处托管框架依赖,直到二进制文件变为纯 Win32 P/Invoke —— 再压缩到能放进一张软盘。

版本 二进制体积 变更内容
v0.4.5 ~65 MB 自包含 .NET(无 AOT
v0.5.0 17.5 MB 启用 Native AOT
v0.6.0 4.2 MB 移除 WinForms —— 托盘图标、菜单、消息循环改用纯 Win32 P/Invoke
v0.6.1 2.3 MB 用操作系统原生 WinHTTPwinhttp.dll)替换 HttpClient
v0.7.2 1.88 MB 移除 JSON source generator、System.ReflectionProcess.Start
v0.7.2 + LZMA ~564 KB 通过 PublishAotCompressed 进行 LZMA 压缩

压缩前 1.88 MB 里还剩什么?

  • ~1.2 MB — .NET Native AOT runtimeGC、线程、异常处理、类型系统)
  • ~0.4 MB — Utf8JsonReader/Utf8JsonWriter + async task machinery
  • ~0.2 MB — 应用代码、P/Invoke stubs、字符串字面量
  • ~0.08 MB — PE headers 与 metadata

关键技术:

  • 无 WinForms、无 System.Drawing — 通过 P/Invoke 使用 Shell_NotifyIconCreatePopupMenuTrackPopupMenuExMessageBoxWCreateIconIndirect
  • 无 HttpClientWinHttpOpen/WinHttpSendRequest 以零二进制成本使用操作系统 HTTP+TLS 栈
  • 无 JSON source generator — 为所需的两个极小 JSON 结构手写 Utf8JsonReader/Utf8JsonWriter
  • 无 System.Reflection — 通过 GetFileVersionInfoExW P/Invoke 读取 PE version resources
  • WndProc 不使用托管委托UnmanagedCallersOnly 函数指针避免 marshaling 开销
  • OptimizationPreference=Size + InvariantGlobalization + 精简 diagnostics

特别感谢 Michal Strehovský —— .NET Native AOT 的架构师 —— 他的 PR #5 启发了最后一轮优化,移除了 JSON source generator、reflection 与托管委托。当构建 AOT 编译器的人亲自优化你的应用时,你会格外重视。🙏

许可证

MIT