You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何用Python创建Windows顶层穿透透明GUI以绘制游戏悬浮图形?

在Windows中实现视觉透明、点击穿透的Python顶层绘图窗口

可行方案:使用Windows分层窗口API

通过Windows的**分层窗口(Layered Window)**机制,结合win32apiwin32gui模块,可以实现仅显示绘制图形、背景完全透明且鼠标点击穿透的顶层窗口,同时避免卡顿和闪烁问题。

核心原理

  • 分层窗口(WS_EX_LAYERED):允许窗口设置透明度或指定透明色,仅保留绘制的图形内容,背景完全透明。
  • 点击穿透(WS_EX_TRANSPARENT):让窗口忽略所有鼠标和键盘输入,直接传递给底层窗口(如游戏)。
  • 顶层窗口(WS_EX_TOPMOST):确保窗口始终显示在所有程序之上。

解决之前方案的问题

  • Tkinter方案缺陷-alpha是全局透明度,无法单独让窗口背景透明;未设置点击穿透的扩展样式,导致窗口阻挡输入。
  • win32gui直接绘点缺陷:直接操作屏幕DC会被系统刷新覆盖,频繁调用SetPixel效率极低,引发卡顿和闪烁。

完整实现代码

import win32gui
import win32api
import win32con

class OverlayWindow:
    def __init__(self):
        # 窗口类名和标题
        self.class_name = "PythonOverlayClass"
        self.window_name = "GameOverlay"
        
        # 注册窗口类
        wc = win32gui.WNDCLASS()
        wc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
        wc.lpfnWndProc = self.wnd_proc
        wc.hInstance = win32api.GetModuleHandle(None)
        wc.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
        wc.lpszClassName = self.class_name
        win32gui.RegisterClass(wc)
        
        # 获取屏幕尺寸
        self.screen_width = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
        self.screen_height = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
        
        # 创建窗口:设置扩展样式为分层、点击穿透、顶层
        self.hwnd = win32gui.CreateWindowEx(
            win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT | win32con.WS_EX_TOPMOST,
            self.class_name,
            self.window_name,
            win32con.WS_POPUP,  # 无边框窗口
            0, 0, self.screen_width, self.screen_height,
            None, None, wc.hInstance, None
        )
        
        # 设置分层窗口属性:指定白色为透明色(后续绘制时背景用白色,会被透明化)
        win32gui.SetLayeredWindowAttributes(self.hwnd, win32api.RGB(255,255,255), 0, win32con.LWA_COLORKEY)
        
        # 显示窗口
        win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW)
    
    def wnd_proc(self, hwnd, msg, wparam, lparam):
        # 处理窗口消息,这里只处理重绘和退出
        if msg == win32con.WM_PAINT:
            self.on_paint()
            return 0
        elif msg == win32con.WM_DESTROY:
            win32api.PostQuitMessage(0)
            return 0
        return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)
    
    def on_paint(self):
        # 获取窗口DC
        hdc = win32gui.GetDC(self.hwnd)
        try:
            # 设置背景为透明色(白色)
            white_brush = win32gui.GetStockObject(win32con.WHITE_BRUSH)
            win32gui.SelectObject(hdc, white_brush)
            win32gui.Rectangle(hdc, 0, 0, self.screen_width, self.screen_height)
            
            # 绘制图形:屏幕中心红色矩形
            center_x = self.screen_width // 2
            center_y = self.screen_height // 2
            size = 10
            # 创建红色画笔
            red_pen = win32gui.CreatePen(win32con.PS_SOLID, 2, win32api.RGB(255,0,0))
            win32gui.SelectObject(hdc, red_pen)
            # 绘制矩形
            win32gui.Rectangle(hdc, 
                            center_x - size, center_y - size,
                            center_x + size, center_y + size)
            # 清理画笔
            win32gui.DeleteObject(red_pen)
            
            # 示例:绘制十字光标线
            cross_size = 50
            win32gui.MoveToEx(hdc, center_x - cross_size, center_y, None)
            win32gui.LineTo(hdc, center_x + cross_size, center_y)
            win32gui.MoveToEx(hdc, center_x, center_y - cross_size, None)
            win32gui.LineTo(hdc, center_x, center_y + cross_size)
            
        finally:
            # 释放DC
            win32gui.ReleaseDC(self.hwnd, hdc)
    
    def run(self):
        # 消息循环,保持窗口运行
        msg = win32gui.GetMessage(None, 0, 0)
        while msg[0] != win32con.WM_QUIT:
            win32gui.TranslateMessage(msg)
            win32gui.DispatchMessage(msg)
            msg = win32gui.GetMessage(None, 0, 0)

if __name__ == "__main__":
    overlay = OverlayWindow()
    overlay.run()

关键说明

  1. 透明色设置:代码中指定白色为透明色,绘制时窗口背景填充白色,会被系统自动透明化,仅保留绘制的彩色图形。
  2. 点击穿透WS_EX_TRANSPARENT扩展样式让窗口完全忽略鼠标输入,不会干扰游戏或其他程序的操作。
  3. 性能优化:通过窗口消息触发重绘(WM_PAINT),而非循环强制绘制,避免卡顿和闪烁;若需要动态更新图形,可调用win32gui.InvalidateRect触发重绘。
  4. 反作弊注意:分层窗口是Windows原生机制,大部分游戏不会检测,但使用时需遵守游戏的用户协议,避免违规操作。

内容的提问来源于stack exchange,提问作者NONAME

火山引擎 最新活动