更新:添加鼠标图标识别、复活逻辑优化、参数配置加载修复、目标血量100%检测
This commit is contained in:
@@ -1,16 +1,12 @@
|
||||
import os
|
||||
import sys
|
||||
import ctypes
|
||||
from ctypes import *
|
||||
import time
|
||||
import win32com.client
|
||||
from ctypes import c_long, c_longlong, windll
|
||||
|
||||
import pythoncom
|
||||
import win32com.client
|
||||
|
||||
|
||||
class HardwareController:
|
||||
"""
|
||||
接入 wyhkm.dll 硬件盒子的 COM 接口封装类。
|
||||
经过实测验证:Index 0 配合 SetMode(2, 1) 可同时支持键盘与鼠标。
|
||||
"""
|
||||
_instance = None
|
||||
_wyhkm = None
|
||||
|
||||
@@ -19,134 +15,189 @@ class HardwareController:
|
||||
cls._instance = super(HardwareController, cls).__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def _runtime_base_dir(self):
|
||||
if getattr(sys, "frozen", False):
|
||||
return os.path.dirname(sys.executable)
|
||||
return os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
def _resolve_resource_path(self, relative_path):
|
||||
if os.path.isabs(relative_path):
|
||||
return relative_path if os.path.exists(relative_path) else None
|
||||
|
||||
candidates = []
|
||||
if getattr(sys, "frozen", False):
|
||||
exe_dir = os.path.dirname(sys.executable)
|
||||
if exe_dir:
|
||||
candidates.append(os.path.join(exe_dir, relative_path))
|
||||
meipass = getattr(sys, "_MEIPASS", "")
|
||||
if meipass:
|
||||
candidates.append(os.path.join(meipass, relative_path))
|
||||
|
||||
module_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
candidates.append(os.path.join(module_dir, relative_path))
|
||||
candidates.append(os.path.abspath(relative_path))
|
||||
|
||||
seen = set()
|
||||
for candidate in candidates:
|
||||
candidate = os.path.abspath(candidate)
|
||||
if candidate in seen:
|
||||
continue
|
||||
seen.add(candidate)
|
||||
if os.path.exists(candidate):
|
||||
return candidate
|
||||
return None
|
||||
|
||||
def _log(self, message):
|
||||
print(message)
|
||||
try:
|
||||
log_path = os.path.join(self._runtime_base_dir(), "hardware_control.log")
|
||||
with open(log_path, "a", encoding="utf-8") as f:
|
||||
f.write(message + "\n")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def __init__(self, dll_path="ddl/wyhkm.dll"):
|
||||
if self._wyhkm:
|
||||
return
|
||||
|
||||
self.dll_path = os.path.abspath(dll_path)
|
||||
if not os.path.exists(self.dll_path):
|
||||
print(f">>> [硬件控制] 错误:找不到 DLL 文件 {self.dll_path}")
|
||||
|
||||
self.dll_path = self._resolve_resource_path(dll_path)
|
||||
if not self.dll_path:
|
||||
self._log(f">>> [hardware_control] DLL not found: {dll_path}")
|
||||
return
|
||||
|
||||
try:
|
||||
# 1. 进程内注册 (标准 64 位注册方式)
|
||||
hkmdll = windll.LoadLibrary(self.dll_path)
|
||||
hkmdll.DllInstall.argtypes = (c_long, c_longlong)
|
||||
|
||||
if hkmdll.DllInstall(1, 2) < 0:
|
||||
print(">>> [硬件控制] 注册失败!")
|
||||
return
|
||||
else:
|
||||
print(">>> [硬件控制] 进程内注册 wyhkm.dll 成功")
|
||||
|
||||
# 2. 创建对象
|
||||
if hkmdll.DllInstall(1, 2) < 0:
|
||||
self._log(">>> [hardware_control] DllInstall failed")
|
||||
return
|
||||
|
||||
self._log(f">>> [hardware_control] DllInstall ok: {self.dll_path}")
|
||||
|
||||
pythoncom.CoInitialize()
|
||||
try:
|
||||
self._wyhkm = win32com.client.Dispatch("wyp.hkm")
|
||||
except Exception as e:
|
||||
print(f">>> [硬件控制] 创建对象失败: {e}")
|
||||
self._log(f">>> [hardware_control] COM Dispatch failed: {e}")
|
||||
return
|
||||
|
||||
# 3. 查找并打开设备 (Index 0 已验证支持键盘鼠标)
|
||||
|
||||
dev_id = self._wyhkm.SearchDevice(0x2612, 0x1701, 0)
|
||||
if dev_id == -1:
|
||||
print(">>> [硬件控制] 未找到无涯键鼠盒子 (Index 0)")
|
||||
self._log(">>> [hardware_control] Device not found (Index 0)")
|
||||
self._wyhkm = None
|
||||
return
|
||||
|
||||
if not self._wyhkm.Open(dev_id, 0):
|
||||
print(">>> [硬件控制] 打开设备失败")
|
||||
self._log(">>> [hardware_control] Open device failed")
|
||||
self._wyhkm = None
|
||||
return
|
||||
|
||||
# 4. 关键初始化设置 (实测鼠标移动必须开启模式 2, 1)
|
||||
# 开启键盘增强模拟
|
||||
self._wyhkm.SetMode(1, 1)
|
||||
# 开启鼠标仿真移动 (解决鼠标不动的问题)
|
||||
self._wyhkm.SetMode(2, 1)
|
||||
|
||||
# 设置推荐的按键/鼠标间隔 (与 test_hw.py 一致,30-50ms 更稳定)
|
||||
|
||||
self._wyhkm.SetMode(1, 1)
|
||||
self._wyhkm.SetMode(2, 1)
|
||||
self._wyhkm.SetKeyInterval(30, 50)
|
||||
self._wyhkm.SetMouseInterval(30, 50)
|
||||
|
||||
print(f">>> [硬件控制] 成功打开设备并完成初始化配置")
|
||||
|
||||
self._log(f">>> [hardware_control] Device opened and initialized: {dev_id}")
|
||||
except Exception as e:
|
||||
print(f">>> [硬件控制] 初始化异常: {e}")
|
||||
self._log(f">>> [hardware_control] Init failed: {e}")
|
||||
self._wyhkm = None
|
||||
|
||||
def is_available(self):
|
||||
if not self._wyhkm:
|
||||
return False
|
||||
try:
|
||||
# 修正:IsOpen 需要参数 (0:全模式, 1:键盘, 2:鼠标)
|
||||
# 之前漏传参数会导致 COM 报错,进而导致 key_down 等所有操作被 skip
|
||||
return self._wyhkm.IsOpen(0)
|
||||
except:
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
def delay_rnd(self, min_ms, max_ms):
|
||||
"""随机延时"""
|
||||
if self.is_available():
|
||||
try: self._wyhkm.DelayRnd(int(min_ms), int(max_ms))
|
||||
except: pass
|
||||
|
||||
# --- 键盘操作 (均使用大写字符串) ---
|
||||
try:
|
||||
self._wyhkm.DelayRnd(int(min_ms), int(max_ms))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def key_down(self, key_str):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.KeyDown(str(key_str).upper())
|
||||
except: pass
|
||||
try:
|
||||
self._wyhkm.KeyDown(str(key_str).upper())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def key_up(self, key_str):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.KeyUp(str(key_str).upper())
|
||||
except: pass
|
||||
try:
|
||||
self._wyhkm.KeyUp(str(key_str).upper())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def key_press(self, key_str):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.KeyPress(str(key_str).upper())
|
||||
except: pass
|
||||
try:
|
||||
self._wyhkm.KeyPress(str(key_str).upper())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 兼容性别名
|
||||
def keyDown(self, key_str): self.key_down(key_str)
|
||||
def keyUp(self, key_str): self.key_up(key_str)
|
||||
def press(self, key_str): self.key_press(key_str)
|
||||
def keyDown(self, key_str):
|
||||
self.key_down(key_str)
|
||||
|
||||
def keyUp(self, key_str):
|
||||
self.key_up(key_str)
|
||||
|
||||
def press(self, key_str):
|
||||
self.key_press(key_str)
|
||||
|
||||
# --- 鼠标操作 ---
|
||||
|
||||
def move_to(self, x, y):
|
||||
"""绝对移动"""
|
||||
if self.is_available():
|
||||
try: self._wyhkm.MoveTo(int(x), int(y))
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.MoveTo(int(x), int(y)))
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] MoveTo failed ({x}, {y}): {e}")
|
||||
return False
|
||||
|
||||
def move_r(self, dx, dy):
|
||||
"""相对移动"""
|
||||
if self.is_available():
|
||||
try: self._wyhkm.MoveR(int(dx), int(dy))
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.MoveR(int(dx), int(dy)))
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] MoveR failed ({dx}, {dy}): {e}")
|
||||
return False
|
||||
|
||||
def MoveR(self, dx, dy): # 兼容写法
|
||||
def MoveR(self, dx, dy):
|
||||
self.move_r(dx, dy)
|
||||
|
||||
def left_click(self):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.LeftClick()
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.LeftClick())
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] LeftClick failed: {e}")
|
||||
return False
|
||||
|
||||
def right_click(self):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.RightClick()
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.RightClick())
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] RightClick failed: {e}")
|
||||
return False
|
||||
|
||||
def left_down(self):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.LeftDown()
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.LeftDown())
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] LeftDown failed: {e}")
|
||||
return False
|
||||
|
||||
def left_up(self):
|
||||
if self.is_available():
|
||||
try: self._wyhkm.LeftUp()
|
||||
except: pass
|
||||
try:
|
||||
return bool(self._wyhkm.LeftUp())
|
||||
except Exception as e:
|
||||
self._log(f">>> [hardware_control] LeftUp failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# 全局实例
|
||||
hw_ctrl = HardwareController()
|
||||
|
||||
Reference in New Issue
Block a user