116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
import numpy, cv2
|
|
import win32gui, win32api, win32con, win32ui
|
|
import time
|
|
from PIL import Image
|
|
def get_window_position(window_title):
|
|
"""
|
|
获取指定窗口的左上角在桌面的位置
|
|
:param window_title: 窗口标题(支持模糊匹配)
|
|
:return: (x, y) 坐标元组,未找到返回 None
|
|
"""
|
|
# 查找目标窗口句柄
|
|
target_hwnd = None
|
|
|
|
def enum_windows_callback(hwnd, _):
|
|
nonlocal target_hwnd
|
|
if win32gui.IsWindowVisible(hwnd):
|
|
title = win32gui.GetWindowText(hwnd)
|
|
if window_title.lower() in title.lower():
|
|
# 检查是否是顶级窗口(排除子窗口)
|
|
if win32gui.GetParent(hwnd) == 0:
|
|
target_hwnd = hwnd
|
|
return False # 停止枚举
|
|
return True # 继续枚举
|
|
|
|
# 枚举所有窗口
|
|
win32gui.EnumWindows(enum_windows_callback, None)
|
|
|
|
# 获取窗口位置
|
|
if target_hwnd:
|
|
rect = win32gui.GetWindowRect(target_hwnd)
|
|
return rect[0], rect[1]
|
|
return None, None
|
|
class WindowsAPI():
|
|
|
|
def __init__(self, hwnd=None, region=None):
|
|
# 如果传入 hwnd 则直接使用传入的句柄,否则设为 None
|
|
self.hWnd = hwnd
|
|
self.region = region # region 格式为 (left, top, right, bottom)
|
|
|
|
def setRegion(self, region):
|
|
"""设置截图区域"""
|
|
self.region = region
|
|
|
|
def getDesktopImg(self):
|
|
if not self.region:
|
|
print("请传入有效的截图区域")
|
|
return None
|
|
|
|
left, top, right, bottom = self.region
|
|
width = right - left
|
|
height = bottom - top
|
|
|
|
# 获取桌面的设备上下文句柄
|
|
hWndDC = win32gui.GetWindowDC(win32gui.GetDesktopWindow())
|
|
# 创建设备描述表
|
|
mfcDC = win32ui.CreateDCFromHandle(hWndDC)
|
|
# 内存设备描述表
|
|
saveDC = mfcDC.CreateCompatibleDC()
|
|
# 创建位图对象
|
|
saveBitMap = win32ui.CreateBitmap()
|
|
# 分配存储空间
|
|
saveBitMap.CreateCompatibleBitmap(mfcDC, width, height)
|
|
# 将位图对象选入到内存设备描述表
|
|
saveDC.SelectObject(saveBitMap)
|
|
|
|
# 截取指定区域
|
|
saveDC.BitBlt((0, 0), (width, height), mfcDC, (left, top), win32con.SRCCOPY)
|
|
|
|
# 获取位图信息
|
|
signedIntsArray = saveBitMap.GetBitmapBits(True)
|
|
im_opencv = numpy.frombuffer(signedIntsArray, dtype='uint8')
|
|
im_opencv.shape = (height, width, 4)
|
|
|
|
# 内存释放
|
|
win32gui.DeleteObject(saveBitMap.GetHandle())
|
|
saveDC.DeleteDC()
|
|
mfcDC.DeleteDC()
|
|
win32gui.ReleaseDC(win32gui.GetDesktopWindow(), hWndDC)
|
|
|
|
im_opencv = cv2.cvtColor(im_opencv, cv2.COLOR_BGR2RGB) # rgb 修改通道数并转换图像
|
|
# im_opencv=im_opencv[40:-1, 2:]
|
|
im_PIL = Image.fromarray(im_opencv) # 图像改成对象类型
|
|
return [im_opencv,im_PIL]
|
|
|
|
def showDesktopImg(self):
|
|
imgs = self.getDesktopImg()
|
|
|
|
if imgs is None:
|
|
print("无法获取截图")
|
|
return
|
|
|
|
im_opencv = imgs[0] # 取 OpenCV 图像
|
|
cv2.imshow("Desktop Screenshot", im_opencv)
|
|
cv2.waitKey(0)
|
|
cv2.destroyAllWindows()
|
|
|
|
|
|
# window_title = "Torchlight:Infinite"
|
|
# left, top = get_window_position(window_title)
|
|
#
|
|
# if left is None or top is None:
|
|
# print(f"错误: 未找到标题包含 '{window_title}' 的窗口")
|
|
# exit(1)
|
|
#
|
|
# print(f"找到窗口 '{window_title}' 位置: ({left}, {top})")
|
|
|
|
# 2. 设置截图区域 (左上角x, 左上角y, 右下角x, 右下角y)
|
|
# width, height = 1282, 761
|
|
|
|
custom_region = (0, 30, 1280, 30+720)
|
|
winApi = WindowsAPI(region=custom_region)
|
|
print(winApi.region)
|
|
# winApi.showDesktopImg()
|
|
|
|
|