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

如何在Python中捕获后台非活动窗口的指定区域?

Python捕获后台非活动窗口指定区域的解决方案

问题背景

已实现后台捕获非活动窗口,但无法精准截取指定区域(需按左上、右下坐标定义),要求不将窗口前置、不使用全屏截图避免干扰。

原代码问题分析

原代码创建的位图大小错误(直接使用窗口屏幕右/下边界值而非窗口宽高),且未针对指定区域做像素复制限制,导致捕获整个窗口。

解决方案1:直接捕获指定区域(高效版)

通过BitBlt精准复制窗口DC中的指定区域,无需先捕获完整窗口:

import win32gui, win32ui
from ctypes import windll
from PIL import Image

def capture_window_region(hwnd, region):
    # region格式:(窗口内左上x, 窗口内左上y, 窗口内右下x, 窗口内右下y)
    x1, y1, x2, y2 = region
    width = x2 - x1
    height = y2 - y1

    # 初始化DC资源
    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC = win32ui.CreateDCFromHandle(hwndDC)
    saveDC = mfcDC.CreateCompatibleDC()

    # 创建对应区域大小的位图
    saveBitMap = win32ui.CreateBitmap()
    saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
    saveDC.SelectObject(saveBitMap)

    # 复制窗口指定区域到目标DC(SRCCOPY表示直接复制像素)
    windll.gdi32.BitBlt(saveDC.GetSafeHdc(), 0, 0, width, height, hwndDC, x1, y1, 0x00CC0020)

    # 转换为PIL图像
    bmpinfo = saveBitMap.GetInfo()
    bmpstr = saveBitMap.GetBitmapBits(True)
    image = Image.frombuffer('RGB', (width, height), bmpstr, 'raw', 'BGRX', 0, 1)

    # 释放系统资源
    win32gui.DeleteObject(saveBitMap.GetHandle())
    saveDC.DeleteDC()
    mfcDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwndDC)

    return image

# 目标窗口名称
WINDOW_NAME = 'Play Chrome Dinosaur Game Online - elgooG - Google Chrome'
hwnd = win32gui.FindWindow(None, WINDOW_NAME)

# 替换为实际需要的窗口内区域坐标
target_region = (100, 200, 800, 600)
screen_capture = capture_window_region(hwnd, target_region)
screen_capture.save('window_region_capture.png')

解决方案2:先捕获完整窗口再裁剪(简洁版)

保留原PrintWindow逻辑,通过PIL的crop方法裁剪指定区域,代码改动最小:

import win32gui, win32ui
from ctypes import windll
from PIL import Image

def capture_window(hwnd):
    rect = win32gui.GetWindowRect(hwnd)
    width = rect[2] - rect[0]
    height = rect[3] - rect[1]

    hwndDC = win32gui.GetWindowDC(hwnd)
    mfcDC = win32ui.CreateDCFromHandle(hwndDC)
    saveDC = mfcDC.CreateCompatibleDC()
    saveBitMap = win32ui.CreateBitmap()
    saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
    saveDC.SelectObject(saveBitMap)

    windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 2)

    bmpinfo = saveBitMap.GetInfo()
    bmpstr = saveBitMap.GetBitmapBits(True)
    image = Image.frombuffer('RGB', (width, height), bmpstr, 'raw', 'BGRX', 0, 1)

    # 释放资源
    win32gui.DeleteObject(saveBitMap.GetHandle())
    saveDC.DeleteDC()
    mfcDC.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwndDC)

    return image

# 裁剪指定区域
def crop_image(image, region):
    return image.crop(region)

WINDOW_NAME = 'Play Chrome Dinosaur Game Online - elgooG - Google Chrome'
hwnd = win32gui.FindWindow(None, WINDOW_NAME)

full_window = capture_window(hwnd)
# 替换为实际窗口内区域坐标
target_region = (100, 200, 800, 600)
screen_capture = crop_image(full_window, target_region)
screen_capture.save('window_region_capture.png')

关键说明

  • 区域坐标:需传入窗口内部的相对坐标(以窗口左上角为原点),可通过截图工具获取目标区域的相对位置
  • 资源释放:必须严格释放DC和位图资源,避免内存泄漏
  • 参数选择:BitBlt方案适合高性能场景,裁剪方案适合快速调试和修改区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 22:08:09