Python使用PyQt5实现指定窗口置顶
文章目录
- 前言
- 一、网上找到的代码
- 二、尝试与借鉴后的代码——加入PyQt界面
-
- 1.引入库
- 2.主代码
- 3.完整主代码
- 4.UI界面代码
- 总结
前言
工作中,同事随口提了一句:要是能让WPS窗口置顶就好了,老是将窗口切换来切换去的太麻烦了。
然后,这个奇怪的点子引起了本人的注意,那就试试能不能实现吧。
一、网上找到的代码
不知道是不是我手法或版本的缘故,用了网上找的代码都是窗口弹出而已,并没有把它置顶,可以参考以下我尝试过于借鉴得到的成功的博客:
Python中最全的窗口操作,如窗口最大化、最小化、窗口置顶、获取缩放比例等
python选择应用窗口到最前面
Python中设置指定窗口为前台活动窗口(最顶层窗口)win32gui
二、尝试与借鉴后的代码——加入PyQt界面
1.引入库
代码如下(示例):
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
# 下面这个是我使用的ui界面代码
from Window_top import Ui_MainWindow as UI_Wimport win32gui
import win32con
import win32com.client
# 下面两行代码是用于解决图标不显示的问题
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")
2.主代码
代码如下(示例):
class MAIN_windows(UI_W, QMainWindow):def __init__(self):super(MAIN_windows, self).__init__()self.hwnd_map = Noneself.setupUi(self)self.pushButton.clicked.connect(self.lll)self.pushButton_2.clicked.connect(self.Window_top) # 选择应用窗口置顶self.pushButton_3.clicked.connect(self.cancel_Window_top) # 取消应用窗口置顶def get_all_hwnd(self, hwnd, mouse):"""获取后台运行的所有程序"""if (win32gui.IsWindow(hwnd) andwin32gui.IsWindowEnabled(hwnd) andwin32gui.IsWindowVisible(hwnd)):self.hwnd_map.update({hwnd: win32gui.GetWindowText(hwnd)})def lll(self):"""显示获取到的所有程序。(第一个显示估计是程序运行的ID号)(第二个显示是程序窗口名与程序名)"""try:self.hwnd_map = {}win32gui.EnumWindows(self.get_all_hwnd, 0)for i in self.hwnd_map.items():if i[1] != "":print(i)self.textEdit_4.append(str(i[0]) + " " + str(i[1]))except Exception as exx:print("\\nlll", exx)def Window_top(self):"""设置指定窗口置顶"""try:App_name = str(self.lineEdit.text())for h, t in self.hwnd_map.items():if t != "":if t.find(App_name) != -1:# h 为想要放到最前面的窗口句柄print(h, t)win32gui.BringWindowToTop(h)shell = win32com.client.Dispatch("WScript.Shell")shell.SendKeys('%')# 被其他窗口遮挡,调用后放到最前面win32gui.SetWindowPos(h, win32con.HWND_TOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)# 解决被最小化的情况win32gui.ShowWindow(h, win32con.SW_RESTORE)except Exception as ee:print("\\nWindow_top", ee)def cancel_Window_top(self):"""取消指定窗口置顶"""try:App_name = str(self.lineEdit.text())for h, t in self.hwnd_map.items():if t != "":if t.find(App_name) != -1:# h 为想要放到最前面的窗口句柄print(h, t)# win32gui.BringWindowToTop(h)# shell = win32com.client.Dispatch("WScript.Shell")# shell.SendKeys('%')# 取消置顶win32gui.SetWindowPos(h, win32con.HWND_NOTOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)# 解决被最小化的情况win32gui.ShowWindow(h, win32con.SW_RESTORE)except Exception as ee:print("\\ncancel_Window_top:", ee)def closeEvent(self, event):"""软件关闭时取消所有窗口置顶,但还有些问题,开了多个窗口置顶后貌似没能让所有置顶的窗口都取消置顶"""try:self.cancel_Window_top()except Exception as ee:print("\\ncloseEvent:", ee)if __name__ == "__main__":try:app = QApplication(sys.argv)win = MAIN_windows()win.show()sys.exit(app.exec_())except Exception as ex:print('主函数入口出错了:', ex)
启动后点击“显示有哪些窗口可以置顶”就会得到类似下图的界面
输入的应用窗口名不需要输全名,输入一些特有的关键字即可,例如打开了Google Chrome,获取到的应用名会包含正在访问的页面标题,显示为“写文章-CSDN博客 - Google Chrome”,那么在输入栏中输入“Google Chrome”或“Google”就行了。
针对WPS软件的话,就直接输入“WPS”即可。
3.完整主代码
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
# 下面这个是我使用的ui界面代码
from Window_top import Ui_MainWindow as UI_Wimport win32gui
import win32con
import win32com.client
# 下面两行代码是用于解决图标不显示的问题
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid")class MAIN_windows(UI_W, QMainWindow):def __init__(self):super(MAIN_windows, self).__init__()self.hwnd_map = Noneself.setupUi(self)self.pushButton.clicked.connect(self.lll)self.pushButton_2.clicked.connect(self.Window_top) # 选择应用窗口置顶self.pushButton_3.clicked.connect(self.cancel_Window_top) # 取消应用窗口置顶def get_all_hwnd(self, hwnd, mouse):"""获取后台运行的所有程序"""if (win32gui.IsWindow(hwnd) andwin32gui.IsWindowEnabled(hwnd) andwin32gui.IsWindowVisible(hwnd)):self.hwnd_map.update({hwnd: win32gui.GetWindowText(hwnd)})def lll(self):"""显示获取到的所有程序。(第一个显示估计是程序运行的ID号)(第二个显示是程序窗口名与程序名)"""try:self.hwnd_map = {}win32gui.EnumWindows(self.get_all_hwnd, 0)for i in self.hwnd_map.items():if i[1] != "":print(i)self.textEdit_4.append(str(i[0]) + " " + str(i[1]))except Exception as exx:print("\\nlll", exx)def Window_top(self):"""设置指定窗口置顶"""try:App_name = str(self.lineEdit.text())for h, t in self.hwnd_map.items():if t != "":if t.find(App_name) != -1:# h 为想要放到最前面的窗口句柄print(h, t)win32gui.BringWindowToTop(h)shell = win32com.client.Dispatch("WScript.Shell")shell.SendKeys('%')# 被其他窗口遮挡,调用后放到最前面win32gui.SetWindowPos(h, win32con.HWND_TOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)# 解决被最小化的情况win32gui.ShowWindow(h, win32con.SW_RESTORE)except Exception as ee:print("\\nWindow_top", ee)def cancel_Window_top(self):"""取消指定窗口置顶"""try:App_name = str(self.lineEdit.text())for h, t in self.hwnd_map.items():if t != "":if t.find(App_name) != -1:# h 为想要放到最前面的窗口句柄print(h, t)# win32gui.BringWindowToTop(h)# shell = win32com.client.Dispatch("WScript.Shell")# shell.SendKeys('%')# 取消置顶win32gui.SetWindowPos(h, win32con.HWND_NOTOPMOST, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)# 解决被最小化的情况win32gui.ShowWindow(h, win32con.SW_RESTORE)except Exception as ee:print("\\ncancel_Window_top:", ee)def closeEvent(self, event):"""软件关闭时取消所有窗口置顶,但还有些问题,开了多个窗口置顶后貌似没能让所有置顶的窗口都取消置顶"""try:self.cancel_Window_top()except Exception as ee:print("\\ncloseEvent:", ee)if __name__ == "__main__":try:app = QApplication(sys.argv)win = MAIN_windows()win.show()sys.exit(app.exec_())except Exception as ex:print('主函数入口出错了:', ex)
4.UI界面代码
from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(800, 600)font = QtGui.QFont()font.setPointSize(12)MainWindow.setFont(font)self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)self.gridLayout.setObjectName("gridLayout")self.pushButton = QtWidgets.QPushButton(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)font.setBold(False)font.setWeight(50)self.pushButton.setFont(font)self.pushButton.setObjectName("pushButton")self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 3)self.textEdit_4 = QtWidgets.QTextEdit(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)self.textEdit_4.setFont(font)self.textEdit_4.setObjectName("textEdit_4")self.gridLayout.addWidget(self.textEdit_4, 1, 0, 1, 3)self.label_9 = QtWidgets.QLabel(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)font.setBold(False)font.setWeight(50)self.label_9.setFont(font)self.label_9.setObjectName("label_9")self.gridLayout.addWidget(self.label_9, 2, 0, 1, 1)self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lineEdit.setFont(font)self.lineEdit.setObjectName("lineEdit")self.gridLayout.addWidget(self.lineEdit, 2, 1, 1, 2)self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)font.setBold(False)font.setWeight(50)self.pushButton_2.setFont(font)self.pushButton_2.setObjectName("pushButton_2")self.gridLayout.addWidget(self.pushButton_2, 3, 0, 1, 2)self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)font = QtGui.QFont()font.setFamily("楷体")font.setPointSize(14)font.setBold(False)font.setWeight(50)self.pushButton_3.setFont(font)self.pushButton_3.setObjectName("pushButton_3")self.gridLayout.addWidget(self.pushButton_3, 3, 2, 1, 1)MainWindow.setCentralWidget(self.centralwidget)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "Window_top"))self.pushButton.setText(_translate("MainWindow", "显示有哪些窗口可以置顶"))self.label_9.setText(_translate("MainWindow", "输入置顶的应用窗口名"))self.pushButton_2.setText(_translate("MainWindow", "确定置顶"))self.pushButton_3.setText(_translate("MainWindow", "取消置顶"))
总结
代码中还有些小bug,但不怎么影响使用。
当软件关闭的时候,好像没能让所有置顶过的窗口取消置顶,所以最好是点击界面右下角的“取消置顶”,不然很难让那指定的窗口取消置顶。