Embedding native windows inside QDockWidget

醉酒当歌 提交于 2021-01-29 08:48:04

问题


I am trying to take a native window from an other process and manage it as a docking widget in my process.

This is very similar to: How to manage separate GUI processes in a Qt application?

I have found the following which gets me pretty far: https://gist.github.com/torarnv/c5dfe2d2bc0c089910ce

Problem is the dock window size does not match the size of the contents it's wrapping (there is a margin which it about 15px wide and 40px tall (see pictures for examples)).

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import Qt
import logging

envent_type_lookup = {v:k for k,v in QtCore.QEvent.__dict__.items() if isinstance(v, int)}

class DockingWindowProxy(QtWidgets.QDockWidget):
    def __init__(self, hwnd,  *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.window_wrapper = QtGui.QWindow.fromWinId(hwnd)
        print('fromWinId window size', self.window_wrapper.size())
        self.window_widget = QtWidgets.QWidget.createWindowContainer(self.window_wrapper)
        self.setWindowTitle("Wrapper")
        print('windowContainer widget size', self.window_widget.size())
        self.setWidget(self.window_widget)
        print('dock widget size', self.size())
        self.installEventFilter(self)

    def eventFilter(self, obj, ev):
        print(f"{envent_type_lookup[ev.type()]} \t {self.window_wrapper.size()}, {self.window_widget.size()}")
        return False


if __name__ == '__main__':
    import win32gui
    logging.basicConfig(level=logging.DEBUG)
    app = QtWidgets.QApplication([])

    sample = QtWidgets.QPushButton("Test")
    sample.show()
    print('Original window size', sample.size())
    w = sample.window()
    hwnd = w.winId().__int__()

    pw = DockingWindowProxy(hwnd)
    pw.show()

    app.exec_()

Results:

Should look like:

Here are the console print outputs indicating the sizes each component has at various times:

Original window size PyQt5.QtCore.QSize(75, 23)
fromWinId window size PyQt5.QtCore.QSize(120, 23)
windowContainer widget size PyQt5.QtCore.QSize(640, 480)
dock widget size PyQt5.QtCore.QSize(640, 480)
PlatformSurface      PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
WinIdChange      PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
WindowIconChange     PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Polish   PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Move     PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)
Resize   PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(200, 100)
Show     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
CursorChange     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ShowToParent     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
PolishRequest    PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
LayoutRequest    PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
UpdateLater      PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
UpdateRequest    PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
WindowActivate   PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ActivationChange     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
InputMethodQuery     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ShortcutOverride     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
KeyPress     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
WindowDeactivate     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)
ActivationChange     PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)

回答1:


Looks like the key issue was to set the FramelessWindowHint windowFlag BEFORE showing the window whose hwnd will be used. Then everything appears to work as expected.



来源:https://stackoverflow.com/questions/60381894/embedding-native-windows-inside-qdockwidget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!