python - 使用 Python 创建 HUD

标签 python winapi pyqt4

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

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

我尝试了 Window API 的一些功能( SetWindowPosBringWindowToTopSetForegroundWindow ),但这些功能都没有给我带来预期的结果: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/

相关文章:

c++ - LoadBitmap 失败 ERROR_RESOURCE_NAME_NOT_FOUND

python - Pyqt4:如何在 Qscintilla 中正确添加边距

python - 如何使用 Python imaplib 将消息从一个 imap 服务器复制到另一个 imap 服务器?

python - 根据类 python 2.7 中的变量按字母顺序对类列表进行排序

c++ - Win32 API CreateWindowW 与菜单创建冲突

pyqt - 如何复制 - 将 QStandardItemModel 创建的 QTableView 的多个项目粘贴到文本/excel 文件?

python - 在PYQT中选择要复制的文本

python - Twitter 用户关注者的随机页面

python - Lock和RLock有什么区别

winapi - Windows 上的低开销 I/O 监控