How to restore the QT window minimized into system tray from other process?
-
This is one feature in big system. We simplify the problem into sample code below. (Test Environment: Win7 64bit, python 2.7)
In the sample, we can click "hide" to minimize the window into system tray with the taskbar button hidden.If we click the tray button, the hidden window can show again.
We hope to implement the feature: when one instance has started and the window has been minimized into system tray, we start another instance(with the same script), then the new instance activates the old instance's window and show it back on the top.
Our method:
The new instance uses FindWindow API to get the window handle and then show it, the problem is that it fail to find the handle of old instance's window. Therefore we cannot locate the window handle to show it out again. We have used Spy++ to detect, there is no "MyWin" named window when the old instance is minimized into system tray.Can anybody help to find the solution to implement the feature?
from PySide import QtGui, QtCore from PySide.QtCore import * from PySide.QtGui import * import sys import os import tempfile import win32gui # enable Ctrl-C to breakdown import signal signal.signal(signal.SIGINT, signal.SIG_DFL) # checkSingleton : code modifieed from tendo.SingletInstance def checkSingleton(): basename = os.path.splitext(os.path.abspath(sys.argv[0]))[0].replace( "/", "-").replace(":", "").replace("\\", "-") + '.lock' lockfile = os.path.normpath(tempfile.gettempdir() + '/' + basename) success = False try: if os.path.exists(lockfile): os.unlink(lockfile) fd = os.open(lockfile, os.O_CREAT | os.O_EXCL | os.O_RDWR) success = True except OSError: pass return success class MyWin(QWidget): def __init__(self): super(MyWin, self).__init__() self.setWindowTitle("MyWin") self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) self.tray = QtGui.QSystemTrayIcon(QtGui.QIcon("logo.png"), self) self.tray.activated.connect(self.trayClicked) self.tray.show() btn = QPushButton("Hide") btn.clicked.connect(self.onHide) btn2 = QPushButton("Close") btn2.clicked.connect(self.onClose) out = QVBoxLayout() out.addWidget(btn) out.addWidget(btn2) self.setLayout(out) def onHide(self): self.setWindowFlags(self.windowFlags() | Qt.Tool) self.showMinimized() def onClose(self): sys.exit() def showUp(self): self.setWindowFlags(self.windowFlags() & (~Qt.Tool)) self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint) self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint) self.setWindowState(Qt.WindowActive) self.show() def trayClicked(self, reason): if reason == QtGui.QSystemTrayIcon.Trigger: self.showUp() app = QtGui.QApplication(sys.argv) ret = checkSingleton() if ret: win= MyWin() win.setGeometry(100,100,300,300) win.show() app.exec_() else: print "One instance has already been running" hwnd = win32gui.FindWindow("QWidget","MyWin") # < == Fail to find the handle of window to show it back if hwnd != 0: win32gui.SetForegroundWindow(hwnd) win32gui.ShowWindow(hwnd, 1)
-
Hi and welcome to devnet,
From what you describe you should rather create bindings for the QtSingleApplication module and use that.
It's typically a module used when you want to have only one instance of your application running.