Results 1 to 4 of 4

Thread: Qt5 QWidget::create() with Win32 HWND embedding not working after port from Qt4

  1. #1

    Default Qt5 QWidget::create() with Win32 HWND embedding not working after port from Qt4

    Hi,
    the following code tries to embed a native Win32 HWND of a custom created OpenGL windows into a QWidget using the create method:

    Qt Code:
    1. viewer_widget::viewer_widget(
    2. QWidget* parent,
    3. const viewer::viewer_attributes& view_attrib,
    4. const wm::context::attribute_desc& ctx_attrib,
    5. const wm::surface::format_desc& win_fmt)
    6. : QWidget(parent)
    7. {
    8. setMouseTracking(true);
    9. setFocusPolicy(Qt::StrongFocus);
    10.  
    11. setAttribute(Qt::WA_NativeWindow, true);
    12. setAttribute(Qt::WA_PaintOnScreen, true); // disables qt double buffering (seems X11 only since qt4.5, ...)
    13. setAttribute(Qt::WA_NoSystemBackground, true);
    14. setAutoFillBackground(false);
    15.  
    16. _viewer = make_shared<viewer>(math::vec2ui(100, 100), parent->winId(), view_attrib, ctx_attrib, win_fmt);
    17.  
    18. // ok set the native window as this widgets window...and hold thumbs
    19. QWidget::create(_viewer->window()->window_handle(), true, true);
    20. }
    To copy to clipboard, switch view to plain text mode 

    The viewer creates a native Win32 (or X11) window wit the parent of the QWidget as a parent. It also creates and initializes an OpenGL context. This was/is done for more control over the context creation and live time (I know that Qt5 is much improved in that regard). The QWidget::create() method now takes the HWND of the native window and embeds it into the current QWidget, so that event handling is completely done through Qt.

    This works perfectly on Qt4 (latest used is Qt 4.8.6 x64 on Windows 7/8.1 x64 on Visual Studio 2013).

    Now when porting to Qt5 the same code should still work according to the Qt5 documentation. It required minor changes to account for the change in the WId type. The QWidget::winId() methods still return the native HWND handles of the widgets, which I verified using spyxx.exe (Visual Studio Tools).

    However, the code does not work anymore (using Qt 5.4.0 x64 on Windows 7/8.1 x64 on Visual Studio 2013). The native window is just not embedded. In Qt4 when inspecting the created QWidget its native handle (winId) after the create call was identical to the native HWND, which meant the embedding worked. Now using Qt5 the QWidget contains its own HWND which I could again confirm using spyxx.exe. Now there is the parent widget/window and two child widgets/windows where there should only be one child (the native one). I looked at the source code of the create() method for both Qt versions and I do not understand why it is not working anymore.

    Ok, after the first night trying to figure this out I tried several other methods I could find on forums or the documentation:

    QWindow::fromWinId(HWND) and QWidget::createWindowContainer(QWindow): This one seems to be the way Qt-Devs want me to do it:
    Qt Code:
    1. _viewer = make_shared<viewer>(math::vec2ui(100, 100), par_hndl, view_attrib, ctx_attrib, win_fmt);
    2. QWindow* native_wnd = QWindow::fromWinId((WId)_viewer->window()->window_handle());
    3. QWidget* native_wdgt = QWidget::createWindowContainer(native_wnd);
    4.  
    5. QHBoxLayout* lo = new QHBoxLayout(this);
    6. lo->setContentsMargins(0, 0, 0, 0);
    7. lo->addWidget(native_wdgt);
    To copy to clipboard, switch view to plain text mode 

    This at least at least behaves almost the way I expect. I see my window and in the newly created widget the native window is embedded. BUT: I have found no way to get any mouse events/input from that newly created widget. I added an eventFilter without luck. I tried a QStackedLayout with a transparent top-level widget to catch the input, but this does not work as the widget created through createWindowContainer() is always on top of the windows stack. I tries creating a QWindow-derived class to intercept the nativeEvent() invocation, without luck...

    I am at the end of my ideas to get this working as with Qt4. Is there anything I can to differently to get the old behavior back? The keyboard input I can track through the parent widget using a Qt::StrongFocus policy but the mouse input in complete swallows by the native window. I cannot move the the Qt5 OpenGL window code and need to use our custom OpenGL context tools as we are doing things with the contexts that Qt5 still does not fully support.

    I could not yet try Qt5 on Linux, but the Qt4 code as seen above did work there.

    I also asked the same question on StackOverflow: http://stackoverflow.com/questions/2...-after-port-fr

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,420
    Thanks
    37
    Thanked 1,545 Times in 1,495 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Qt5 QWidget::create() with Win32 HWND embedding not working after port from Qt4

    Have you tried handling the events in the foreign window itself?
    Since it is not part of Qt's windows the application is not notified about events sent to it by the window system, but it should receive them.

    Another technique to integrate different OpenGL renderers with each other is to have one render into a frame buffer object and the other one rendering that into the visible scene.

    Cheers,
    _

  3. #3

    Default Re: Qt5 QWidget::create() with Win32 HWND embedding not working after port from Qt4

    Hi,
    I thought about that. However, since this viewer will create a windows on Win32 and X11 I hoped to get the QWidget::create() version working again as it allows me to handle the input through Qt independent of the windowing system.

    Is there anything that changed for the QWidget::create() method with Qt5 that I am unaware of?

    Regards
    -chris

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,420
    Thanks
    37
    Thanked 1,545 Times in 1,495 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Qt5 QWidget::create() with Win32 HWND embedding not working after port from Qt4

    The platform abstraction works differently in Qt5, e.g. only top level windows have a native handle now as far as I know.

    The mechanism of QWindow::fromWinId() was primarily designed to embed windows created by other processes (so called foreign windows), which usually have their own event handling (different application, different event loop).

    Since this is all pretty low level you might want to check with the Qt development list.

    Cheers,
    _

Similar Threads

  1. HWND on Win32 API to Qt widget
    By delio in forum Newbie
    Replies: 8
    Last Post: 30th March 2014, 16:29
  2. hwnd to qwidget setparent error
    By cic in forum Qwt
    Replies: 1
    Last Post: 27th August 2013, 15:40
  3. win32 API serial port in Qt4
    By jakr13 in forum Newbie
    Replies: 5
    Last Post: 15th February 2013, 10:33
  4. Create a QWidget as child of a Win32 window
    By BenPa in forum Qt for Embedded and Mobile
    Replies: 1
    Last Post: 29th March 2011, 15:35
  5. Embedding SDL in a QWidget That is not a Window
    By PhilippB in forum Qt Programming
    Replies: 0
    Last Post: 21st August 2008, 12:17

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.