首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Python创建HUD

使用Python创建HUD
EN

Stack Overflow用户
提问于 2019-03-04 04:21:34
回答 2查看 1.8K关注 0票数 1

我正在尝试使用Python为第三方应用程序编写HUD。

我已经能够确保我的HUD在第三方应用程序移动时跟随第三方应用程序,但我很难确保HUD始终显示在第三方应用程序的顶部,并在最小化或其他应用程序转到前台时消失。

我已经尝试了Window的一些函数(SetWindowPosBringWindowToTopSetForegroundWindow),但这些函数都没有给出预期的结果: HUD始终位于第三方应用程序之后。

下面是一个简单的代码示例来说明我的问题:

代码语言:javascript
复制
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或其他什么东西来工作吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-07-16 21:31:38

通过将HUD父类设置为QMainWindow而不是QLabel,并删除对setWindowOpacity的调用,我最终设法确保我的HUD始终位于给定的第三方应用程序的顶部。以下代码适用于我:

代码语言:javascript
复制
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 

class Hud(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.hwnd = self.winId().__int__()


    def initUI(self):
        self.setWindowFlags(Qt.FramelessWindowHint)   
        self.resize(HUD_WIDTH,HUD_HEIGHT)   
        self.textArea = QLabel()
        self.setCentralWidget(self.textArea);  
        self.setStyleSheet("background-color: rgb(0, 0, 0);color: rgb(255,255,255);")
        self.textArea.setText("Hello")
        self.textArea.setAlignment(Qt.AlignCenter)
        self.show()


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()
            user32.SetParent(self.hud.hwnd,window_handle)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = MainWindow()
    sys.exit(app.exec_())  

如果有人知道为什么QMainWindow适用于SetParent而不是像QLabel这样的其他Qt类,或者为什么修改窗口不透明度会导致不可见的HUD (对SetParent的调用不会返回0,所以我假设HUD实际上被设置为我的第三方应用程序的子类,但被绘制为完全透明),我会非常感兴趣。

票数 0
EN

Stack Overflow用户

发布于 2019-03-04 06:21:37

试试看:

代码语言:javascript
复制
# ... 
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()                                      # <--- !!!
# ...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54973359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档