方寸之间,图标各安其位。
一个面向 Windows 桌面的图标围栏(Icon Fences)工具,类似 Stardock Fences。用多个可自定义的“围栏”把桌面图标分门别类收纳:半透明圆角、可拖动缩放、随桌面壁纸自适应、不受“显示桌面(Win+D)”影响。
- 图标围栏分组收纳:创建多个围栏,把常用快捷方式、文件拖进去,桌面从此整洁清晰。
- 真实图标渲染:读取目标自身的真实文件/快捷方式图标,双击即用系统
ShellExecute打开。 - 半透明圆角:围栏为 per-pixel alpha 分层窗口,支持圆角与任意半透明度。
- Win+D 免疫:围栏是独立顶层窗口但把所有者(owner) 挂到桌面
SHELLDLL_DefView——按 Win+D 显示桌面时围栏不会隐藏,且可被普通窗口正常遮挡(不置顶)。 - 全功能围栏操作:
- 标题栏拖动移动;双击标题栏重命名。
- 四边/四角原生缩放(缩放光标跟随)。
- 条目多选(Ctrl / Shift 点选整组)、整组拖放;可把条目拖到其他软件(仅复制,不移动源文件,避免引用死链)。
- 点击围栏内外任意非选中区自动取消选择(全局低级鼠标钩子)。
- 溢出模式:滚动 或 省略(超出容量折叠为“还有 N 项”)。
- 显示模式:图标 或 列表。
- 拖拽重排带实时插入指示线:围栏内拖动条目改变顺序时,
DragOver按光标相对各条目边框的位置实时算出插入索引,并画出高亮插入线(图标模式竖线贴目标格左/右、列表模式横线跨条目宽度);空白处不再恒为末尾,而是按光标位置插入到对应位置。所见即所得,瞄准更顺手。
- 层叠模式(窗口层级):可在右键菜单或配置窗切换三种模式,即时生效、随配置持久化:
- 置底(默认):把窗口 owner 设为桌面
SHELLDLL_DefView→ Win+D 不隐藏、沉在普通窗口之下(等同此前默认行为)。 - 置顶:解除桌面 owner,用
HWND_TOPMOST成为始终置于所有普通窗口之上的窗口;代价是按 Win+D 会像普通置顶窗一样被隐藏(Windows 置顶窗标准行为)。 - 窗口:独立顶层窗口,随普通窗口 z 序、可点击聚焦、Win+D 会最小化、可 Alt+Tab(不入任务栏)。
⚠️ 取舍:“Win+D 免疫(owner=桌面)”与“总在最前(置顶)”在 Windows 下互斥——被拥有的窗口必须始终位于 owner 之上,而桌面 owner 位于 z 序最底层,二者只能取其一;“置顶”按“总在最前”实现。
- 置底(默认):把窗口 owner 设为桌面
- 同步模式(文件夹活镜像):
- 手动(默认):自由增删,等同此前行为。
- 监视:在弹出的配置窗里指定文件夹地址(含「浏览」按钮)+后缀筛选(如
txt;*.png;lnk,留空=全部),确定后围栏自动成为该文件夹的“活镜像”——文件新增 / 删除 / 重命名实时同步进围栏;双击打开仍指向真实文件/快捷方式;切回手动即停止监视并保留当前条目转为自由管理。重启后若原为监视模式会自动接管。
- 随桌面壁纸自适应:可选“随桌面自适应”——按围栏所在壁纸区域的明暗生成中性半透明玻璃背景(RGB 与壁纸色相无关、保留 ~40% 透出桌面,观感始终透明可辨,不会因“同色叠自己”而像一块不透明色板),换壁纸自动刷新;栏底(标题栏)玻璃同源略暗,保持可分辨;拖动/缩放围栏时也会按所在桌面区域实时重算(200ms 防抖,避免拖动每帧采样卡顿)。条目与标题字体颜色按玻璃灰度自动在黑/白间切换(标题字单独按更暗的栏底玻璃判定,深栏底必出白字),保证任何壁纸下都清晰可读。
- 系统托盘常驻:开机自启、新建围栏、一键**隐藏/显示所有围栏(N)**、退出。
- 多实例免疫:单实例守卫,双击 exe 不会重复叠加启动。
- 跨显示器记忆:每个围栏记住所属显示器(
DeviceName)及其在屏内的相对位置;副屏拔掉时不丢失记忆(仍记着它在哪块屏、偏移多少),重新插回时自动还原到原相对位置(无需重启,订阅SystemEvents.DisplaySettingsChanged实时响应)。记忆与绝对坐标解耦,旧 config 无此字段则首次启动自动建立。
配置窗口按“背景样式 → 标题栏样式 → 条目样式”组织(预设主题在右键「预设主题」子菜单,不在配置窗内);围栏右键「预设主题」子菜单含「自适应/浅色/深色/自定义」,前三项立即应用、「自定义」进入配置窗手动调色,且当前主题会在子菜单对应项上打勾(自定义态勾在「自定义」上)。手动改任意自定义配色会自动退出自适应(自定义色不被后续壁纸重算覆盖)。菜单中点选「⋯」按钮或右键标题栏可快速切换显示模式与溢出模式。
下载 Release 的单文件 Fangcun.exe,双击即可运行,无需安装 .NET(--no-self-contained 版需本机装有 .NET 10 Desktop Runtime)。
环境:Windows + .NET 10 SDK。
git clone git@github.com:highwindmx/fangcun.git
cd fangcun
# Debug 运行
dotnet run --project Fangcun
# 发布单文件 exe(win-x64,框架依赖)
dotnet publish Fangcun -c Release -r win-x64 --no-self-contained \
-p:PublishSingleFile=true -p:PublishReadyToRun=false产物位于 Fangcun/bin/Release/net10.0-windows/win-x64/publish/Fangcun.exe。
- 配置:
%LocalAppData%\Fangcun\config.json(围栏列表、位置尺寸、样式)。 - 运行日志:
%LocalAppData%\Fangcun\fangcun.log(排障用,尤其 Win+D 免疫的 owner 挂载状态)。
主题
方案
窗口模型
顶层 Window + AllowsTransparency(per-pixel alpha),非 reparent 子窗
Win+D 免疫
SetWindowLongPtr(hwnd, GWL_HWNDPARENT, SHELLDLL_DefView) 设 owner,非 SetParent 子窗关系 → 半透明圆角正常 + 不随 Win+D 隐藏 + 坐标零污染
缩放/移动
WM_NCHITTEST 返回 HT*/HTCAPTION 交系统原生处理(根 ResizeMode=CanResize)
圆角
WPF CornerRadius + Clip
图标
SHGetFileInfo 取目标自身真实图标
自适应背景
WallpaperTint 采样壁纸区域明暗 → 生成中性玻璃色(RGB 与壁纸色相无关),SystemEvents.UserPreferenceChanged 即时刷新;心跳另做壁纸签名(路径+时间戳)轮询兜底,覆盖第三方换壁纸不触发系统事件的情况;LocationChanged/SizeChanged 在自适应开启时以 200ms 防抖重算,使围栏移到不同亮度的桌面区域时背景随位置变化。字体色由 ComputeInk 基于玻璃灰度 v(栏底用 v*0.82)判定黑/白,根除"栏底压暗后标题黑字看不清"的问题。
层叠模式
ApplyLayerMode() 按 Fence.LayerMode 切换:置底=SetWindowLongPtr(GWL_HWNDPARENT, SHELLDLL_DefView) 设 owner + SendToBack 沉底;置顶=清除桌面 owner + SetWindowPos(HWND_TOPMOST)(注意 owner 与 TOPMOST 互斥,挂桌面 owner 会令窗口被钉在桌面层、永远浮不到普通窗口之上);窗口=清除 owner/Topmost/NOACTIVATE,成为独立顶层窗口。OnSourceInitialized 调用、Closed 释放。
同步模式
ApplySyncMode() + FileSystemWatcher(NotifyFilter=FileName|DirectoryName,后缀筛选靠 MatchesFilter 手动匹配);Created/Deleted/Renamed/Error 回调均在 Dispatcher.Invoke 回 UI 线程增删/改路径;Error 后重建 watcher(缓冲溢出恢复)。进入监视先 ResyncFromFolder() 以文件夹当前内容全量重建。外部拖入在监视模式被忽略以防孤儿项。
本项目在“让 Windows 围栏既保持半透明圆角、又能免疫 Win+D”这一难点上,深受 **openFence**(C++/Win32 桌面围栏)的思路启发——尤其是“贴桌面 + 分层合成”的窗口宿主机制,以及“显示桌面只最小化顶层窗口、归入桌面归属即可逃逸”这一关键原理的印证。在此对 openFence 项目的作者与贡献者表示诚挚感谢。
Powered by WorkBuddy
MIT © 2026 highwindmx