DirectX 之上的透明 Qt 窗口

Ade*_*ost 5 directx user-interface qt transparency hud

我想制作一个透明的无框架 QWidget,它看起来像是在另一个 QWidget 之上渲染的。

我的目的是使用DirectXQt在 3D 游戏之上创建一个HUD

到目前为止,在我的努力中,我的 QMainWindow 包含一个自定义的 DirectX-Widget,它是通过在 DirectX 中创建交换链时将普通 QWidget 的 HWND 传递给 DirectX 创建的,然后使用 QTimer 创建自定义渲染循环(请参阅代码以下)。

然后我尝试渲染一个新的叠加层在 QMainWindow 顶部

通过在叠加上使用以下标志,我可以使其行为与我想要的类似,但我仍然无法摆脱框架。

setWindowFlags(Qt::WindowStaysOnBottomHint);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_TransparentForMouseEvents);
Run Code Online (Sandbox Code Playgroud)

左图显示了它真正的样子,借助 MS Paint 的魔力,右图就是想要的样子。

调试图像

正如您从图片中看到的,透明度在 DirectX 小部件之上不起作用,但它似乎在普通小部件(例如工具栏)之上起作用之上起作用,当我尝试使用 QPainter 之类的东西时,情况似乎也是如此而不是 DirectX。

有谁知道为什么会发生这种情况?关于如何摆脱 DirectX 中的框架或实现类似的效果有什么建议吗?


源代码

您可以从此处下载完整的Visual Studio 2010项目项目。

可能需要适用于 Qt4 的 Visual Studio Add-in 1.1.112010 年 6 月的 DirectX SDK如果您想自己编译,

大部分源代码也如下所示。我试图让它尽可能短。

#pragma once

#include <QtGui/QMainWindow>
#include <QtCore/QTimer>
#include "ui_mainwindow.h"
#include "ui_overlay.h"

class DXWidget : public QWidget
{
    Q_OBJECT
private:
    QTimer* timer;
public:
    DXWidget(QWidget* parent) : QWidget(parent){}
    ~DXWidget()
    {
        // dx cleanup
    };
    void init(HWND windowHandle)
    {
        // init DirectX using our HWND as render target
        initDX(windowHandle);

        // start render loop
        timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(render()));
        timer->start(0);
    }
private:
    void initDX(HWND windowHandle)
    {
        // inits DirectX stuff
    }
private slots:
    void render()
    {
        // renders a frame to the Widget using DirectX
    }
};

class Overlay : public QMainWindow
{
    Q_OBJECT
private:
    Ui::Overlay ui;
public:
    Overlay(QWidget* parent) : QMainWindow(parent)
    {
        ui.setupUi(this);
        QWidget::setWindowFlags(Qt::WindowStaysOnBottomHint);
        QWidget::setAttribute(Qt::WA_TranslucentBackground, true);
        show();
        move(6, 50); // move window so we can see it overlapping our toolbar
    };
    ~Overlay()
    {
    };
};


class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    Ui::MainWindowClass ui;
    DXWidget* widget;
public:
    MainWindow()
    {
        // setup window
        ui.setupUi(this);

        // create DirectX-widget
        widget = new DXWidget(this);
        MainWindow::setCentralWidget(widget);

        // hand HWND to DirectXs swap chain so
        // we can draw to that window
        widget->init(widget->winId());

        // create overlay
        new Overlay(this);
    };
};
Run Code Online (Sandbox Code Playgroud)