Я пытаюсь запрограммировать HUD для стороннего приложения, использующего Python.
Я уже смог убедиться, что мой HUD следует стороннему приложению при перемещении стороннего приложения, но я изо всех сил стараюсь, чтобы HUD всегда отображался вверху стороннего приложения и исчезалкогда оно свернуто или когда другое приложение выходит на передний план.
Я пробовал некоторые функции оконного API ( SetWindowPos , BringWindowToTop и SetForegroundWindow ), но ни одна из них не дала мне ожидаемого результата:HUD всегда остается за сторонним приложением.
Вот простой пример кода, иллюстрирующий мою проблему:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import ctypes
import ctypes.wintypes
user32 = ctypes.windll.user32
HUD_WIDTH = 100
HUD_HEIGHT = 50
WINDOW_NAME = "Window name" #Replace this by the name of an opened window
EVENT_OBJECT_LOCATIONCHANGE = 0x800B
EVENT_SYSTEM_FOREGROUND = 0x0003
WINEVENT_OUTOFCONTEXT = 0x0000
EVENT_SYSTEM_MINIMIZEEND = 0x0017
class Hud(QLabel):
def __init__(self,window_handle):
super().__init__()
self.initUI()
self.window_handle = window_handle
rect = ctypes.wintypes.RECT()
user32.GetWindowRect(window_handle,ctypes.byref(rect))
self.window_x = rect.left
self.window_y = rect.top
self.setFollowWindow()
def initUI(self):
self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
self.resize(HUD_WIDTH,HUD_HEIGHT)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
p.setColor(self.foregroundRole(),Qt.white)
self.setPalette(p)
self.setWindowOpacity(0.7)
self.setText("Hello")
self.setAlignment(Qt.AlignCenter)
self.show()
def mousePressEvent(self,event):
self.click_x_coordinate = event.x()
self.click_y_coordinate = event.y()
def mouseMoveEvent(self,event):
self.move(event.globalX()-self.click_x_coordinate,event.globalY()-self.click_y_coordinate)
def setFollowWindow(self):
WinEventProcType = ctypes.WINFUNCTYPE(
None,
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
ctypes.wintypes.HWND,
ctypes.wintypes.LONG,
ctypes.wintypes.LONG,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD
)
def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime):
if idObject != -9: #Avoids mouse events
if event == EVENT_OBJECT_LOCATIONCHANGE and hwnd == self.window_handle:
rect = ctypes.wintypes.RECT()
user32.GetWindowRect(hwnd,ctypes.byref(rect))
self.move(self.x() + rect.left - self.window_x,self.y() + rect.top - self.window_y)
self.window_x = rect.left
self.window_y = rect.top
elif event == EVENT_SYSTEM_FOREGROUND or event == EVENT_SYSTEM_MINIMIZEEND:
if hwnd == self.window_handle:
user32.SetWindowPos(self.winId().__int__(),-1,self.x(),self.y(),self.width(),
self.height())
self.WinEventProc = WinEventProcType(callback)
user32.SetWinEventHook.restype = ctypes.wintypes.HANDLE
self.hook = user32.SetWinEventHook(
EVENT_SYSTEM_FOREGROUND,
EVENT_OBJECT_LOCATIONCHANGE,
0,
self.WinEventProc,
0,
0,
WINEVENT_OUTOFCONTEXT
)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
self.initUI()
def initUI(self):
self.launch_hud_button = QPushButton("Launch HUD",self)
self.launch_hud_button.clicked.connect(self.launchHud)
self.show()
def launchHud(self):
window_handle = user32.FindWindowW(0,WINDOW_NAME)
if window_handle != 0 :
self.hud = Hud(window_handle)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
Я также попытался установить стороннее приложение в качестве родительского для моего HUD, используя SetParent но при этом мой HUD вообще не отображается.
Есть ли у вас какие-либо предложения, чтобы заставить его работать, используя Window API или что-то еще?