我正在尝试从其他进程中获取一个本机窗口,并将其作为停靠窗口小部件进行管理。
这非常类似于:How to manage separate GUI processes in a Qt application?
我发现以下内容使我很远:https://gist.github.com/torarnv/c5dfe2d2bc0c089910ce
问题是停靠窗口的大小与它要包装的内容的大小不匹配(存在大约15像素宽和40像素高的边距(请参阅示例图片)。
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_()
结果:
应该看起来像:
这里是控制台打印输出,指示每个组件在不同时间的尺寸:
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)
看起来关键是在显示要使用其hwnd的窗口之前,先设置FramelessWindowHint windowFlag。然后一切似乎都按预期工作。