You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用win32ui截图报CreateCompatibleDC failed错误如何解决

CreateCompatibleDC报错排查与解决方案

该报错属于pywin32的错误提示偏差,实际是你调用CreateCompatibleBitmap时传入了无效参数、或者系统GDI资源耗尽触发的异常,可按以下顺序排查解决:

1. 校验窗口宽高有效性

你当前的代码仅在构造函数中获取一次窗口句柄,没有实时校验窗口宽高的合法性。当窗口最小化、被关闭、动态缩放时,缓存的self.w和self.h可能变为0或者负数,传入CreateCompatibleBitmap就会直接触发该报错。
修改方案:将窗口尺寸获取逻辑移到get_screenshot方法开头,每次截图前先获取最新窗口参数,过滤无效状态:

def get_screenshot(self):
    # 每次截图前获取最新窗口尺寸
    rect = win32gui.GetWindowRect(self.hwnd)
    self.w = rect[2] - rect[0]
    self.h = rect[3] - rect[1]
    # 窗口最小化/状态异常时直接跳过本次截图
    if self.w <= 0 or self.h <= 0:
        return None
    # 后续接原有的DC操作逻辑

2. 修复GDI资源泄漏

你当前的资源释放逻辑没有异常兜底,如果DC创建、位图拷贝等步骤中途抛出异常,后面的资源释放代码不会执行,GDI对象会持续堆积,达到单进程GDI对象上限(默认10000个)后就会触发该报错。
修改方案:用try-finally块包裹DC操作逻辑,保证无论执行是否成功,资源都会被释放:

def get_screenshot(self):
    # 先执行上方新增的窗口尺寸校验逻辑
    wDC = win32gui.GetWindowDC(self.hwnd)
    dcObj = None
    cDC = None
    dataBitMap = None
    img = None
    try:
        dcObj = win32ui.CreateDCFromHandle(wDC)
        cDC = dcObj.CreateCompatibleDC()
        dataBitMap = win32ui.CreateBitmap()
        dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
        cDC.SelectObject(dataBitMap)
        cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)
        signedIntsArray = dataBitMap.GetBitmapBits(True)
        # 替换已弃用的np.fromstring,减少异常概率
        img = np.frombuffer(signedIntsArray, dtype='uint8')
        img.shape = (self.h, self.w, 4)
        # 可选:直接去掉alpha通道,适配OpenCV图片匹配的输入要求
        img = img[..., :3]
    finally:
        # 无论是否报错,强制释放所有GDI资源
        if dataBitMap:
            win32gui.DeleteObject(dataBitMap.GetHandle())
        if cDC:
            cDC.DeleteDC()
        if dcObj:
            dcObj.DeleteDC()
        win32gui.ReleaseDC(self.hwnd, wDC)
    return img

3. 其他高频场景适配

  • 高DPI屏幕适配:如果系统开启了DPI缩放,拿到的窗口尺寸会和实际像素尺寸不符,在程序入口添加以下代码适配高DPI:
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2)
  • 降低截图频率:在主循环中添加10ms左右的延迟,避免空跑循环占用过高CPU,同时降低GDI资源申请频率:
while(True):
    haystack_img = wincap.get_screenshot()
    if haystack_img is None:
        time.sleep(0.01)
        continue
    points = search.find(haystack_img, 0.85, 'rectangles')
    time.sleep(0.01)
  • 特殊窗口适配:如果捕获的是UWP应用、带DRM保护的视频窗口、开启硬件加速的游戏窗口,win32原生截图接口无法正常访问,可替换为mss、pyautogui等第三方截图库实现捕获。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 16:27:03