在 QDockWidget 中嵌入本机窗口 [英] Embedding native windows inside QDockWidget

查看:57
本文介绍了在 QDockWidget 中嵌入本机窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从其他进程中获取本机窗口,并将其作为我的进程中的停靠小部件进行管理.

这非常类似于:

应该是这样的:

以下是控制台打印输出,指示每个组件在不同时间的大小:

原始窗口大小 PyQt5.QtCore.QSize(75, 23)fromWinId 窗口大小 PyQt5.QtCore.QSize(120, 23)windowContainer 小部件大小 PyQt5.QtCore.QSize(640, 480)停靠小部件大小 PyQt5.QtCore.QSize(640, 480)平台表面 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)波兰语 PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)移动 PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(640, 480)调整 PyQt5.QtCore.QSize(136, 62), PyQt5.QtCore.QSize(200, 100)显示 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)波兰请求 PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)LayoutRequest PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)更新后期 PyQt5.QtCore.QSize(200, 100), PyQt5.QtCore.QSize(200, 100)更新请求 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)按键 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)

解决方案

看起来关键问题是在显示将使用其 hwnd 的窗口之前设置 FramelessWindowHint windowFlag.然后一切似乎都按预期工作.

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)

解决方案

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.

这篇关于在 QDockWidget 中嵌入本机窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆