Qt/C++实现Windows 11桌面图标与壁纸间绘制窗口的问题
在Windows桌面图标与壁纸之间绘制Qt窗口的问题
问题描述
我尝试使用Qt和C++在Windows桌面的图标与壁纸之间绘制一个窗口,使其成为壁纸的一部分。编写了简化版程序,创建了一个处于非活动状态、始终在后台且不捕获输入的窗口,尺寸与位置匹配第一个屏幕:
#include <QApplication> #include <QScreen> #include <QWindow> #include <Windows.h> #include <QPainter> #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QRect geometry, QWidget* parent = nullptr): QMainWindow(parent) { setGeometry(geometry); setWindowFlags( Qt::FramelessWindowHint | Qt::WindowTransparentForInput | Qt::WindowStaysOnBottomHint ); HWND hWnd = (HWND)winId(); LONG_PTR exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE); SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE); } ~MainWindow(){} protected: void paintEvent(QPaintEvent*) { QPainter painter(this); painter.fillRect(geometry(), QColor(0, 50, 120)); } }; int main(int argc, char* argv[]) { QApplication a(argc, argv); MainWindow w(a.screens().at(0)->geometry()); w.show(); return a.exec(); }
但问题是,尽管该窗口位于所有窗口下方且允许输入穿透(包括桌面右键点击),它仍显示在桌面图标上方。
尝试的解决方案
参考相关资料后,我写出了以下获取壁纸HWND并关联Qt窗口的代码:
// 两个函数来自参考资料 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { HWND p = FindWindowEx(hwnd, NULL, L"SHELLDLL_DefView", NULL); HWND* ret = (HWND*)lParam; if (p) { // 获取当前窗口之后的WorkerW窗口 *ret = FindWindowEx(NULL, hwnd, L"WorkerW", NULL); } return true; } HWND get_wallpaper_window() { // 获取Progman窗口 HWND progman = FindWindow(L"ProgMan", NULL); // 向Progman发送0x052C消息,使其在桌面图标后生成WorkerW窗口(已存在则无操作) SendMessageTimeout(progman, 0x052C, 0, 0, SMTO_NORMAL, 1000, nullptr); // 枚举所有窗口,找到包含SHELLDLL_DefView子窗口的窗口,然后获取其下一个WorkerW兄弟窗口 HWND wallpaper_hwnd = nullptr; EnumWindows(EnumWindowsProc, (LPARAM)&wallpaper_hwnd); // 返回目标窗口句柄 return wallpaper_hwnd; } // 我的代码 int main(int argc, char *argv[]) { QApplication a(argc, argv); HWND wallpaper_hwnd = get_wallpaper_window(); QWindow* wallpaper_window = QWindow::fromWinId((WId)wallpaper_hwnd); QWidget* wallpaper_widget = QWidget::createWindowContainer(wallpaper_window); MainWindow w(a.screens().at(0)->geometry(), wallpaper_widget); w.show(); return a.exec(); }
但程序无视觉效果,窗口不显示但未崩溃,我怀疑错误使用了get_wallpaper_window返回的HWND。
补充信息
wallpaper_window的几何参数(x, y, width, height)为1200, 720, 160, 160wallpaper_widget的几何参数为0, 0, 640, 480- 我的显示器几何参数为0, 0, 1600, 2560
- 未关联壁纸作为父窗口的第一版代码中,点击窗口时桌面图标会短暂显示在窗口上方
后续发现
相关内容显示,我想要的实现方式可能不可行,应该子类化ListView以拦截其WM_ERASEBKGND和WM_PAINT消息,这可能无法使用Qt实现,我将研究具体方法。
内容的提问来源于stack exchange,提问作者evamiaou
相关产品推荐
相关产品推荐

