有一位名叫小旺的小伙伴,最近和女朋友在追一档综艺节目《一年一度喜剧大赛》。

这档节目播出以来,形式年轻化、多样化,剧本也是脑洞频出、创意无限、极具特色,颇受时下年轻人的追捧。

其中就有这么一部被主创者自称为陷阱喜剧的小品《先生请出山》,在播出后突然网络上就爆火了。

这不,小旺和他女朋友也着了迷、上了瘾,问我能不能把这视频放到桌面上,这样不就又可以看又显得酷了?


有这么让人痴迷吗?

我还真有点不信哈,结果当我看了一遍那魔性的舞步和风骚的走位后就再也出不来了!

嘿嘿,没错,被成功洗脑的我,现在也时常动不动就想模仿一下那舞步的动作。

现在大部分年轻人不抽烟不喝酒也就图点这些乐子了,理解理解!

我和小旺说,不是有不少动态桌面壁纸程序嘛,下载下来用就是了。

可我得到的回复是,这些软件不是收费的就是里面夹带私货的,都不怎么让人放心,问有没有靠谱点的方法。

也是哈,于是同样上头的我研究了好几天,最终自己动手成功将这魔性舞步视频当作了动态桌面壁纸!


在本文结尾有自制程序下载,免费安全可靠,不夹带任何私货哦~


实验平台

Windows 10 (默认开启 Aero


目标效果

可以基本实现在桌面上播放视频,达到动态桌面的效果。

与此同时,不妨碍日常的操作,比如桌面图标的点击、移动等。


工具介绍

欲善其工,必利其器,除了编程工具外,在正式开始了解原理之前,我们需要先请出“窗口句柄抓取工具”:Microsoft Spy++

它是来自 Vistual Studio 的一个实用工具,可以提供系统的进程、线程、窗口及消息的图形视图。


当然如果你对此比较熟悉,也是可以用其他一些窗口句柄查看工具的。

不过如果你不太清楚什么是窗口句柄,那也没关系,我简单给你解释一哈,你大概了解了解就行。


首先我们要知道,在系统中窗口(或叫作窗体)是最常用最基本的容器载体,在窗口中会有很多各种各样不同的控件,它们都是用来操作系统功能或与用户互动的。

窗口很重要,那么我们如何管理这些窗口呢?

很简单,系统会分配给这些窗口一个ID,这个ID就叫作句柄(Handle)。

这些窗口的句柄就像身份证号码一样,当我们想要操作它们的时候,只要告诉系统它们的身份证ID也就是窗口句柄就可以了。

那么 Spy++ 可以提供图形化的参考,让我们获知哪个窗口是哪个句柄。


桌面壁纸原理

实际上我们的系统是由很多很多个窗口组成,有的看得见,有的看不见(隐藏或透明),有的看得见但无法直接访问,而有的即使看不见我们也可以对它进行操作,总之所有的这些窗口互相堆叠最后呈现在我们面前。

你只要把这些窗口想像成多块不同的玻璃,就像照镜子一样由近及远、分别多层次地立在了你的面前,有的透明而有的不透明。

那么对于桌面来说,它也算是一块玻璃(一个窗口),只是它有些特殊,里面还套着几个小玻璃(子窗口)。

因此,大概地了解了窗口的概念,那么我们就可以使用 Spy++ 来观察它具体是个啥模样了。


桌面窗口本来的模样

如下图,通过 Spy++ 来展开当前窗口的句柄树,就可以非常容易地了解到桌面窗口里面是怎么套娃的。


最顶上就是桌面窗口的句柄,在它下面还有很多个子窗口。

其中重点的对于我们有用的就是名字叫作 Program Manager 的子窗口,它正是我们苦苦寻找的桌面背景,里面囊括了包含壁纸和图标的子窗口。

简单地说,桌面窗口就如下面这样的层次。

|- "Program Manager" Progman    // 总体桌面
|--- "" SHELLDLL_DefView    // 负责显示桌面图标
|----- "FolderView" SysListView32    // 控制桌面图标排列顺序
|------- "" SysHeader32    // 隐藏窗口,功能不详
 


这些子窗口中的 "" SHELLDLL_DefView 就是桌面图标窗口了。

简单说一嘴,引号里是 窗口标题 ,而后面则是 类名 ,比如 "Program Manager" 就是窗口标题,而 Progman 就是类名了。

知道窗口标题和类名会非常有利于我们查找定位窗口,进而可以方便地对其进行操作。


直接嵌入 Progman 窗口中行吗

根据前面的介绍,我们很容易得出一个结论,既然桌面壁纸和图标是分别属于不同的子窗口,那么是不是我们可以将自己的程序窗口插入它们之间,就可以实现在图标下方显示呢?

理论想法是没错,可经过我的实际测试,非常遗憾根本无法实现这样的效果!


将程序窗口设定为 Progman 的子窗口,虽然它跑到了所有窗口的最后面,但是却无法在图标后面显示。


那么问题出在哪儿呢?


冒出来个多桌面 WorkerW

原来啊,我们使用的是 Windows 10 系统,虽说它默认就支持 Aero 效果,但它还有一个多桌面的新功能,你只要按一下 Win + Tab 键就能看到了。

而这个多桌面功能会使得桌面窗口产生奇妙的变化,系统会生成多个 WorkerW 的窗口出来。

这个 WorkerW 我们可以简单理解为为了切换桌面的小窗口,只不过现在变出来很多个。

而跑出来的这么多个 WorkerW 窗口中呢,有一个会把原来 Progman 下的子窗口给“抢过去”,就像下图那样。


好了,这么一来可坏事了!

我们按照 Progman 窗口来找到桌面图标背景的方法就彻底失效了!

那为啥要搞出来这么多个 WorkerW 呢,就不能愉快地使用 Progman 吗?

实际上官方是这么解释的,为了让桌面切换呈现平滑过渡的效果,因此设计启用了多个 WorkerW 窗口,否则效果会糟糕到让你想砸电脑了。

好吧,道理大家都懂,那接下来怎么整呢?

既然 Progman 下的子窗口被“抢过去”了,那是不是我们可以尝试寻找这个拥有 SHELLDLL_DefView 类子窗口的 WorkerW ,然后将自己程序的窗口作为子窗口放到它的后面就行了呢?


尝试将程序窗口嵌入 WorkerW

经过我又一番的折腾,发现即使找到了目标 WorkerW ,并且将程序窗口放到它在下面还是行不通。

如下图,程序窗口虽然跑到了所有窗口的最后面,但却还是停留在了桌面图标的前面,效果就跟前面将程序窗口挂在 Progman 下面是一样一样的。


这下我就懵了,怎么这也不行,那也不行呢?

实际上这里是有一个套路的,而这个套路着实让我琢磨了很久很久!

什么套路呢,咱们往下看!


我查阅了网上大量的资料,在不断的实验中我发现除了拥有子窗口的 WorkerW 之外,其他所有的 WorkerW 都是隐藏不可见的。


而实际有效的做法是,我们需要将程序窗口嵌入到第二个可见非隐藏的 WorkerW 之上才行。

注意它的特点有两个,第一是排名第二并不含有子窗口,第二是可见非隐藏属性。


WorkerW 窗口可见并且变透明

前面我们说过,按下 Win+Tab 键可以切换多桌面,当我们这么一切换时,系统就会产生多个 WorkerW 窗口用于过渡切换效果。

所以我们可以用程序模拟按下 Win+Tab 键。

不过我尝试模拟按键后,发现有窗口闪动的现象,不是太理想的状态,于是我找到了网上的资料。


根据网上资料,Windows 有一个系统保留消息,当我们向 Progman 窗口发送 0x052C 消息时,桌面就会生成一个透明的 WorkerW 窗口,同时会将 Progman 的子窗口转移到这个新生成的 WorkerW 之下。

这也正是我们前面所看到的,子窗口被“抢过去”的效果。

需要注意的是,这是在 Vista 之后的版本才有效,嗯,可以理解为开启 Aero 效果的系统。

我用 VB 代码很容易就实现了,就像下面这样。

' 获取 Progman 句柄
lngDesktopHwnd = FindWindow("Progman", vbNullString)

' 然后向 Progman 发送 0x052C 使其产生 WorkerW
SendMessage lngDesktopHwnd, &H52C, 0, 0
 


遍历查找目标 WorkerW 窗口

生成了我们想要的 WorkerW 窗口后,我们就要想办法去找到那个目标窗口,也就是第二个可见的 WorkerW 窗口。

切记,这个 WokerW 窗口是可见非隐藏的,并且同时不包含任何子窗口的。

我的遍历算法能用但灰常粗糙,你们简单参考,自己改进哈。


' 获取桌面句柄
lngDesktopHwnd = GetDesktopWindow

' 获得第一个 WorkerW 窗口句柄
lngWorkerW = FindWindowEx(lngDesktopHwnd, 0, "WorkerW", vbNullString)

' 定义临时类名,用于对比查找多个同级的 WorkerW 窗口
Dim lpClassName As String

' 遍历所有 WorkerW 直至找到不拥有 SysListView32 子窗口的那个 WorkerW 为止!
Do While lngWorkerW > 0

    If IsWindowVisible(lngWorkerW) Then

        lngShellDll = FindWindowEx(lngWorkerW, 0, "SHELLDLL_DefView", vbNullString)

        If lngShellDll = 0 Then
            Exit Do
        Else

            ' 查找下一个同级的类窗体句柄
            lpClassName = Space(255)
            Do While UCase(Left(lpClassName, 7)) <> UCase("WorkerW")
                lngWorkerW = GetWindow(lngWorkerW, GW_HWNDNEXT)
                GetClassName lngWorkerW, lpClassName, 255
            Loop
        End If

    Else

        ' 查找下一个同级的类窗体句柄
        lpClassName = Space(255)
        Do While UCase(Left(lpClassName, 7)) <> UCase("WorkerW")
            lngWorkerW = GetWindow(lngWorkerW, GW_HWNDNEXT)
            GetClassName lngWorkerW, lpClassName, 255
        Loop
    End If

Loop
 


将程序窗口变成目标 WorkerW 窗口的子窗口

看到没,就像下图这样,我们的程序窗口跑到了第二个可见 WorkerW 的下面了。


参考代码如下:

' 将程序窗口设定为 WorkerW 的子窗口,WorkerW 成为父窗口
lngOriginalParentHwnd = SetParent(Me.hwnd, lngWorkerW)

' 最后在程序退出时别忘记再变回来
lngTmpHwnd = SetParent(Me.hwnd, lngOriginalParentHwnd)
 


最后,我们看到了这样的效果,窗口终于跑到了图标的后面,耶!


效果演示

后续还有很多工作需要继续,比如播放器的操作控制,前景布局等等。

不过这些繁杂的事不算主要问题,我们只要基本能够实现桌面动态播放视频即可。

就像下面,效果还算可以吧。


点击浏览,选择视频文件。


先载入视频,再点击播放。


来张动图展示一下实际效果,可以看到视频是在图标后面播放的。


我搞了两个版本的程序,对比如下:

  • WindowsMediaPlayerWindows 系统自带无需额外安装播放器,但可能播放效果差。

  • VLCMediaPlayer:需要单独安装 VLC 播放器,但播放效果好。

    安装播放器要选择32位的,同时切记切记务必务必要安装 ActiveX 插件 !!


使用方法很简单,除单独需要安装播放器外,下载后只要解压缩后直接使用就可以了,绿色环保。


网管小贾的MP4动态壁纸程序(WindowsMediaPlayer).7z (106K)

下载链接:https://pan.baidu.com/s/1ow7k9IrIZDuJh0ExbijqZA

提取码:

输入阅读密码,解锁隐藏内容...



★扫码关注公众号, 发送【000903】获取阅读密码


网管小贾的MP4动态壁纸程序(VLCMediaPlayer).7z (106K)

VLC 安装包较大,此压缩包不含 VLC 安装包,请到下面官网链接下载。

下载链接:https://pan.baidu.com/s/1xoiwZpzKeUzmYcmBepoRlw

提取码:

输入阅读密码,解锁隐藏内容...



★扫码关注公众号, 发送【000903】获取阅读密码


VLC Media Player(vlc-3.0.16-win32).exe (40M)

当前最新版本 3.0.16 ,切记安装 32 位。

下载链接:https://www.videolan.org/


《先生请出山》魔性舞步演示视频小片段

下载链接:https://pan.baidu.com/s/1PgIkBv--E3A5Dwuwt9VWvA

提取码:

输入阅读密码,解锁隐藏内容...



★扫码关注公众号, 发送【000903】获取阅读密码


PS:后期经过测试,我发现在一些较新电脑高分辨率屏幕下会出现界面错乱的问题。

解决的方法也很简单,右键点击应用程序 XJLiveWallpaper.exe ,然后在属性窗口中点选 兼容性 ,在下方找到 更改高 DPI 设置 按钮,然后勾选 替代高 DPI 缩放行为 ,并确保缩放替代对象的是 应用程序


写在最后

前面啰嗦了一大堆,窗口已经实现在桌面图标后面显示了,之后的工作也就此继续展开。

虽然在窗口上加上个播放器,然后再给它一些播放时的操作控制功能看似简单,但起先我为了节约时间就把系统默认自带的 Windows Media Player 直接拿来用了,自然有时候它的播放效果并不是很理想,特别是对于要求高的小伙伴。

当然以后有时间的话,我是会改进这一问题,使用 libVLC 来做为播放引擎。

(PS:目前已经初步补上了,下载链接前面有~)


除播放器外,前景布局效果也是挺有挑战性的,比如在桌面图标的后面和视频的前面挂个 Logo 或是时钟啥的。

当然这是以后我有空有闲的事了。

在这里需要向小伙伴们声明一下,由于我也是个小白,查找资料连带测试花了我不少时间,因此做出来的最终效果可能无法和那些商业软件相比,请小伙伴多多包涵。


好了,至少对我来说还算满意,小旺同学也试用OK,和女朋友感情升温,关系也更进了一步,也算我成就了一桩好事啊!

如果你们喜欢,或是有此需要,尽管拿去拿去别客气!

但是哈,别忘记关注、点赞外加转发哦!

祝小伙伴们新年心想事成,一切顺遂,么么哒~


扫码关注@网管小贾,阅读更多

网管小贾的博客 / www.sysadm.cc



暂无评论

登录并提交评论

© 2020-present 网管小贾 | 微信公众号 @网管小贾
许可协议:CC-BY-NC 4.0 | 转载文章请注明作者出处及相关链接