文章目录
- import win32gui from mss import mss # 获取窗口句柄 hwnd = win32gui.FindWindow(None, “记事本”) # 替换为实际窗口标题 if hwnd == 0: raise Exception(“未找到目标窗口”) # 获取窗口客户区坐标(排除标题栏/边框) left, top, right, bot = win32gui.GetClientRect(hwnd) win32gui.ClientToScreen(hwnd, (left, top)) # 转换为屏幕绝对坐标
- with mss() as sct: # 定义截图区域(精确到客户区) monitor = { “left”: left, “top”: top, “width”: right – left, “height”: bot – top } # 捕获屏幕区域 sct_img = sct.grab(monitor) # 保存为PNG(自动处理BGRA转RGB) sct_img = sct_img.convert(“RGB”) sct_img.save(“window_mss.png”)
- 原因:GetWindowRect返回的是窗口外部矩形,包含非客户区。 解决:使用GetClientRect + ClientToScreen组合获取客户区绝对坐标,确保截图仅包含内容区域。
- 检测方法: from ctypes import windll dpi = windll.user32.GetDpiForWindow(hwnd) scale = dpi / 96.0 # 96为基准DPI adjusted_width = int((right – left) * scale) 处理:在monitor字典中使用调整后的尺寸。
- 验证:使用ctypes.windll.user32.GetMonitorInfo获取显示器物理范围。 示例: monitor_info = {} ctypes.windll.user32.GetMonitorInfoA(ctypes.windll.user32.MonitorFromWindow(hwnd, 1), ctypes.byref(monitor_info)) print(“显示器工作区:”, monitor_info[“rcWork”])
目录
- 1. 安装依赖库(需在本地执行)
- 2. 使用mss获取窗口图片的详细步骤
- 步骤1:获取窗口句柄及精确坐标
- 步骤2:配置mss截图参数
- 3. 关键问题处理
- 问题1:坐标偏移(如标题栏/边框)
- 问题2:DPI缩放导致尺寸错误
- 问题3:多显示器坐标系差异
- 4. 完整修正代码
- 5. 跨平台适配建议
- 6. 验证与调试技巧
您在使用mss时遇到的ModuleNotFoundError表明当前环境未安装该库。以下是完整解决方案,包含安装指导、代码逻辑详解及常见问题处理:
pip install mss pywin32
import win32gui
from mss import mss
# 获取窗口句柄
hwnd = win32gui.FindWindow(None, "记事本") # 替换为实际窗口标题
if hwnd == 0:
raise Exception("未找到目标窗口")
# 获取窗口客户区坐标(排除标题栏/边框)
left, top, right, bot = win32gui.GetClientRect(hwnd)
win32gui.ClientToScreen(hwnd, (left, top)) # 转换为屏幕绝对坐标
with mss() as sct:
# 定义截图区域(精确到客户区)
monitor = {
"left": left,
"top": top,
"width": right - left,
"height": bot - top
}
# 捕获屏幕区域
sct_img = sct.grab(monitor)
# 保存为PNG(自动处理BGRA转RGB)
sct_img = sct_img.convert("RGB")
sct_img.save("window_mss.png")
- 原因:
GetWindowRect返回的是窗口外部矩形,包含非客户区。
- 解决:使用
GetClientRect + ClientToScreen组合获取客户区绝对坐标,确保截图仅包含内容区域。
GetWindowRect返回的是窗口外部矩形,包含非客户区。GetClientRect + ClientToScreen组合获取客户区绝对坐标,确保截图仅包含内容区域。
检测方法:
from ctypes import windll dpi = windll.user32.GetDpiForWindow(hwnd) scale = dpi / 96.0 # 96为基准DPI adjusted_width = int((right - left) * scale)
处理:在monitor字典中使用调整后的尺寸。
- 验证:使用
ctypes.windll.user32.GetMonitorInfo获取显示器物理范围。
- 示例:
monitor_info = {}
ctypes.windll.user32.GetMonitorInfoA(ctypes.windll.user32.MonitorFromWindow(hwnd, 1), ctypes.byref(monitor_info))
print("显示器工作区:", monitor_info["rcWork"])
ctypes.windll.user32.GetMonitorInfo获取显示器物理范围。
import win32gui
from mss import mss
import ctypes
# 获取窗口句柄
hwnd = win32gui.FindWindow(None, "记事本")
if hwnd == 0:
raise Exception("未找到记事本窗口")
# 获取客户区坐标
left, top, right, bot = win32gui.GetClientRect(hwnd)
win32gui.ClientToScreen(hwnd, (left, top))
# 处理DPI缩放
dpi = ctypes.windll.user32.GetDpiForWindow(hwnd)
scale = dpi / 96.0
adjusted_left = int(left * scale)
adjusted_top = int(top * scale)
width = int((right - left) * scale)
height = int((bot - top) * scale)
# 使用mss截图
with mss() as sct:
monitor = {
"left": adjusted_left,
"top": adjusted_top,
"width": width,
"height": height
}
sct_img = sct.grab(monitor)
sct_img = sct_img.convert("RGB") # 转换颜色格式
sct_img.save("corrected_window.png")
print("截图已保存,尺寸:{}x{}".format(width, height))
macOS/Linux:使用Quartz或Xlib替代win32gui,逻辑类似:
# macOS示例(通过Quartz获取窗口ID)
from Quartz import CGWindowListCopyWindowInfo
windows = CGWindowListCopyWindowInfo(kCGWindowListOptionAll)
target_window = [w for w in windows if "记事本" in w.get("kCGWindowName", "")][0]
bounds = target_window["kCGWindowBounds"]
- 坐标验证:使用
print(monitor)输出截图区域坐标,与实际窗口对比。
- 边界测试:在纯色桌面背景下测试,检查截图边角是否与窗口边缘对齐。
- 性能优化:对于频繁截图场景,缓存窗口句柄和DPI值以减少重复计算。
print(monitor)输出截图区域坐标,与实际窗口对比。通过上述方法,可彻底解决窗口截图的位置偏差问题。如仍遇异常,建议使用pygetwindow库辅助验证窗口坐标,或通过pywin32的GetWindowPlacement进一步调试窗口状态。
到此这篇关于Python使用mss获取窗口图片的方法的文章就介绍到这了,更多相关Python mss获取窗口图片内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- Python使用pymssql连接SQL SEVER数据库全流程
- python中使用pymssql库操作MSSQL数据库
- python调用pymssql包操作SqlServer数据库的实现
- 使用Python操作MySql数据库和MsSql数据库