QWidget overlay stops responding after HWND parent minimizes/restores



  • I know mixing Qt and native Win32 spells trouble, but controlling a transparent QWidget on top of a another program is just cool.
    The example code puts a button and movable ellipse in a QGraphicsScene and sets notepad as its parent HWND.
    It works great untill notepad is minimized/restored. The overlay shows up, but does not respond anymore to (mouse) events.
    How to avoid this issue?

    Running Windows 7x64/Aero

    mainwindow.h
    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QMainWindow>
    #include <QWidget>
    #include <QtWidgets>
    #include <QDebug>
    #include <windows.h>

    class Overlay : public QWidget
    {
    Q_OBJECT
    public:
    explicit Overlay(QWidget *parent = 0) {
    UNREFERENCED_PARAMETER(parent);
    scene = new QGraphicsScene(this);
    view = new QGraphicsView(this);
    view->setScene(scene);
    view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    if (!FindParentHwnd()) return;
    Reposition();
    TransparentThis();
    setVisible(true);
    HookHwnd();
    InitItems();
    view->setVisible(true);
    }

    void TransparentThis() {
    this->setAttribute(Qt::WA_NoSystemBackground, true);
    this->setAttribute(Qt::WA_TranslucentBackground, true);
    this->setAttribute(Qt::WA_ShowWithoutActivating);
    this->setStyleSheet("background-color: transparent");
    view->setFrameShape(QFrame::NoFrame);
    this->setAutoFillBackground(true);
    this->setWindowFlags(Qt::FramelessWindowHint| Qt::WindowDoesNotAcceptFocus);
    }

    void InitItems() {
    ellipse = new QGraphicsEllipseItem(0, 0, 100, 50);
    QBrush redBrush(QColor(255, 0, 0, 128));
    QPen blackPen(Qt::black);
    blackPen.setWidth(2);
    ellipse->setBrush(redBrush);
    ellipse->setPen(blackPen);
    ellipse->setFlag(QGraphicsItem::ItemIsMovable);
    ellipse->setScale(1);
    scene->addItem(ellipse);

    stats = new QPushButton("Button");
    stats->setGeometry(QRect(0, 0, 45, 20));
    stats->setMaximumSize(QSize(45, 20));
    scene->addWidget(stats);
    }

    bool FindParentHwnd()
    {
    ParentHwnd = FindWindow(NULL, L"Untitled - NotePad");
    if (!ParentHwnd) {
    qDebug() << "Failed to Find Window";
    return false;
    }
    return true;
    }

    bool HookHwnd()
    {
    LONG RetValue = SetWindowLong((HWND)effectiveWinId(), GWL_HWNDPARENT,(LONG)ParentHwnd);
    if (GetLastError() && !RetValue)
    {
    qDebug() << QString("Overlay failed for window: %1, Error: %2").arg((DWORD)ParentHwnd).arg(GetLastError());
    return false;
    }
    qDebug() << QString("Overlay attached to window: %1").arg((DWORD)ParentHwnd);
    return true;
    }

    void Reposition()
    {
    RECT lpRect;
    POINT client_top_left = { 0, 0 };
    GetClientRect(ParentHwnd, &lpRect);
    ClientToScreen(ParentHwnd, &client_top_left);
    resize(lpRect.right - lpRect.left, lpRect.bottom - lpRect.top);
    move(client_top_left.x, client_top_left.y);
    }

    private:
    QGraphicsScene * scene;
    QGraphicsView * view;
    QGraphicsEllipseItem *ellipse;
    QPushButton *stats;
    HWND ParentHwnd;
    QRect RectParent;

    protected:
    void resizeEvent(QResizeEvent* event) {
    view->resize(event->size());
    view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
    }
    void showEvent(QShowEvent* event) {
    UNREFERENCED_PARAMETER(event);
    scene->setSceneRect(view->viewport()->rect());
    }

    };

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

    private:
    Ui::MainWindow *ui;
    };

    #endif // MAINWINDOW_H
    @

    main.cpp

    @#include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QApplication>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Overlay O;
    MainWindow w;
    w.show();
    return a.exec();
    }

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);
    }

    MainWindow::~MainWindow()
    {
    delete ui;
    }
    @


  • Moderators

    Hi, and welcome to the Qt Dev Net!

    I'm afraid I don't know how to solve your particular problem, but I do know that there are multiple other issues related to interacting with foreign windows in Qt. Here's a compilation of issues I've found: https://bugreports.qt-project.org/browse/QTBUG-40320

    Numerous other users have asked for help with working with foreign windows too, so we know that there is demand for such features. If you're willing to open a new bug report at https://bugreports.qt-project.org/ and refer to the one above, that will help build a picture of what developers are looking for. Hopefully, this will lead to better support for foreign windows.



  • Thanks.

    Realizing it might be a bug I came across this report:

    https://bugreports.qt-project.org/browse/QTBUG-38856

    The suggested QAbstractNativeEventFilter/WM_SHOWWINDOW workaround might just work for me.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.