Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MovingBackground — 桌面动态背景层

纯 Win32 API + GDI+ 写的桌面覆盖程序:一张图铺满桌面,鼠标移动时整张图片反向平移, 鼠标回到屏幕中心图片回到正中,带弹簧加减速缓冲,边缘自动约束不会露黑边。 托盘图标 + 设置对话框,可开开机自启。没有 ESC 退出。

编译

源码只有一个 MovingBackground.cpp,不需要 .rc 资源文件。

一键编译(优先 MSVC,其次 MinGW):

build.bat

手动编译 MSVC(/utf-8 必须加,否则源码里的中文界面文字会乱码):

cl /nologo /utf-8 /EHsc /O2 /DUNICODE /D_UNICODE MovingBackground.cpp ^
   /link /SUBSYSTEM:WINDOWS user32.lib gdi32.lib gdiplus.lib shell32.lib ^
         comdlg32.lib advapi32.lib winmm.lib

手动编译 MinGW-w64:

g++ -O2 -municode -mwindows MovingBackground.cpp -o MovingBackground.exe ^
    -lgdiplus -lgdi32 -luser32 -lshell32 -lcomdlg32 -lwinmm -static

使用

  1. 图片默认用仓库里自带的 bg.jpg(和 exe 放同一目录)。想换成自己的图: 托盘右键 → 打开设置 → 选图片,或改源码顶部 CONFIG_IMAGE_PATH。 写相对路径(如 bg.jpg)时按 exe 所在目录 解析,不依赖当前工作目录, 所以开机自启(工作目录是 C:\Windows\System32)也能正确找到图。
  2. 运行 MovingBackground.exe,图片会作为一个顶层窗口插在桌面正上方: 盖住桌面壁纸和桌面图标,但仍在所有普通窗口和任务栏之下,鼠标点击可穿透到桌面。 注意这不是"把图挂进壁纸层"——图标会被图片盖住(图标仍在原位、仍能点到), 做不到"图片在图标下面"。为什么只能这样,见下面「关于层级」。
  3. 托盘图标(图片缩略图):
    • 右键 → 打开设置 / 重新加载图片 / 开机自动启动 / 退出
    • 双击 → 打开设置
  4. 退出:托盘右键 → 退出,或 Ctrl+Alt+Q(可在配置区关掉)。

配置

优先级:MovingBackground.ini(exe 同目录,首次运行自动生成)> 源码顶部 CONFIG_* 默认值。

配置项 说明 建议范围
ImagePath 图片路径,jpg/png/bmp/gif/tif。可写绝对路径,也可写相对 exe 目录的文件名(如 bg.jpg) —
MoveStrength 鼠标位移 → 图片位移比例 0 ~ 0.4
Zoom 放大倍数,决定可移动余量 (倍数-1)/2 × 屏幕 1.05 ~ 1.5
SpringOmega 弹簧角频率,越大回中越快 3 ~ 15
SpringZeta 阻尼比,<1 有过冲回弹,=1 不过冲 0.4 ~ 1.0
MarginUse 余量使用率,留边防露黑边 0.8 ~ 1.0
VirtualDesktop 1=覆盖所有显示器,0=只覆盖主屏 0/1
FrameMs → Fps 帧率档位:30 / 60 / 75 / 90 / 120 / 144 / 180 / 240 见下节
Autostart 开机自启(写 HKCU\...\Run)。默认 0:程序不会自动改你的注册表,想要自己勾 0/1
ExitHotkey 是否启用 Ctrl+Alt+Q 退出 0/1
LayerMode 0=插在桌面正上方(默认,盖住图标、不盖窗口) 1=置顶(盖住所有程序) 0/1
DeadZone 中心死区像素:鼠标离屏幕中心这么近时图片完全不动 80 ~ 300
IdleReturnMs 鼠标停下多久后自动缓缓回中;0=关闭(默认,最不晕) 0 或 3000+
IntroMs 启动/退出缩放动画时长:启动时从 100% 平滑长到 Zoom,退出时反向演一遍再退出。0=关闭 300 ~ 1500

启动/退出缩放动画

程序启动时,图片从**刚好铺满屏幕(100%)**平滑放大到设置的 放大倍数(默认 1.08 = 108%); 点退出时反向演一遍,演完才真正退出(所以退出动画期间程序还活着,不是卡住了)。

  • 时长由 IntroMs 控制(默认 700ms),0 = 关闭(启动即最终倍数、点退出立刻退出)。
  • 用 smoothstep 缓动,两端都平滑,不会突然起步或急停。
  • 动画期间鼠标平移会按进度一起淡入,动画结束正好接上正常的跟手位移,中间没有跳变。
  • 实测(把 IntroMs 设成 3000 便于观察):
时刻 画面 = 最终状态的
启动 t≈0 92.5%(正好 100% ÷ 1.08)
启动 t≈1.2s 95.5%
启动 t≈2.4s 100.0%
退出 +0.5s 98.8%
退出 +2.6s 92.5%
退出 +3.1s 窗口销毁、程序退出(设定 3000ms)✓

实现方式:预缩放位图仍然只做一次(按最终倍数),动画期间用 StretchBlt 按当前比例取一块源矩形拉伸到窗口。 缩放幅度小(默认档位最大 8%)时用 COLORONCOLOR(快),幅度大才用 HALFTONE(保质量); 比例回到 1.0 后自动切回 1:1 整数像素 BitBlt,所以最终画面依然完全清晰,动画只在过程中略软。

怕晕怎么调(重要)

默认值已经按"尽量不晕"调过了。如果还觉得晃,按这个顺序改(设置对话框里直接改,改完立刻生效):

  1. 移动强度 调到 0.04 或更低 —— 这是最直接的开关。0.08 时全屏最大位移约 92px, 0.04 就只有 46px,属于"几乎察觉不到在动"。
  2. 中心死区 调大(200~400)—— 鼠标在中心附近怎么抖,画面都纹丝不动。
  3. 阻尼比 保持 1.0 —— 只要小于 1 就会来回过冲回弹,那是最容易晕的部分。
  4. 弹簧速度 调小(1.5~2.5)—— 画面跟得更慢、更柔和。
  5. 静止回归 保持 0 —— 打开会让画面在你没碰鼠标时自己滑动,反而更晕。
  6. 放大倍数 调到 1.03~1.05 —— 可移动余量变小,位移自然更小。

让画面完全静止的极端做法:把 移动强度 设成 0,程序就变成一张静态壁纸(仍然省电、仍可托盘管理)。

帧率档位

可选 30 / 60 / 75 / 90 / 120 / 144 / 180 / 240 fps,两处都能改,改完立即生效:

  • 托盘图标 → 右键 → 帧率(单选项,当前档位带勾)
  • 托盘图标 → 打开设置 → 帧率档位 下拉框

实现上不是"每帧 Sleep 固定毫秒",而是按 QPC 绝对时间累加来调度, 所以 75 / 144 / 240 这种非整数毫秒的档位也精确 —— 实测各档都正好跑到设定值:

设定 实测 帧间隔
30 30 33.33 ms
60 60 16.67 ms
75 75 13.33 ms
144 144 6.94 ms
240 240 4.17 ms

说明:

  • 想更省 CPU 用 30(笔记本省电明显);日常 60 就够; 鼠标甩得快或者想要最顺滑用 120/144;180/240 基本只对高刷屏有意义。
  • 超过显示器刷新率的部分屏幕上看不出来,但时间精度仍然更好,动作更"跟手"。
  • 画面没有实际变化时(图片位置取整后没动)会直接跳过绘制,所以高档位在鼠标静止时 几乎不增加 CPU 占用。
  • INI 里 Fps 也可以手写其它数值(10~500),托盘菜单只列出这 8 个档位。

实现要点

  • 反向平移:目标位移 = -(鼠标离中心距离 - 死区) × MoveStrength,图片整体一起动,不分层。 死区按"距离"做平滑缩放,所以越过死区边界时不会跳一下。
  • 不出黑边:图片先按 cover 铺满,再乘 Zoom,多出来的那圈就是可平移余量; 位移被硬夹在 ±余量 × MarginUse 内,绘制时源矩形还会再夹一次。
  • 动画驱动:用高精度可等待定时器 + 独立线程驱动,按 QPC 绝对时间调度(支持任意帧率档位)。 WM_TIMER 会被系统合并延迟,实测 16ms 只能跑到 33fps,全屏平移在 33fps 下顿挫很明显、 看久了会晕 —— 换成可等待定时器后实测稳定 60fps(设为 240 时也精确跑到 240),单帧绘制 <1ms。 用独立线程还有个好处:打开设置对话框(模态)时画面不会停,改参数能立刻看到效果。
  • 性能:GDI+ 只在启动/改配置时把图缩放到一张 32bpp DIBSection, 每帧只做一次整数像素 BitBlt;位置没变化时直接跳过重绘(鼠标不动时 CPU 几乎为 0)。
  • 层级:自己作为顶层窗口,用 SetWindowPos 插到桌面窗口 Progman 正上方。 层级为:壁纸 < 本程序 < 普通窗口 < 任务栏;窗口带 WS_EX_LAYERED | WS_EX_TRANSPARENT + SetLayeredWindowAttributes(...,255,LWA_ALPHA), 鼠标点击穿透到桌面、永不抢焦点、不进任务栏和 Alt+Tab。 定时器里会检查 z 序,被顶掉就立刻重申(点桌面、Win+D 之后也能自动恢复)。
  • DPI 感知:进程按 per-monitor-v2 感知,150% 缩放时按物理像素渲染,不会被系统拉伸变糊。
  • 单实例:重复启动不会开第二个,只会把已有实例的设置窗口叫出来。
  • 健壮性:explorer 重启后会自动把托盘图标和覆盖窗口重建。

关于层级(重要,实测结论)

网上流传的"把窗口 SetParent 到 WorkerW 壁纸层,让图片待在图标下面"的做法, 在 Windows 11 24H2 及以后完全失效:实测把窗口塞进 Progman 的子窗口 (包括 Progman 下的 WorkerW 壁纸层、以及 Progman 本身)之后, 一个像素都不会被渲染到屏幕上 —— 新版桌面的壁纸由更高的合成层绘制, Progman 的子窗口被它盖住且不参与合成。

实测四种挂法在同一块桌面可见区域的结果:

挂法 能否显示 鼠标穿透
挂到 Progman 下的 WorkerW(常见教程做法) 不显示 —
挂到 Progman 不显示 —
顶层窗口 + WS_EX_TRANSPARENT 显示 挡住鼠标
顶层窗口 + WS_EX_LAYERED+WS_EX_TRANSPARENT+LWA_ALPHA,插到 Progman 正上方 显示 穿透

所以本程序采用最后一种。代价是:运行期间桌面图标会被图片盖住(图标本身还在、 也仍然点得到,只是看不见)。若想让图片盖住所有程序,把设置里"置顶(盖住所有程序)" 勾上,或把 INI 的 LayerMode 改成 1。

另外注意:WS_EX_LAYERED 窗口如果不调用 SetLayeredWindowAttributes, 会变成"完全透明"什么都看不见 —— 这里已经调了。

已验证

在 2560×1600 / 150% 缩放的机器上实测(屏幕像素 + PrintWindow 逐点比对 + 互相关求位移):

项目 结果
屏幕真的在动 鼠标移动 → 屏幕内容跟随变化 ✓
屏幕显示的就是覆盖层 桌面可见区采样点全部吻合 ✓
反向平移方向 鼠标右移 → 图片左移 ✓
位移量 鼠标右移 500px → 实测 +30px,与理论值一致 ✓
回到中心 鼠标回屏幕中心 → 位移 0 ✓
中心死区 鼠标在中心 +100px(死区 120)→ 完全不动 ✓
边缘约束 鼠标顶到屏幕最左/最右 → ±92px,正好卡在余量上限,无黑边 ✓
帧率 各档位实测都精确命中:30/60/75/144/240 → 30/60/75/144/240 ✓
启动缩放动画 从 92.5%(=100%÷1.08)平滑长到 100% ✓
退出缩放动画 100% → 92.2% 平滑缩回,演完才退出(+3099ms / 设定 3000ms)✓
托盘「帧率」菜单 切换后 INI 立即更新 ✓
设置对话框帧率下拉框 8 个档位,选中 90 → 确定 → Fps=90 ✓
鼠标点击穿透 命中桌面图标层,不挡操作 ✓
层级 紧贴桌面之上,普通窗口仍在上面 ✓
DPI per-monitor-v2 感知,物理像素渲染 ✓
托盘图标 / 设置对话框 / 单实例 均正常 ✓

已知注意点

  • 桌面图标会被图片盖住(见上面"关于层级")。图标仍在原位、仍可点击。
  • 图片建议选一张和当前桌面壁纸不同的图,否则"生效了"和"没生效"肉眼看起来差不多。
  • PNG 的透明区域会按黑色处理(BuildScaledBitmap 里先铺黑底),要别的底色改那一行即可。
  • 开机自启写的是 HKCU\Software\Microsoft\Windows\CurrentVersion\Run;如果被安全软件拦住, 勾选状态不会变,但程序其它功能正常。
  • 改完图片或换分辨率后画面没更新的话,托盘右键"重新加载图片"即可。

常见问题

Q:为什么桌面图标被盖住了? 见上面"关于层级"。这是 Win11 24H2 之后唯一能让图片既显示、鼠标又能穿透的挂法, 代价就是图标被盖住。图标本身仍在原位、也仍然点得到,只是看不见。

Q:编译出来界面中文变问号 / 乱码? MSVC 必须带 /utf-8 参数(源码是 UTF-8 无 BOM)。直接跑 build.bat 不会踩这个坑。

Q:杀毒软件报警? 这是未签名的自研程序,"全屏覆盖 + 可写注册表"的组合很容易触发启发式误报。 你可以自己 build.bat 编译一份。程序默认不修改任何注册表(Autostart 默认 0), 只有你在托盘菜单里主动勾选"开机自动启动"时才会写 HKCU\...\Run。

Q:会不会很费电 / 占 CPU? 鼠标不动时画面没有变化,程序会直接跳过重绘,CPU 占用接近 0。 笔记本想更省电可以把帧率降到 30。

许可证

本项目采用 MIT License —— 你可以自由使用、修改、分发、商用,只需保留版权声明。

仓库中的 bg.jpg 为作者自备图片,随项目一起按 MIT 分发。

参与贡献

欢迎提 Issue 和 PR。提交前请确认:

  1. build.bat 能编译通过(MSVC 或 MinGW 都行)。
  2. 改动涉及渲染 / 层级 / 帧率的,请附上你机器上的实测结果(参考上面"已验证"的表格风格)。
  3. 不要提交 MovingBackground.ini 和 *.exe——前者含个人图片路径,后者是编译产物, 两者都已在 .gitignore 里。

About

A single-file Win32/GDI+ overlay that pans a full-screen image opposite to your mouse — spring-damped, edge-clamped, tray-managed, no black edges. Zero dependencies, MIT. | 桌面动态背景层:一张图铺满桌面,鼠标一动整张图反向平移 —— 弹簧缓冲、边缘永不露黑边、托盘管理。单文件无第三方依赖。

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages