[Interest] QML and window handles (MS windows)

Constantin Makshin cmakshin at gmail.com
Mon May 27 05:32:13 CEST 2013


It's very likely that you try to do something QGraphics[Proxy]Widget wasn't
designed to do as it relies on the fact that Qt draws widgets by itself
instead of creating native widgets/controls (except top-level ones, of
course).

In your "pure QWidget" application Qt, while drawing widgets by itself, is
still able to create a native handle which can be used as a parent for the
embedded window, delegating all repainting job to it.

But QGraphics[Proxy]Widgets completely rely on painting performed by
QWidget-s, making it possible to embed them even in 3D scenes (you can
google for the demo where QWidget-s were placed on walls of a 3D maze
without losing any of their functionality). But drawing into an off-screen
buffer makes it impossible to embed system's native widgets as Qt can't
interact (things like sending input events and getting contents for
drawing) with them being hidden, and Qt has to hide these widgets, because
otherwise it would ruin the whole idea of QGraphicsItem's independence from
output destination (screen, simple off-screen buffer, texture, etc.).

P.S.: And the idea of clearing bits in a number by using subtraction is not
only strange, but also dangerous -- if the corresponding bit is already
equal to zero, you'll get not what you want.
On May 27, 2013 6:08 AM, "Ruediger Norbert" <ruediger.norbert at gmx.net>
wrote:

> Dear all,
>
> what I try to do is catching the main window of an existing application
> (running on MS Windows 7) and embedding it into a QWidget. This works fine
> using pure Qt, e.g., to "steal" the window of a blank notepad.exe (with
> window title "Unbenannt - Editor" in German), the C++ source code shown as
> QtTest.cxx below does the trick.
>
> If I try to do essentially the same with a QWidget wrapped as
> QDeclarativeItem for use in QML, this approach does not work - see
> QmlTest.cxx, QmlTest.qml, WidgetWrapper.h and WidgetWrapper.cxx below.
> "Does not work" means that the notepad instance gets embedded somewhere
> (the original notepad window disappears, process still in task manager),
> but it is not embedded into the wrapped QWidget - it is not visible
> anymore, possibly embedded in some invisible window.
>
> Can you help me further? It would be very important for me to understand
> why my window-steal-approach is not working with the wrapped QWidget in QML
> setup. Is there a solution for my problem or do I try something which is
> per definition not possible using QML? What happens with the window handle
> of the wrapped Qt QWidget as soon as loaded into the QML rect?
>
> Thanks.
>
> RĂ¼diger
>
> <<start//QtTest.cxx>>
> #include <QApplication>
>
> #include <QWidget>
>
> #include <iostream>
>
> #include <Windows.h>
>
>
>
> int main(int argc, char *argv[])
>
> {
>
>   QApplication app(argc, argv);
>
>     QWidget *widget = new QWidget();
>
>   widget->setGeometry(0, 0, 600, 280);
>
>   widget->setStyleSheet("background-color:red;");
>
>   widget->show();
>
>
>
>   HWND hnotepad;
>
>   if (hnotepad = FindWindow("Notepad", "Unbenannt - Editor"))
>
>   {
>
>     LONG wstyle = GetWindowLong(hnotepad, GWL_STYLE);
>
>     if (!wstyle)
>
>       return 1;
>
>     wstyle -= WS_CAPTION;
>
>     wstyle -= WS_BORDER;
>
>     wstyle -= WS_OVERLAPPED;
>
>     wstyle -= WS_THICKFRAME;
>
>     if (!SetWindowLong(hnotepad, GWL_STYLE, wstyle))
>
>       return 1;
>
>
>
>     SetParent(hnotepad, widget->winId()); // embed notepad into QWidget
>
>
>
>     SendMessage(widget->winId(), WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
>
>     ShowWindow(hnotepad, SW_MAXIMIZE);
>
>     UpdateWindow(hnotepad);
>
>
>
>     SetWindowLong(widget->winId(), GWL_STYLE, GetWindowLong(widget->winId(), GWL_STYLE) | WS_CLIPCHILDREN);
>
>     SetForegroundWindow(hnotepad);
>
>   }
>
>   else
>
>   {
>
>     std::cerr << "notepad not found\n";
>
>     return 1;
>
>   }
>
>
>
>   return app.exec();
>
> }
>
> <<end//QtTest.cxx>>
>
>
> <<start//QmlTest.cxx>>
> #include <QApplication>
>
> #include <iostream>
>
> #include "WidgetWrapper.h"
>
> #include "qmlapplicationviewer.h"
>
>
>
> int main(int argc, char *argv[])
>
> {
>
>   QApplication app(argc, argv);
>
>
>
>   qmlRegisterType<WidgetWrapper>("MyWidgets", 1, 0, "WidgetWrapper");
>
>
>
>   QmlApplicationViewer viewer;
>
>   viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
>
>   viewer.setMainQmlFile(QLatin1String("QmlTest.qml"));
>
>   viewer.showExpanded();
>
>
>
>   QObject *startItem = viewer.rootObject()->findChild<QObject*>("startItem");
>
>   if (startItem)
>
>   {
>
>     QVariant returnedValue;
>
>     QMetaObject::invokeMethod(startItem, "start", Q_RETURN_ARG(QVariant, returnedValue));
>
>     return app.exec();
>
>   }
>
>   return 1;
>
> }
>
>  <<end//QmlTest.cxx>>
>
>
> <<start//QmlTest.qml>>
> import QtQuick 1.1
>
> import MyWidgets 1.0
>
>
>
> Rectangle {
>
>   id: mainWindow
>
>   width: 600
>
>   height: 280
>
>
>
>   WidgetWrapper {
>
>     id: displayWidget
>
>     anchors.fill: parent
>
>   }
>
>
>
>   Item { /* Helper for starting up the applicationn */
>
>     id: startItem
>
>     objectName: "startItem"
>
>
>
>     function start()
>
>     {
>
>       startTimer.start();
>
>     }
>
>   }
>
>
>
>   Timer {
>
>     id: startTimer
>
>     objectName: "startTimer"
>
>     interval: 10
>
>     onTriggered: {
>
>       stop();
>
>       displayWidget.embedNotepad()
>
>     }
>
>   }
>
> }
>
>  <<end//QmlTest.qml>>
>
>
> <<start//WidgetWrapper.h>>
> #ifndef WIDGETWRAPPER_H
>
> #define WIDGETWRAPPER_H
>
>
>
> #include <QDeclarativeItem>
>
> #include <QGraphicsProxyWidget>
>
>
>
> class WidgetWrapper : public QDeclarativeItem
>
> {
>
>   Q_OBJECT
>
> public:
>
>   WidgetWrapper(QDeclarativeItem* parent = 0);
>
>   Q_PROPERTY(int windowID READ getWindowID NOTIFY windowIDChanged)
>
>   int getWindowID();
>
> public slots:
>
>   void embedNotepad();
>
> signals:
>
>   void windowIDChanged();
>
> protected:
>
>   QGraphicsProxyWidget *proxy;
>
>   QWidget *widget;
>
>   virtual void componentComplete();
>
> };
>
>
>
> QML_DECLARE_TYPE(WidgetWrapper)
>
>
>
> #endif // WIDGETWRAPPER_H
>
>  <<end//WidgetWrapper.h>>
>
>
>  <<start//WidgetWrapper.cxx>>
> #include "WidgetWrapper.h"
>
> #include <iostream>
>
> #include <Windows.h>
>
>
>
> WidgetWrapper::WidgetWrapper(QDeclarativeItem *parent)
>
>   : QDeclarativeItem(parent)
>
> {
>
>   widget = new QWidget();
>
>   widget->setStyleSheet("background-color:red;");
>
>   widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
>
>   proxy = new QGraphicsProxyWidget(this);
>
>   proxy->setWidget(widget);
>
>   proxy->setPos(-widget->sizeHint().width() / 2, -widget->sizeHint().height() / 2);
>
> }
>
>
>
> int WidgetWrapper::getWindowID()
>
> {
>
>   return reinterpret_cast<int>(widget->winId());
>
> }
>
>
>
> void WidgetWrapper::embedNotepad()
>
> {
>
>   HWND hnotepad;
>
>   if (hnotepad = FindWindow("Notepad", "Unbenannt - Editor"))
>
>   {
>
>     LONG wstyle = GetWindowLong(hnotepad, GWL_STYLE);
>
>     if (!wstyle)
>
>       return;
>
>     wstyle -= WS_CAPTION;
>
>     wstyle -= WS_BORDER;
>
>     wstyle -= WS_OVERLAPPED;
>
>     wstyle -= WS_THICKFRAME;
>
>     if (!SetWindowLong(hnotepad, GWL_STYLE, wstyle))
>
>       return;
>
>
>
>     SetParent(hnotepad, widget->winId()); // embed notepad into QWidget
>
>
>
>     SendMessage(widget->winId(), WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
>
>     ShowWindow(hnotepad, SW_MAXIMIZE);
>
>     UpdateWindow(hnotepad);
>
>
>
>     SetWindowLong(widget->winId(), GWL_STYLE, GetWindowLong(widget->winId(), GWL_STYLE) | WS_CLIPCHILDREN);
>
>     SetForegroundWindow(hnotepad);
>
>   }
>
>   else
>
>   {
>
>     std::cout << "notepad not found\n";
>
>   }
>
> }
>
>
>
> void WidgetWrapper::componentComplete()
>
> {
>
>   QRect geom = widget->geometry();
>
>   geom.setWidth(this->parentItem()->width());
>
>   geom.setHeight(this->parentItem()->height());
>
>   widget->setGeometry(geom);
>
>   QDeclarativeItem::componentComplete();
>
> }
>
>  <<end//WidgetWrapper.cxx>>
>
>
> _______________________________________________
> Interest mailing list
> Interest at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20130527/6484b241/attachment.html>


More information about the Interest mailing list