我正在尝试使用 Python 为第三方应用程序编写 HUD 程序。
我已经能够确保当第三方应用程序移动时我的 HUD 跟随第三方应用程序,但我很难确保 HUD 始终出现在第三方应用程序的顶部并在第三方应用程序移动时消失最小化或当其他应用程序转到前台时。
我尝试了 Window 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_())
我还尝试使用 SetParent 将第三方应用程序设置为我的 HUD 的父应用程序但这样做时,我的 HUD 根本不显示。
您对使用 Window API 或其他方式使其工作有什么建议吗?
最佳答案
尝试一下:
# ...
def launchHud(self):
window_handle = user32.FindWindowW(0,WINDOW_NAME)
if window_handle != 0 :
self.hud = Hud(window_handle)
self.hud.setWindowFlags(self.windowFlags() | # <---
Qt.FramelessWindowHint | # <---
Qt.WindowStaysOnTopHint) # <---
self.hud.show() # <--- !!!
# ...
关于python - 使用 Python 创建 HUD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54973359/