Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 377e991

Browse files
Merge remote-tracking branch 'iron/master'
2 parents 6daff6b + 920ce5b commit 377e991

File tree

5 files changed

+113
-8
lines changed

5 files changed

+113
-8
lines changed

‎.pydevproject‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<?eclipse-pydev version="1.0"?><pydev_project>
3-
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Python35</pydev_property>
4-
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
5-
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
6-
<path>/${PROJECT_DIR_NAME}</path>
7-
</pydev_pathproperty>
8-
</pydev_project>
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<?eclipse-pydev version="1.0"?><pydev_project>
3+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
4+
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 3.0</pydev_property>
5+
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
6+
<path>/${PROJECT_DIR_NAME}</path>
7+
</pydev_pathproperty>
8+
</pydev_project>

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
- [1.20 exec()动态生成控件](partner_625781186/1.exec动态生成控件/)
2828
- [1.21 仿QQ设置面板](仿QQ设置面板/)
2929
- [1.22 Json生成QTreeWidget](Json生成QTreeWidget/)
30+
- [1.23 嵌入外部窗口](嵌入外部窗口/)
3031

3132

3233
### [2.QGraphicsView练习](QGraphicsView练习/)

‎嵌入外部窗口/EmbedWidget.py‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
from PyQt5.QtGui import QWindow
2+
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QListWidget,\
3+
QLabel
4+
import win32con
5+
import win32gui
6+
7+
8+
class Window(QWidget):
9+
10+
def __init__(self, *args, **kwargs):
11+
super(Window, self).__init__(*args, **kwargs)
12+
self.resize(800, 600)
13+
layout = QVBoxLayout(self)
14+
15+
self.myhwnd = int(self.winId()) # 自己的句柄
16+
17+
layout.addWidget(QPushButton('获取所有可用、可视窗口', self,
18+
clicked=self._getWindowList, maximumHeight=30))
19+
layout.addWidget(
20+
QLabel('双击列表中的项目则进行嵌入目标窗口到下方\n格式为:句柄|父句柄|标题|类名', self, maximumHeight=30))
21+
self.windowList = QListWidget(
22+
self, itemDoubleClicked=self.onItemDoubleClicked, maximumHeight=200)
23+
layout.addWidget(self.windowList)
24+
25+
def closeEvent(self, event):
26+
"""窗口关闭"""
27+
if self.layout().count() == 4:
28+
self.restore()
29+
super(Window, self).closeEvent(event)
30+
31+
def _getWindowList(self):
32+
"""清空原来的列表"""
33+
self.windowList.clear()
34+
win32gui.EnumWindows(self._enumWindows, None)
35+
36+
def onItemDoubleClicked(self, item):
37+
"""列表双击选择事件"""
38+
# 先移除掉item
39+
self.windowList.takeItem(self.windowList.indexFromItem(item).row())
40+
hwnd, phwnd, _, _ = item.text().split('|')
41+
# 开始嵌入
42+
43+
if self.layout().count() == 4:
44+
# 如果数量等于4说明之前已经嵌入了一个窗口,现在需要把它释放出来
45+
self.restore()
46+
hwnd, phwnd = int(hwnd), int(phwnd)
47+
# 嵌入之前的属性
48+
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
49+
exstyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
50+
print('save', hwnd, style, exstyle)
51+
52+
widget = QWidget.createWindowContainer(QWindow.fromWinId(hwnd))
53+
widget.hwnd = hwnd # 窗口句柄
54+
widget.phwnd = phwnd # 父窗口句柄
55+
widget.style = style # 窗口样式
56+
widget.exstyle = exstyle # 窗口额外样式
57+
self.layout().addWidget(widget)
58+
59+
def restore(self):
60+
"""归还窗口"""
61+
# 有bug,归还后窗口没有了WS_VISIBLE样式,不可见
62+
widget = self.layout().itemAt(3).widget()
63+
print('restore', widget.hwnd, widget.style, widget.exstyle)
64+
win32gui.SetParent(widget.hwnd, widget.phwnd) # 让它返回它的父窗口
65+
win32gui.SetWindowLong(
66+
widget.hwnd, win32con.GWL_STYLE, widget.style | win32con.WS_VISIBLE) # 恢复样式
67+
win32gui.SetWindowLong(
68+
widget.hwnd, win32con.GWL_EXSTYLE, widget.exstyle) # 恢复样式
69+
win32gui.ShowWindow(
70+
widget.hwnd, win32con.SW_SHOW) # 显示窗口
71+
widget.close()
72+
self.layout().removeWidget(widget) # 从布局中移出
73+
widget.deleteLater()
74+
75+
def _enumWindows(self, hwnd, _):
76+
"""遍历回调函数"""
77+
if hwnd == self.myhwnd:
78+
return # 防止自己嵌入自己
79+
if win32gui.IsWindow(hwnd) and win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
80+
phwnd = win32gui.GetParent(hwnd)
81+
title = win32gui.GetWindowText(hwnd)
82+
name = win32gui.GetClassName(hwnd)
83+
self.windowList.addItem(
84+
'{0}|{1}|\t标题:{2}\t|\t类名:{3}'.format(hwnd, phwnd, title, name))
85+
86+
87+
if __name__ == '__main__':
88+
import sys
89+
from PyQt5.QtWidgets import QApplication
90+
app = QApplication(sys.argv)
91+
w = Window()
92+
w.show()
93+
sys.exit(app.exec_())

‎嵌入外部窗口/README.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# 内嵌外部窗口
2+
3+
### 原理思路:
4+
- 1.使用SetParent函数设置外部窗口的parent为Qt的窗口
5+
- 2.Qt使用QWidget.createWindowContainer(QWindow.fromWinId(窗口ID))生成QWidget
6+
- 3.使用GetWindowLong得到原来窗口的样式属性(style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)和exstyle = win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE))
7+
- 4.这里还原窗口后不会显示,用spy++发现没有了WS_VISIBLE样式(未解决)
8+
9+
截图
10+
11+
![1](ScreenShot/1.gif)

‎嵌入外部窗口/ScreenShot/1.gif‎

344 KB
Loading[フレーム]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /