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

Python调用Win32 API捕获后台窗口时如何设置捕获顶部坐标排除标题栏

解决方案

根因说明

PrintWindow 本身不支持指定偏移捕获,只能完整写入目标窗口的全量内容到指定DC,因此仅调整位图大小只会裁剪底部区域,无法去掉顶部内容。你可以选择两种方案实现指定高度的顶部裁剪:


方案1:PIL图像裁剪(最易实现,适合90%以上场景)

先捕获完整窗口内容,再通过PIL的裁剪方法去掉顶部指定高度区域即可:

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

target_window_hwnd = win32gui.FindWindow(None, "Math Analysis - Google Chrome")
# 手动指定需要排除的顶部总高度,包含Chrome自绘标题栏、地址栏、书签栏等
application_window_topbar_size = 200 

# 获取窗口客户区完整尺寸
l, t, r, b = win32gui.GetClientRect(target_window_hwnd)
full_width = r - l
full_height = b - t

# 捕获完整窗口内容
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
mfcDC  = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, full_width, full_height)
saveDC.SelectObject(saveBitMap)
# 传参3兼容捕获Chrome等开启硬件加速的窗口内容
windll.user32.PrintWindow(target_window_hwnd, saveDC.GetSafeHdc(), 3)

# 转PIL图像后裁剪顶部区域
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
full_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
# 核心裁剪逻辑:保留从顶部指定高度以下到窗口底部的所有内容
cropped_image = full_image.crop((0, application_window_topbar_size, full_width, full_height))

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

# 可直接使用cropped_image,或保存验证
# cropped_image.save("cropped_result.png")

方案2:内存DC层BitBlt裁剪(适合高性能需求场景)

如果需要避免生成全量PIL图像的开销,可以通过双DC实现内存层面的偏移裁剪:

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

target_window_hwnd = win32gui.FindWindow(None, "Math Analysis - Google Chrome")
application_window_topbar_size = 200 

# 获取窗口完整尺寸
l, t, r, b = win32gui.GetClientRect(target_window_hwnd)
full_width = r - l
full_height = b - t
# 计算裁剪后的尺寸
cropped_width = full_width
cropped_height = full_height - application_window_topbar_size

# 临时DC:捕获完整窗口内容
hwndDC = win32gui.GetWindowDC(target_window_hwnd)
sourceDC = win32ui.CreateDCFromHandle(hwndDC)
tempDC = sourceDC.CreateCompatibleDC()
tempBitMap = win32ui.CreateBitmap()
tempBitMap.CreateCompatibleBitmap(sourceDC, full_width, full_height)
tempDC.SelectObject(tempBitMap)
windll.user32.PrintWindow(target_window_hwnd, tempDC.GetSafeHdc(), 3)

# 目标DC:从临时DC偏移复制需要的区域
targetDC = sourceDC.CreateCompatibleDC()
targetBitMap = win32ui.CreateBitmap()
targetBitMap.CreateCompatibleBitmap(sourceDC, cropped_width, cropped_height)
targetDC.SelectObject(targetBitMap)
# 核心偏移复制:从临时DC的(0, 顶部裁剪高度)位置开始复制对应大小的内容到目标DC
targetDC.BitBlt((0, 0), (cropped_width, cropped_height), tempDC, (0, application_window_topbar_size), win32con.SRCCOPY)

# 转换为PIL图像
bmpinfo = targetBitMap.GetInfo()
bmpstr = targetBitMap.GetBitmapBits(True)
cropped_image = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)

# 资源释放
win32gui.DeleteObject(tempBitMap.GetHandle())
win32gui.DeleteObject(targetBitMap.GetHandle())
tempDC.DeleteDC()
targetDC.DeleteDC()
sourceDC.DeleteDC()
win32gui.ReleaseDC(target_window_hwnd, hwndDC)

注意事项

  • 对于Chrome、Edge这类自绘界面的软件,系统API无法区分软件自身的地址栏、菜单栏,手动指定application_window_topbar_size是最简化的实现方式
  • 捕获常规无硬件加速的软件时,可将PrintWindow的第三个参数改为1,仅捕获系统级客户区,自动排除系统自带标题栏

内容的提问来源于stack exchange,提问作者D.Moore

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:09:03