python中win32gui库常用函数

常用函数

获取所有窗口信息

通过win32gui.EnumWindows(_callback, windows)获取所有窗口信息

传入回调函数容器即可

win32gui.GetWindowText(hwnd) 获取窗口标题栏文本

win32gui.GetClassName(hwnd)获取窗口类名

def get_all_windows():
    """
    获取所有可见的顶层窗口信息。

    注意:
        - EnumWindows 仅枚举【顶层窗口】,不包含子控件(如按钮、输入框)。
          若需获取子窗口,请使用 win32gui.EnumChildWindows(parent_hwnd, callback, param)。
        - 返回结果仅包含可见窗口,系统隐藏窗口(如 Default IME)已被过滤。
    """

    def _callback(hwnd, result):
        """
        EnumWindows 回调函数,每找到一个顶层窗口时被系统自动调用。

        Args:
            hwnd: 当前窗口的句柄(整数标识符)
            result: 由 EnumWindows 第二个参数透传进来的列表容器
        """
        # 【过滤】跳过不可见窗口,避免返回大量无意义的系统隐藏窗口
        if win32gui.IsWindowVisible(hwnd):
            title = win32gui.GetWindowText(hwnd)  # 获取窗口标题栏文本
            cls = win32gui.GetClassName(hwnd)  # 获取窗口类名(标识窗口类型,如 Chrome_WidgetWin_1)

            result.append({
                "hwnd": hwnd,
                "title": title,
                "class": cls,
            })

        # ⚠️ 【关键】回调函数必须返回 True!
        # 若忘记返回或返回 False/None,EnumWindows 会在处理完当前窗口后立即停止枚举,
        # 且不会抛出任何错误提示,这是新手最常遇到的隐蔽 Bug。
        return True

    windows = []
    # 启动顶层窗口枚举,windows 列表会作为第二个参数传入回调函数的 result 参数
    win32gui.EnumWindows(_callback, windows)
    return windows

查找指定title的窗口

# 定义要查找的目标窗口标题(需与窗口实际标题完全一致,包括空格和标点)
title = "永远的蔚蓝星球"
# 通过窗口标题精确查找窗口句柄
# 第一个参数为窗口类名,传 None 表示不限类名,仅按标题匹配
# 返回值 hwnd 为窗口句柄(整数),未找到时返回 0
hwnd = win32gui.FindWindow(None, title)
# 判断是否成功找到窗口(0 在布尔上下文中为 False)
if hwnd:
    # 找到窗口,打印窗口标题和对应句柄
    print(f"找到了窗口<{title}>,句柄:{hwnd}")
else:
    # 未找到匹配标题的窗口,提示用户检查标题是否正确或窗口是否已打开
    print(f"没找到窗口<{title}>")

判断窗口是否最小化

min_win = win32gui.IsIconic(hwnd)
print(f"窗口<{title}>是否最小化:{'是' if min_win else '否'}")

判断窗口是否可见

visible = win32gui.IsWindowVisible(hwnd)
print(f"窗口<{title}>是否可见:{'是' if visible else '否'}")

获取窗口坐标

# 获取窗口坐标
rect = win32gui.GetWindowRect(hwnd)
print(f"窗口<{title}>坐标:{rect}")
# 返回值含义:(left, top, right, bottom) 分别代表窗口左、上、右、下边缘相对于屏幕左上角(0, 0) 的像素坐标。
# 宽高计算:width = right - left,height = bottom - top

设置窗口置顶显示

def safe_set_topmost(hwnd):
    """
    安全地将窗口置顶(始终显示在其他普通窗口之上)。

    Args:
        hwnd: 目标窗口句柄

    Returns:
        bool: True 表示操作成功或窗口已处于置顶状态;False 表示句柄无效
    """
    # 校验窗口句柄是否有效,避免对已销毁的窗口操作导致异常
    if not win32gui.IsWindow(hwnd):
        return False

    # 如果窗口处于最小化状态,先恢复到正常状态
    # 原因:最小化窗口无法被真正置顶,且后续获取坐标/尺寸会返回缓存值
    if win32gui.IsIconic(hwnd):
        win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)

    # 使用 SetWindowPos 设置 Z 序为 HWND_TOPMOST
    # SWP_NOMOVE | SWP_NOSIZE:仅改变 Z 序,不移动窗口也不调整大小
    win32gui.SetWindowPos(
        hwnd, win32con.HWND_TOPMOST,
        0, 0, 0, 0,
        win32con.SWP_NOMOVE | win32con.SWP_NOSIZE
    )
    return True

设置窗口居中并且置顶显示

def safe_center_and_topmost(hwnd):
    """
    安全地将窗口居中到当前所在显示器的工作区并置顶。
    自动处理最小化状态、多显示器环境和 DPI 缩放。

    Args:
        hwnd: 目标窗口句柄

    Returns:
        bool: True 表示操作成功;False 表示句柄无效
    """
    if not win32gui.IsWindow(hwnd):
        return False

    # 1. 最小化窗口必须先恢复,否则 GetWindowRect 返回的是历史缓存坐标
    #    直接用缓存坐标计算会导致居中位置完全错误
    if win32gui.IsIconic(hwnd):
        win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)

    # 2. 获取窗口当前所在显示器的工作区(排除任务栏区域)
    #    MONITOR_DEFAULTTONEAREST:多显示器下自动定位窗口实际所在的屏幕
    monitor = win32api.MonitorFromWindow(hwnd, win32con.MONITOR_DEFAULTTONEAREST)
    monitor_info = win32api.GetMonitorInfo(monitor)
    work_area = monitor_info['Work']  # (left, top, right, bottom)

    # 3. 获取窗口当前的像素尺寸
    rect = win32gui.GetWindowRect(hwnd)
    win_w = rect[2] - rect[0]
    win_h = rect[3] - rect[1]

    # 4. 基于工作区(而非整个屏幕物理分辨率)计算居中坐标
    #    使用 Work 而非 Monitor 避免窗口被任务栏遮挡或视觉上偏下
    x = work_area[0] + (work_area[2] - work_area[0] - win_w) // 2
    y = work_area[1] + (work_area[3] - work_area[1] - win_h) // 2

    # 5. 单次 SetWindowPos 同时完成移动 + 置顶
    #    分两步调用(先 MoveWindow 再 SetWindowPos)会产生两帧中间状态导致可见闪烁
    #    此处不设 SWP_NOMOVE/SWP_NOSIZE,因为本次需要同时改变位置和 Z 序
    win32gui.SetWindowPos(
        hwnd, win32con.HWND_TOPMOST,
        x, y, win_w, win_h,
        0
    )
    return True

取消窗口置顶显示

def safe_clear_topmost(hwnd):
    """
    取消窗口的置顶状态,恢复为普通 Z 序。

    Args:
        hwnd: 目标窗口句柄

    Returns:
        bool: True 表示操作成功或窗口已非置顶;False 表示句柄无效
    """
    if not win32gui.IsWindow(hwnd):
        return False

    # 将 Z 序设为 HWND_NOTOPMOST,移除置顶属性
    # 同样使用 NOMOVE | NOSIZE 避免意外改变窗口位置和尺寸
    win32gui.SetWindowPos(
        hwnd, win32con.HWND_NOTOPMOST,
        0, 0, 0, 0,
        win32con.SWP_NOMOVE | win32con.SWP_NOSIZE
    )
    return True

最大化显示

def safe_maximize(hwnd):
    """
    安全地最大化窗口。自动处理最小化状态,避免异常显示。

    Args:
        hwnd: 目标窗口句柄

    Returns:
        bool: True 表示操作成功或窗口已最大化;False 表示句柄无效
    """
    if not win32gui.IsWindow(hwnd):
        return False

    # ⚠️ 关键:最小化窗口直接调用 SW_MAXIMIZE 会导致"最小化+最大化"异常状态
    # 表现为任务栏图标闪烁但窗口不可见,必须先恢复再最大化
    if win32gui.IsIconic(hwnd):
        win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)

    # SW_MAXIMIZE:最大化到当前所在显示器的全部工作区
    win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)
    return True

最小化显示

def safe_minimize(hwnd):
    """
    安全地最小化窗口。跳过已最小化的窗口,避免重复触发消息回调。

    Args:
        hwnd: 目标窗口句柄

    Returns:
        bool: True 表示操作成功或窗口已最小化;False 表示句柄无效
    """
    if not win32gui.IsWindow(hwnd):
        return False

    # 幂等守卫:已最小化则直接返回,避免对 WPF/Electron 等框架触发多余动画
    if win32gui.IsIconic(hwnd):
        return True

    # SW_MINIMIZE:仅改变状态为最小化,不强制激活窗口(保持当前前台窗口不变)
    # 如需最小化同时激活窗口,应改用 SW_SHOWMINIMIZED
    win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
    return True

取消最大化或者最小化

def safe_restore(hwnd):
    """
    取消窗口的最大化或最小化状态,将其恢复至正常显示状态。

    若窗口已处于正常状态,则不执行任何操作。

    Args:
        hwnd: 目标窗口句柄。

    Returns:
        bool: True 表示操作成功或窗口已处于正常状态;
              False 表示窗口句柄无效。
    """
    # 校验窗口句柄有效性
    if not win32gui.IsWindow(hwnd):
        return False

    # 既非最小化也非最大化,无需处理
    if not win32gui.IsIconic(hwnd) and win32gui.GetWindowPlacement(hwnd)[1] != win32con.SW_SHOWMAXIMIZED:
        return True

    # SW_RESTORE: 取消最大化/最小化,恢复至上一次正常状态的尺寸与位置
    # ⚠️ 不可使用 SW_SHOWNORMAL,该标志会重置窗口为默认初始尺寸
    win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
    return True
posted @ 2026-08-10 21:03  南风丶轻语  阅读(5)  评论(0)    收藏  举报