考虑这段小代码:
import subprocess
import win32gui
import win32con
import time
import sys
from PyQt5.Qt import * # noqa
class Mcve(QMainWindow):
def __init__(self, path_exe):
super().__init__()
menu = self.menuBar()
attach_action = QAction('Attach', self)
attach_action.triggered.connect(self.attach)
menu.addAction(attach_action)
detach_action = QAction('Detach', self)
detach_action.triggered.connect(self.detach)
menu.addAction(detach_action)
self.dock = QDockWidget("Attach window", self)
self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
p = subprocess.Popen(path_exe)
time.sleep(0.5) # Give enough time so FindWindowEx won't return 0
self.hwnd = win32gui.FindWindowEx(0, 0, "CalcFrame", None)
if self.hwnd == 0:
raise Exception("Process not found")
def detach(self):
try:
self._window.setParent(None)
# win32gui.SetWindowLong(self.hwnd, win32con.GWL_EXSTYLE, self._style)
self._window.show()
self.dock.setWidget(None)
self._widget = None
self._window = None
except Exception as e:
import traceback
traceback.print_exc()
def attach(self):
# self._style = win32gui.GetWindowLong(self.hwnd, win32con.GWL_EXSTYLE)
self._window = QWindow.fromWinId(self.hwnd)
self._widget = self.createWindowContainer(self._window)
self.dock.setWidget(self._widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Mcve("C:\\Windows\\system32\\calc.exe")
w.show()
sys.exit(app.exec_())
这里的目标是修复代码,使窗口附加/分离到QDockWidget中时能够正确进行。当前,该代码存在两个重要问题。
问题1
原始窗口的样式出现了问题:
a) 在附加之前(计算器有一个菜单栏)
b) 当附加时(计算器菜单栏消失)
c) 当分离时(菜单栏未正确还原)
我已经尝试使用flags/setFlags qt函数或getWindowLong/setWindowLong,但我在所有尝试中都没有成功
问题2
如果您已经将计算器附加并分离到主窗口,然后决定关闭主窗口,您肯定希望一切(pyqt进程)被正确关闭和清理。现在,这不是这种情况,为什么?
事实上,当您将计算器附加/分离到主窗口时,Python进程将被占用,您需要手动强制终止进程(即ctrl+break conemu,ctrl+c cmd prompt)...这表明代码在父/取消父级关系时没有做正确的事情。
附加注释:
- http://doc.qt.io/qt-5/qwindow.html#fromWinId
- http://doc.qt.io/qt-5/qwidget.html#createWindowContainer
- 在上述最小化代码中,我正在生成calc.exe作为子进程,但您可以假设calc.exe是由explorer.exe生成的现有非子进程。
from PyQt5.Qt import * # noqa
并不是我在创建这个帖子时遇到的主要问题,你有看过我的问题吗?无论如何,感谢你汇报了那篇被抓取的文章。 - BPL