可以稳刷的单机版本

This commit is contained in:
Ray
2025-10-29 10:28:38 +08:00
commit 8294cab51b
21 changed files with 897 additions and 0 deletions

115
utils/WindowsAPI.py Normal file
View File

@@ -0,0 +1,115 @@
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()