5

I want to make a transparent frame-less QWidget which looks like it is being rendered on top of another QWidget.

My intention is to create a HUD on top of a 3D-game using DirectX and Qt.

In my efforts so far my QMainWindow contains a custom made DirectX-Widget, which is created by handing the HWND of an ordinary QWidget to DirectX when creating the swap chain in DirectX, and then creating a custom render loop by using a QTimer (see code below).

I then try to render a new Overlay-widget (my intended HUD) on top of the QMainWindow and make it appear like it is part of the main window.

By using the following flags on the Overlay I can make it behave similarly to what I want, but I still can't get rid off the frame.

setWindowFlags(Qt::WindowStaysOnBottomHint);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_TransparentForMouseEvents);

The left image shows what it really looks like, and by the magic of MS Paint the right image is how I would like it to be.

Debug image

As you can see from the picture the transparency does not work on top of the DirectX-widget, but it appears to be working on top of ordinary Widgets such as the toolbar, and the same appears to be true when I experimented using something like QPainter instead of DirectX.

Does anyone know why this is happening? Any suggestions on how to get rid of the frame in DirectX or to achieve something similar?


Source code

You can download the full Visual Studio 2010 project from here.

Probably requires Visual Studio Add-in 1.1.11 for Qt4 and June 2010 DirectX SDK if you want to compile it yourself.

Most of the source code is also shown below. I tried to make it as short as possible.

#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);
    };
};
Adelost
  • 2,343
  • 2
  • 23
  • 28
  • hi! have you come up with solution? – jungle_mole Mar 01 '17 at 08:51
  • @jungle_mole I don't recommend it, but in the game we made I basically had the Overlay as a separate QMainWindow, readjusted the Overlay on every Move or Resize event from the MainWindow. It worked, but I can't say if it will hold in a serious project. It's not the best code that I've written, but I think these are the most relevant classes if you want to have a look (use at your own discretion): https://github.com/L0mion/xkill-source/blob/08709ac9cff31b4b1dd05a1aff3884fa4def3a90/xkill-gui/Menu_Main.cpp https://github.com/L0mion/xkill-source/blob/master/xkill-gui/Menu_HUD.cpp – Adelost Mar 01 '17 at 13:08

0 Answers0