基于QT和OpenGL实现的水波动态壁纸

这个程序主要是出于娱乐和学习的目的制作的。单就这个功能而言WallpaperEngine的创意工坊中已经有了,WallpaperEngine是把一个浏览器窗口嵌入了桌面,然后在浏览器中加载各种页面作为壁纸。其实QT也可以用这种方法来实现动态壁纸,不过本程序是将一个QOpenGLWindow作为桌面实现的,省去了浏览器,牺牲了灵活性,不过体积也得以缩减。你可以方便地设置背景图片,修改水波参数来获得不同的效果。

环境

Windows7
Qt Creator 4.5.1
Qt 5.10.1 MSVC2017_64
本程序使用了WinAPI,只支持Windows系统

效果图

在这里插入图片描述

获取程序

代码

github

编译好的程序

Release

关于将窗口嵌入桌面

尽管我认为这个程序最难的部分,也就是水波效果的部分,已经在之前完成了,但是利用它来实现这个壁纸程序的过程倒也不是那么的一帆风顺,一番修改之后,这个壁纸程序中的代码并不怎么便于复用,如果你想试试给自己的程序界面添加一个有水波效果的背景,可以去我之前的文章看一看,QT使用OpenGL实现水波特效

动态壁纸程序基本上都是通过将各种窗口嵌入桌面来实现的,相关的文章倒也不少,内容也大致相同。首先获取Windows的桌面窗口句柄,然后再把桌面窗口设为我们自己窗口的父亲,其中基本都使用了SetParent的WinAPI。
然而我下载了他们的代码,至少在我自己的环境中,SetParent是不起作用的,他们都使用了QWidget::showFullScreen()函数,此操作会让窗口变得半独立,你可以通过alt+tab呼出它,令他显示在顶层,但是当你显示桌面时,又发现它渲染在了桌面上,而无论我是否注释掉SetParent这一句,窗口的表现都是一样的。
这种写法我觉得倒是也可以接受,只不过似乎跟SetParent没什么关系。毕竟我们写了一个什么样的QWidget,就可以通过这种方式令其显示在桌面上,操作比较简单,将窗口嵌入桌面的需求也可以说实现了。

不过如果你想把Qt窗口嵌入其他程序,或者是想获得更为理想的效果,可能需要研究一下QWindow相关的类。

关于Qt窗口和其他程序窗口的互相嵌入,Qt中有这样一个函数,文档中如此介绍:

[static] QWindow *QWindow::fromWinId(WId id)
Creates a local representation of a window created by another process or by using native libraries below Qt.
Given the handle id to a native window, this method creates a QWindow object which can be used to represent the window when invoking methods like setParent() and setTransientParent().
This can be used, on platforms which support it, to embed a QWindow inside a native window, or to embed a native window inside a QWindow.
If foreign windows are not supported or embedding the native window failed in the platform plugin, this function returns 0.
Note: The resulting QWindow should not be used to manipulate the underlying native window (besides re-parenting), or to observe state changes of the native window. Any support for these kind of operations is incidental, highly platform dependent and untested.
See also setParent() and setTransientParent().

这样,当你使用一个基于QWindow的窗口时,可以通过如下代码将他嵌入到其他Windows窗口中。

	HWND a;//假设这是某个Windows系统中的窗口句柄
	QWindow* p=QWindow::fromWinId(reinterpret_cast<WId>(a));
	this->setParent(p);

但是,QWidget和QWindow是无法直接相互转化的,对于如何将QWidget的内容渲染到QWindow,Qt提供了一个示例,我这个程序中并没有用到所以没继续研究,有这个需求的同学可以查阅QWindow和QBackingStore相关的文档和文章。
Qt提供了QOpenGLWindow这样一个类,而且跟QOpenGLWidget在使用上非常相似,我可以比较容易地将之前的Widget改为Window从而使用上方的方式将窗口嵌入到桌面。

关于找到Windows桌面窗口句柄,我参考的代码中的实现原理大同小异,其中一份代码中给出了解释原理的文章链接Draw Behind Desktop Icons in Windows 8+,我在代码中也按自己的理解写了一部分注释,大家按需阅读吧。

如果想让嵌入桌面的窗口获得鼠标事件,可以通过鼠标钩子实现,此程序就是使用鼠标钩子监听Windows的鼠标消息的。

实现一个动态壁纸通用的部分主要也就是以上的内容了,其他有的没的基本都写到代码注释里了。

最后,欢迎使用此程序,也欢迎评论反馈。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值