98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
"""
|
|
游戏窗口管理
|
|
"""
|
|
|
|
import win32gui
|
|
import win32con
|
|
from typing import Optional, Tuple
|
|
from src.utils.logger import logger
|
|
|
|
|
|
class GameWindowManager:
|
|
"""游戏窗口管理器"""
|
|
|
|
# 游戏窗口类名和标题
|
|
GAME_CLASS_NAME = "UnityWndClass" # Unity游戏常用类名
|
|
GAME_WINDOW_TITLE = "桃源深处有人家"
|
|
|
|
def __init__(self):
|
|
self._hwnd: Optional[int] = None
|
|
self._window_rect: Tuple[int, int, int, int] = (0, 0, 0, 0)
|
|
|
|
@property
|
|
def is_window_captured(self) -> bool:
|
|
"""是否已捕获窗口"""
|
|
if self._hwnd is None:
|
|
return False
|
|
return win32gui.IsWindow(self._hwnd)
|
|
|
|
@property
|
|
def hwnd(self) -> Optional[int]:
|
|
"""窗口句柄"""
|
|
return self._hwnd
|
|
|
|
@property
|
|
def window_rect(self) -> Tuple[int, int, int, int]:
|
|
"""窗口矩形 (left, top, right, bottom)"""
|
|
if self.is_window_captured:
|
|
self._window_rect = win32gui.GetWindowRect(self._hwnd)
|
|
return self._window_rect
|
|
|
|
@property
|
|
def client_size(self) -> Tuple[int, int]:
|
|
"""客户端区域大小 (width, height)"""
|
|
if not self.is_window_captured:
|
|
return (0, 0)
|
|
left, top, right, bottom = self.window_rect
|
|
return (right - left, bottom - top)
|
|
|
|
def find_window(self) -> bool:
|
|
"""查找游戏窗口"""
|
|
# 先尝试精确匹配
|
|
hwnd = win32gui.FindWindow(None, self.GAME_WINDOW_TITLE)
|
|
|
|
# 如果没找到,尝试模糊匹配
|
|
if hwnd == 0:
|
|
def callback(hwnd, extra):
|
|
if win32gui.IsWindowVisible(hwnd):
|
|
title = win32gui.GetWindowText(hwnd)
|
|
if self.GAME_WINDOW_TITLE in title:
|
|
extra.append(hwnd)
|
|
return True
|
|
|
|
windows = []
|
|
win32gui.EnumWindows(callback, windows)
|
|
if windows:
|
|
hwnd = windows[0]
|
|
|
|
if hwnd != 0:
|
|
self._hwnd = hwnd
|
|
self._window_rect = win32gui.GetWindowRect(hwnd)
|
|
logger.info(f"找到游戏窗口: {hwnd}, 大小: {self.client_size}")
|
|
return True
|
|
|
|
logger.warning("未找到游戏窗口")
|
|
return False
|
|
|
|
def capture_window(self) -> bool:
|
|
"""捕获游戏窗口"""
|
|
return self.find_window()
|
|
|
|
def bring_to_front(self):
|
|
"""将窗口置前"""
|
|
if self.is_window_captured:
|
|
win32gui.SetForegroundWindow(self._hwnd)
|
|
|
|
def click(self, x: int, y: int):
|
|
"""在窗口内点击"""
|
|
if not self.is_window_captured:
|
|
return
|
|
|
|
left, top, _, _ = self.window_rect
|
|
# 转换为屏幕坐标
|
|
screen_x = left + x
|
|
screen_y = top + y
|
|
|
|
# TODO: 使用pyautogui或win32api发送点击
|
|
logger.debug(f"点击坐标: ({screen_x}, {screen_y})")
|