""" 调试工具集 用于开发和调试时的便捷功能 """ import sys import time import json from pathlib import Path from datetime import datetime sys.path.insert(0, str(Path(__file__).parent)) import win32api import win32gui import win32con from src.core.game_window import GameWindowManager from src.core.input_simulator import InputSimulator class CoordinateDebugger: """坐标调试器 - 实时显示鼠标坐标""" def __init__(self): self.window = None self.running = False def capture_window(self): """捕获游戏窗口""" self.window = GameWindowManager() if self.window.capture_window(): print(f"✅ 已捕获窗口: {self.window.window_title}") print(f" 窗口大小: {self.window.client_size}") return True else: print("❌ 未找到游戏窗口") return False def show_realtime_coords(self): """实时显示鼠标坐标""" print("\n" + "="*60) print("实时坐标显示") print("="*60) print("移动鼠标到游戏窗口内查看坐标") print("按 Ctrl+C 停止\n") if not self.window: print("⚠️ 请先捕获窗口 (选项 1)") return self.running = True last_pos = None try: while self.running: # 获取鼠标屏幕坐标 screen_x, screen_y = win32api.GetCursorPos() # 获取窗口信息 hwnd = self.window.hwnd if not hwnd: print("❌ 窗口已关闭") break # 获取窗口客户区位置 client_rect = win32gui.GetClientRect(hwnd) client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1])) # 计算窗口相对坐标 rel_x = screen_x - client_left rel_y = screen_y - client_top # 只在坐标变化时更新显示 current_pos = (rel_x, rel_y) if current_pos != last_pos: # 清行并显示新坐标 print(f"\r屏幕坐标: ({screen_x:4d}, {screen_y:4d}) | " f"窗口相对: ({rel_x:4d}, {rel_y:4d})", end="", flush=True) last_pos = current_pos time.sleep(0.05) except KeyboardInterrupt: print("\n\n已停止") self.running = False def test_click_at_current_pos(self): """在当前鼠标位置测试点击""" print("\n" + "="*60) print("测试点击 - 当前鼠标位置") print("="*60) if not self.window: print("⚠️ 请先捕获窗口 (选项 1)") return print("3秒后将点击当前鼠标位置...") time.sleep(3) # 获取当前鼠标位置 screen_x, screen_y = win32api.GetCursorPos() # 转换为窗口相对坐标 hwnd = self.window.hwnd client_rect = win32gui.GetClientRect(hwnd) client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1])) rel_x = screen_x - client_left rel_y = screen_y - client_top print(f"\n点击位置: 屏幕({screen_x}, {screen_y}) | 窗口相对({rel_x}, {rel_y})") # 执行点击 sim = InputSimulator(self.window) sim.click(rel_x, rel_y) print("✅ 点击完成") def test_click_at_coords(self): """在指定坐标测试点击""" print("\n" + "="*60) print("测试点击 - 指定坐标") print("="*60) if not self.window: print("⚠️ 请先捕获窗口 (选项 1)") return try: x = int(input("请输入 X 坐标: ")) y = int(input("请输入 Y 坐标: ")) except ValueError: print("❌ 无效的坐标") return print(f"\n将在 ({x}, {y}) 点击") print("3秒后开始...") time.sleep(3) sim = InputSimulator(self.window) sim.click(x, y) print("✅ 点击完成") class CoordinateRecorder: """坐标记录器 - 记录并保存常用坐标""" def __init__(self, save_file: str = "coordinates.json"): self.save_file = Path(save_file) self.coordinates = {} self.load() def load(self): """加载已保存的坐标""" if self.save_file.exists(): with open(self.save_file, 'r', encoding='utf-8') as f: self.coordinates = json.load(f) else: self.coordinates = {} def save(self): """保存坐标到文件""" with open(self.save_file, 'w', encoding='utf-8') as f: json.dump(self.coordinates, f, ensure_ascii=False, indent=2) print(f"✅ 坐标已保存到 {self.save_file}") def record_current_pos(self, name: str, window: GameWindowManager): """记录当前鼠标位置""" screen_x, screen_y = win32api.GetCursorPos() hwnd = window.hwnd client_rect = win32gui.GetClientRect(hwnd) client_left, client_top = win32gui.ClientToScreen(hwnd, (client_rect[0], client_rect[1])) rel_x = screen_x - client_left rel_y = screen_y - client_top self.coordinates[name] = { "x": rel_x, "y": rel_y, "screen_x": screen_x, "screen_y": screen_y, "recorded_at": datetime.now().isoformat() } print(f"✅ 已记录 '{name}': ({rel_x}, {rel_y})") def list_coordinates(self): """列出所有记录的坐标""" if not self.coordinates: print("⚠️ 没有记录的坐标") return print("\n" + "="*60) print("已记录的坐标:") print("="*60) for name, coord in self.coordinates.items(): print(f" {name}: ({coord['x']}, {coord['y']})") def get_coordinate(self, name: str) -> tuple: """获取指定名称的坐标""" if name in self.coordinates: coord = self.coordinates[name] return (coord['x'], coord['y']) return None def delete_coordinate(self, name: str): """删除指定坐标""" if name in self.coordinates: del self.coordinates[name] print(f"✅ 已删除 '{name}'") else: print(f"❌ 未找到 '{name}'") def show_menu(): """显示主菜单""" print("\n" + "="*60) print("调试工具菜单") print("="*60) print("1. 捕获游戏窗口") print("2. 实时显示鼠标坐标") print("3. 测试点击 - 当前鼠标位置") print("4. 测试点击 - 指定坐标") print("5. 记录当前坐标") print("6. 查看已记录的坐标") print("7. 删除坐标记录") print("8. 保存坐标到文件") print("0. 退出") def main(): """主函数""" debugger = CoordinateDebugger() recorder = CoordinateRecorder() print("="*60) print("LuoLuoTool 调试工具") print("="*60) print("请以管理员权限运行此脚本") while True: show_menu() choice = input("\n请选择功能 (0-8): ").strip() if choice == '0': print("\n感谢使用,再见!") break elif choice == '1': debugger.capture_window() elif choice == '2': debugger.show_realtime_coords() elif choice == '3': debugger.test_click_at_current_pos() elif choice == '4': debugger.test_click_at_coords() elif choice == '5': if not debugger.window: print("⚠️ 请先捕获窗口 (选项 1)") continue name = input("请输入坐标名称 (如: '主界面按钮', '开始游戏'): ").strip() if name: recorder.record_current_pos(name, debugger.window) else: print("❌ 名称不能为空") elif choice == '6': recorder.list_coordinates() elif choice == '7': recorder.list_coordinates() name = input("请输入要删除的坐标名称: ").strip() if name: recorder.delete_coordinate(name) elif choice == '8': recorder.save() else: print("❌ 无效选项") if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\n\n程序被用户中断") except Exception as e: print(f"\n❌ 发生错误: {e}") import traceback traceback.print_exc()