first commit

This commit is contained in:
王鹏
2026-03-18 09:04:37 +08:00
commit b7719b377d
121 changed files with 116104 additions and 0 deletions

262
wow.md Normal file
View File

@@ -0,0 +1,262 @@
import sys
from PyQt6.QtWidgets import *
from PyQt6.QtCore import QThread, pyqtSignal, Qt
from PyQt6.QtGui import QIcon
import win32gui, win32api, win32con
import time, random, json, os
class KeyConfigWidget(QWidget):
"""单个按键配置组件"""
def __init__(self, key_name, default_config):
super().__init__()
self.key_name = key_name
self.config = default_config or {'enabled': False, 'interval': 10, 'jitter': 2}
self.init_ui()
def init_ui(self):
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
# 启用复选框
self.checkbox = QCheckBox(f"按键 [{self.key_name}]")
self.checkbox.setChecked(self.config['enabled'])
layout.addWidget(self.checkbox)
# 间隔
layout.addWidget(QLabel("间隔:"))
self.interval_spin = QSpinBox()
self.interval_spin.setRange(1, 60)
self.interval_spin.setValue(self.config['interval'])
layout.addWidget(self.interval_spin)
layout.addWidget(QLabel("秒"))
# 随机延迟
layout.addWidget(QLabel("随机:"))
self.jitter_spin = QSpinBox()
self.jitter_spin.setRange(0, 10)
self.jitter_spin.setValue(self.config['jitter'])
layout.addWidget(self.jitter_spin)
layout.addWidget(QLabel("秒"))
layout.addStretch()
# 连接信号
self.checkbox.toggled.connect(self.on_toggle)
self.on_toggle()
def on_toggle(self):
enabled = self.checkbox.isChecked()
self.interval_spin.setEnabled(enabled)
self.jitter_spin.setEnabled(enabled)
def get_config(self):
return {
'enabled': self.checkbox.isChecked(),
'interval': self.interval_spin.value(),
'jitter': self.jitter_spin.value()
}
class KeyWorker(QThread):
"""按键工作线程"""
log_signal = pyqtSignal(str)
def __init__(self, hwnd, key_name, config):
super().__init__()
self.hwnd = hwnd
self.key_name = key_name
self.config = config
self.running = True
def run(self):
while self.running:
if self.config['enabled']:
self.press_key()
# 随机间隔
sleep_time = self.config['interval'] + random.uniform(-self.config['jitter'], self.config['jitter'])
sleep_time = max(1, sleep_time)
for _ in range(int(sleep_time * 2)):
if not self.running:
break
time.sleep(0.5)
def press_key(self):
"""发送按键"""
if not self.hwnd:
return
key_map = {
'空格(跳跃)': win32con.VK_SPACE,
'1': 0x31, '2': 0x32, '3': 0x33, '4': 0x34, '5': 0x35
}
vk = key_map.get(self.key_name)
if vk:
try:
win32api.PostMessage(self.hwnd, win32con.WM_KEYDOWN, vk, 0)
time.sleep(random.uniform(0.05, 0.15))
win32api.PostMessage(self.hwnd, win32con.WM_KEYUP, vk, 0)
key_type = "跳跃" if self.key_name == '空格(跳跃)' else f"技能 {self.key_name}"
self.log_signal.emit(f"➡️ 执行 {key_type}")
except Exception as e:
self.log_signal.emit(f"❌ 按键 {self.key_name} 失败: {e}")
class WoWMultiKeyGUI(QMainWindow):
def __init__(self):
super().__init__()
self.config_file = "wow_multikey_qt.json"
self.config = self.load_config()
self.workers = {}
self.hwnd = None
self.init_ui()
self.find_wow_window()
def init_ui(self):
self.setWindowTitle("WoW多键控制器")
self.setGeometry(100, 100, 700, 550)
central = QWidget()
self.setCentralWidget(central)
layout = QVBoxLayout(central)
# 窗口状态
self.window_label = QLabel("正在查找窗口...")
layout.addWidget(self.window_label)
self.refresh_btn = QPushButton("刷新窗口")
self.refresh_btn.clicked.connect(self.find_wow_window)
layout.addWidget(self.refresh_btn)
# 按键配置
self.key_widgets = {}
keys = ['空格(跳跃)', '1', '2', '3', '4', '5']
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll_widget = QWidget()
scroll_layout = QVBoxLayout(scroll_widget)
for key in keys:
widget = KeyConfigWidget(key, self.config.get(key))
scroll_layout.addWidget(widget)
self.key_widgets[key] = widget
scroll_layout.addStretch()
scroll.setWidget(scroll_widget)
layout.addWidget(scroll)
# 按钮
btn_layout = QHBoxLayout()
self.start_btn = QPushButton("🚀 启动")
self.start_btn.clicked.connect(self.start_all)
self.stop_btn = QPushButton("⏹ 停止")
self.stop_btn.clicked.connect(self.stop_all)
self.stop_btn.setEnabled(False)
btn_layout.addWidget(self.start_btn)
btn_layout.addWidget(self.stop_btn)
btn_layout.addStretch()
layout.addLayout(btn_layout)
# 日志
self.log_text = QTextEdit()
self.log_text.setReadOnly(True)
self.log_text.setMaximumHeight(150)
layout.addWidget(self.log_text)
# 状态栏
self.status_bar = self.statusBar()
self.status_bar.showMessage("就绪")
def load_config(self):
if os.path.exists(self.config_file):
try:
with open(self.config_file, "r") as f:
return json.load(f)
except:
pass
return {}
def save_config(self):
config = {key: widget.get_config() for key, widget in self.key_widgets.items()}
with open(self.config_file, "w") as f:
json.dump(config, f, indent=2)
def find_wow_window(self):
titles = ["魔兽世界", "World of Warcraft"]
for title in titles:
self.hwnd = win32gui.FindWindow(None, title)
if self.hwnd:
self.window_label.setText(f"✅ 已找到: {title}")
self.log(f"成功绑定窗口: {title}")
return
self.window_label.setText("❌ 未找到游戏窗口")
self.hwnd = None
def log(self, message):
self.log_text.append(f"[{time.strftime('%H:%M:%S')}] {message}")
def start_all(self):
if not self.hwnd:
QMessageBox.warning(self, "警告", "未找到游戏窗口!")
return
any_enabled = any(w.get_config()['enabled'] for w in self.key_widgets.values())
if not any_enabled:
QMessageBox.warning(self, "警告", "请至少启用一个按键!")
return
self.save_config()
# 启动工作线程
for key_name, widget in self.key_widgets.items():
config = widget.get_config()
if config['enabled']:
worker = KeyWorker(self.hwnd, key_name, config)
worker.log_signal.connect(self.log)
worker.start()
self.workers[key_name] = worker
self.start_btn.setEnabled(False)
self.stop_btn.setEnabled(True)
self.status_bar.showMessage("🟢 运行中")
self.log("🎮 自动按键已启动")
def stop_all(self):
for worker in self.workers.values():
worker.running = False
worker.wait()
self.workers.clear()
self.start_btn.setEnabled(True)
self.stop_btn.setEnabled(False)
self.status_bar.showMessage("⏹️ 已停止")
self.log("🛑 所有按键已停止")
def closeEvent(self, event):
if self.workers:
reply = QMessageBox.question(self, "退出", "确认退出?")
if reply == QMessageBox.StandardButton.Yes:
self.stop_all()
event.accept()
else:
event.ignore()
else:
event.accept()
def main():
app = QApplication(sys.argv)
window = WoWMultiKeyGUI()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()