桌面窗口层次关系
桌面窗口层次是这样的
检查系统是否开启了Aero
动态壁纸技术需要系统开启Aero才行,原因下面会讲到。
检测系统是否开启了Aero可以使用 DwmIsCompositionEnabled 函数。
只有在Win7及以前的系统上需要检测,Win8后这个函数总是返回 TRUE。
未公开的消息
桌面窗口内部有一个神秘的消息:WM_USER + 300
,数值为0x52C
。
它收到这个消息后就会在其上创建两个窗口,并将图标层移动上去,然后窗口层次就变成这样了
如果系统没有开启Aero,它收到消息后就不会创建这两个窗口,也就无法实现动态壁纸了,这就是系统必须开启Aero的原因。
创建壁纸窗口
最后一步就是创建一个Win32窗口了,然后将其父窗口设置为上面提到的Worker窗口(靠下面的那一个)。
1 | HWND createWindow(HWND hParent) |
还有个细节要注意,当动态壁纸窗口销毁时需要将父窗口刷新一下,因为父窗口的扩展样式用到了WS_EX_TRANSPARENT
,这是一个透明窗口,如果不刷新的话,动态壁纸窗口的残影会一直留在桌面上。
最简单的刷新办法是隐藏它,我们在窗口消息过程中处理即可
1 | LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lparam) |
剩下的就是在窗口上播放一个短视频了。还有的人甚至在上面放置浏览器,这不是一个好注意,浏览器太占用内存资源,会比较卡。
至此,一个简单的动态壁纸功能就实现了。
思考
如果要使软件更加完美,还需要考虑以下问题
1、当桌面窗口大小变化时(修改分辨率),壁纸也要跟着变化。
2、用户执行全屏程序时,应停止播放动态壁纸以便节省系统资源。
3、交互功能,一般不用实现交互功能,如果要做,可以考虑HOOK、消息钩子的手段。
参考
如何实现一个 windows 桌面动态壁纸
自定义·自制HTML壁纸
Draw Behind Desktop Icons in Windows 8+
Draw on Windows 10 wallpaper in C++
Drawing on the desktop background as wallpaper replacement (Windows/C#)