DirectX顶部的透明Qt窗口

DirectX顶部的透明Qt窗口,qt,user-interface,directx,transparency,hud,Qt,User Interface,Directx,Transparency,Hud,我想制作一个透明的无框QWidget,它看起来像是在另一个QWidget上渲染的。 我的意图是使用DirectX和Qt在3D游戏的基础上创建一个HUD 在我迄今为止的工作中,我的QMainWindow包含一个定制的DirectX小部件,它是在DirectX中创建交换链时将普通QWidget的HWND交给DirectX创建的,然后使用QTimer创建自定义渲染循环(请参见下面的代码) 然后,我尝试在QMainWindow的顶部渲染一个新的覆盖-小部件(我想要的HUD),并使其看起来像是主窗口的一部

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

我的意图是使用DirectX和Qt在3D游戏的基础上创建一个HUD

在我迄今为止的工作中,我的QMainWindow包含一个定制的DirectX小部件,它是在DirectX中创建交换链时将普通QWidget的HWND交给DirectX创建的,然后使用QTimer创建自定义渲染循环(请参见下面的代码)

然后,我尝试在QMainWindow的顶部渲染一个新的覆盖-小部件(我想要的HUD),并使其看起来像是主窗口的一部分

通过在覆盖层上使用以下标志,我可以使其与我想要的行为类似,但我仍然无法摆脱帧。

setWindowFlags(Qt::WindowStaysOnBottomHint);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_TransparentForMouseEvents);
图像显示了它的真实外观,借助MS Paint的魔力,图像就是我想要的样子

从图片中可以看出,透明度在DirectX小部件上不起作用,但在普通小部件(如工具栏)上起作用,当我尝试使用QPaint而不是DirectX时,情况也是如此

有人知道为什么会这样吗?关于如何摆脱DirectX中的框架或实现类似功能,有什么建议吗


源代码

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

如果您想自己编译,可能需要针对Qt4和2010年6月DirectX SDK的Visual Studio插件1.1.11

大部分源代码也显示在下面。我尽量把它缩短

#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);
    };
};
#pragma一次
#包括
#包括
#包括“ui_main window.h”
#包括“ui_overlay.h”
类DXWidget:publicqwidget
{
Q_对象
私人:
QTimer*定时器;
公众:
DXWidget(QWidget*父对象):QWidget(父对象){}
~DXWidget()
{
//dx清理
};
void init(HWND windowHandle)
{
//使用HWND作为渲染目标初始化DirectX
initDX(窗口句柄);
//开始渲染循环
计时器=新的QTimer(此);
连接(计时器、信号(超时())、此、插槽(渲染());
定时器->启动(0);
}
私人:
void initDX(HWND windowHandle)
{
//inits DirectX的东西
}
专用插槽:
void render()
{
//使用DirectX向小部件呈现帧
}
};
类覆盖:公共QMainWindow
{
Q_对象
私人:
Ui::覆盖Ui;
公众:
覆盖(QWidget*父项):QMainWindow(父项)
{
ui.setupUi(这个);
QWidget::setWindowFlags(Qt::WindowStaysOnBottomHint);
QWidget::setAttribute(Qt::WA_半透明背景,true);
show();
移动(6,50);//移动窗口以便我们可以看到它与工具栏重叠
};
~Overlay()
{
};
};
类主窗口:公共QMainWindow
{
Q_对象
私人:
Ui::MainWindowClass Ui;
DXWidget*widget;
公众:
主窗口()
{
//设置窗口
ui.setupUi(这个);
//创建DirectX小部件
widget=新的DXWidget(本);
主窗口::setCentralWidget(小部件);
//将HWND交给DirectXs交换链so
//我们可以拉到那个窗口
widget->init(widget->winId());
//创建覆盖
新覆盖层(本);
};
};

嗨!你想出解决办法了吗?@jungle\u mole我不推荐,但在我们制作的游戏中,我基本上把叠加作为一个单独的QMainWindow,在每次移动时重新调整叠加,或者从主窗口调整事件大小。它成功了,但我不能说它是否能在一个严肃的项目中持续下去。这不是我写过的最好的代码,但如果您想看一看(根据自己的判断使用),我认为这些是最相关的类: