如何使用Python MSS库通过窗口句柄捕获后台运行的指定窗口?
窗口后台截图方案实现
该需求存在可行落地方案,Windows平台下可通过Win32 API结合窗口句柄实现后台窗口捕获,即使窗口被其他窗口完全遮挡也可正常抓取,仅部分最小化状态、高权限、UWP类窗口存在兼容限制。
依赖安装
需要先安装pywin32库调用Win32系统接口:pip install pywin32
核心实现逻辑
- 通过窗口标题/窗口类名获取目标窗口的唯一句柄hwnd
- 调用Win32 API获取窗口的实际尺寸参数
- 创建内存DC,调用
PrintWindow接口将目标窗口的内容直接绘制到内存缓冲区,无需依赖前台显示状态 - 将缓冲区内容转为numpy数组适配opencv后续处理
修改后的完整代码
import cv2 as cv import numpy as np import time import win32gui import win32ui import win32con import win32api # 关闭系统DPI虚拟化,避免高DPI屏幕下抓取内容偏移 win32api.SetProcessDPIAware() def window_capture(hwnd): # 获取窗口完整尺寸(包含标题栏、边框) left, top, right, bottom = win32gui.GetWindowRect(hwnd) width = right - left height = bottom - top # 创建设备上下文 hwndDC = win32gui.GetWindowDC(hwnd) mfcDC = win32ui.CreateDCFromHandle(hwndDC) saveDC = mfcDC.CreateCompatibleDC() # 创建位图对象存储窗口内容 saveBitMap = win32ui.CreateBitmap() saveBitMap.CreateCompatibleBitmap(mfcDC, width, height) saveDC.SelectObject(saveBitMap) # 把窗口内容打印到内存DC,参数0表示抓取完整窗口,1表示仅抓取客户区 win32gui.PrintWindow(hwnd, saveDC.GetSafeHdc(), 0) # 转为opencv支持的numpy数组格式 signedIntsArray = saveBitMap.GetBitmapBits(True) img = np.frombuffer(signedIntsArray, dtype='uint8') img.shape = (height, width, 4) # 释放资源避免内存泄漏 win32gui.DeleteObject(saveBitMap.GetHandle()) saveDC.DeleteDC() mfcDC.DeleteDC() win32gui.ReleaseDC(hwnd, hwndDC) # 移除alpha通道,转为BGR格式适配opencv return cv.cvtColor(img, cv.COLOR_BGRA2BGR) # 替换为你要捕获的窗口标题,也可通过其他方式获取目标窗口句柄 target_window_title = "你的目标窗口标题" hwnd = win32gui.FindWindow(None, target_window_title) if not hwnd: raise Exception("未找到对应标题的目标窗口") while "Screen capturing": last_time = time.time() screenshot = window_capture(hwnd) cv.imshow('Computer Vision', screenshot) print(f'FPS {(1 / (time.time() - last_time)):.2f}') # 按q退出 if cv.waitKey(1) == ord("q"): cv.destroyAllWindows() break
注意事项
- 若目标窗口处于最小化状态,部分程序会停止渲染,抓取结果会黑屏,可增加逻辑判断,最小化时临时恢复窗口再抓取,完成后恢复最小化状态即可
- 若目标窗口以管理员权限运行,你的脚本也需要以管理员权限启动,否则会出现抓取失败、黑屏问题
- 本方案仅适配Windows平台,macOS/Linux需使用对应系统的原生窗口API实现
内容的提问来源于stack exchange,提问作者whyeyes
相关产品推荐
相关产品推荐

