| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906 |
- import sys
- import time
- import win32gui
- import win32con
- import win32api
- import win32process
- import threading
- from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
- QHBoxLayout, QPushButton, QListWidget, QListWidgetItem,
- QMessageBox, QLabel, QLineEdit, QGroupBox, QTextEdit,
- QSplitter, QComboBox, QSpinBox, QCheckBox, QRadioButton,
- QButtonGroup)
- from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QObject
- from PyQt5.QtGui import QFont
- class WorkerSignals(QObject):
- """工作线程信号"""
- status = pyqtSignal(str)
- progress = pyqtSignal(int, int) # 当前索引, 总数
- finished = pyqtSignal()
- class WindowManagerApp(QMainWindow):
- def __init__(self):
- super().__init__()
- self.window_handles = []
- self.all_windows = []
- self.is_running = False
- self.should_stop = False # 停止标志
- self.initUI()
-
- def initUI(self):
- """初始化界面"""
- self.setWindowTitle('霸器窗口自动点击工具 - 多窗口批量执行')
- self.setGeometry(100, 100, 950, 750)
-
- # 设置主窗口样式
- self.setStyleSheet("""
- QMainWindow {
- background-color: #2b2b2b;
- }
- QGroupBox {
- color: #ffffff;
- border: 2px solid #555;
- border-radius: 5px;
- margin-top: 10px;
- font-weight: bold;
- }
- QGroupBox::title {
- subcontrol-origin: margin;
- left: 10px;
- padding: 0 5px 0 5px;
- }
- QPushButton {
- background-color: #4a4a4a;
- color: white;
- border: 1px solid #555;
- padding: 8px 16px;
- border-radius: 4px;
- font-weight: bold;
- font-size: 12px;
- }
- QPushButton:hover {
- background-color: #5a5a5a;
- }
- QPushButton:pressed {
- background-color: #3a3a3a;
- }
- QPushButton#refreshBtn {
- background-color: #0078d4;
- }
- QPushButton#refreshBtn:hover {
- background-color: #1a8ad4;
- }
- QPushButton#startBtn {
- background-color: #107c10;
- font-size: 14px;
- padding: 12px 24px;
- }
- QPushButton#startBtn:hover {
- background-color: #1a8c1a;
- }
- QPushButton#startBtn:disabled {
- background-color: #555;
- }
- QPushButton#stopBtn {
- background-color: #d13438;
- font-size: 14px;
- padding: 12px 24px;
- }
- QPushButton#stopBtn:hover {
- background-color: #e14448;
- }
- QListWidget {
- background-color: #3c3c3c;
- color: #ffffff;
- border: 1px solid #555;
- border-radius: 4px;
- padding: 5px;
- }
- QListWidget::item {
- padding: 8px;
- border-bottom: 1px solid #444;
- }
- QListWidget::item:selected {
- background-color: #0078d4;
- }
- QLabel {
- color: #cccccc;
- }
- QCheckBox {
- color: #ffffff;
- font-size: 12px;
- padding: 5px;
- }
- QCheckBox::indicator {
- width: 18px;
- height: 18px;
- }
- QCheckBox::indicator:unchecked {
- background-color: #3c3c3c;
- border: 2px solid #555;
- border-radius: 3px;
- }
- QCheckBox::indicator:checked {
- background-color: #0078d4;
- border: 2px solid #0078d4;
- border-radius: 3px;
- }
- QRadioButton {
- color: #ffffff;
- font-size: 12px;
- padding: 5px;
- }
- QRadioButton::indicator {
- width: 18px;
- height: 18px;
- }
- QRadioButton::indicator:unchecked {
- background-color: #3c3c3c;
- border: 2px solid #555;
- border-radius: 9px;
- }
- QRadioButton::indicator:checked {
- background-color: #0078d4;
- border: 2px solid #0078d4;
- border-radius: 9px;
- }
- QLineEdit, QComboBox, QSpinBox {
- background-color: #3c3c3c;
- color: #ffffff;
- border: 1px solid #555;
- border-radius: 4px;
- padding: 5px;
- }
- QTextEdit {
- background-color: #1e1e1e;
- color: #00ff00;
- border: 1px solid #555;
- border-radius: 4px;
- font-family: 'Consolas', monospace;
- font-size: 10pt;
- }
- """)
-
- # 创建中央窗口
- central_widget = QWidget()
- self.setCentralWidget(central_widget)
- main_layout = QVBoxLayout(central_widget)
-
- # 标题
- title_label = QLabel('霸器窗口自动点击工具 - 批量执行')
- title_label.setAlignment(Qt.AlignCenter)
- title_font = QFont('Arial', 18, QFont.Bold)
- title_label.setFont(title_font)
- title_label.setStyleSheet('color: #00b4d8; margin: 15px;')
- main_layout.addWidget(title_label)
-
- # 控制区域
- control_group = QGroupBox('控制面板')
- control_layout = QHBoxLayout()
-
- self.refresh_btn = QPushButton('🔄 加载窗口')
- self.refresh_btn.setObjectName('refreshBtn')
- self.refresh_btn.clicked.connect(self.load_processes)
- control_layout.addWidget(self.refresh_btn)
-
- self.filter_label = QLabel('筛选:')
- control_layout.addWidget(self.filter_label)
-
- self.filter_input = QLineEdit()
- self.filter_input.setPlaceholderText('输入标题关键词过滤...')
- self.filter_input.textChanged.connect(self.filter_list)
- control_layout.addWidget(self.filter_input)
-
- # 显示模式选择
- self.show_mode_combo = QComboBox()
- self.show_mode_combo.addItems(['所有窗口', '仅可见窗口', '仅隐藏窗口'])
- self.show_mode_combo.currentTextChanged.connect(self.on_show_mode_changed)
- control_layout.addWidget(QLabel('显示:'))
- control_layout.addWidget(self.show_mode_combo)
-
- control_group.setLayout(control_layout)
- main_layout.addWidget(control_group)
-
- # 复选框区域 - 功能选择
- checkbox_group = QGroupBox('功能选择')
- checkbox_layout = QHBoxLayout()
-
- self.cb_molong = QCheckBox('争夺魔龙之心')
- self.cb_molong.setChecked(False)
- checkbox_layout.addWidget(self.cb_molong)
-
- self.cb_feicui = QCheckBox('翡翠荣耀旗')
- self.cb_feicui.setChecked(False)
- checkbox_layout.addWidget(self.cb_feicui)
-
- self.cb_jinyan = QCheckBox('金岩霸者棋')
- self.cb_jinyan.setChecked(False)
- checkbox_layout.addWidget(self.cb_jinyan)
-
- self.cb_chiyan = QCheckBox('炽焰战神棋')
- self.cb_chiyan.setChecked(False)
- checkbox_layout.addWidget(self.cb_chiyan)
-
- checkbox_group.setLayout(checkbox_layout)
- main_layout.addWidget(checkbox_group)
-
- # 单选按钮区域 - 皇宫占位
- radio_group = QGroupBox('皇宫占位位置')
- radio_layout = QHBoxLayout()
-
- self.radio_random = QRadioButton('随机')
- self.radio_random.setChecked(True)
- radio_layout.addWidget(self.radio_random)
-
- self.radio_door = QRadioButton('门口')
- radio_layout.addWidget(self.radio_door)
-
- self.radio_corner = QRadioButton('角落')
- radio_layout.addWidget(self.radio_corner)
-
- # 将单选按钮分组
- self.radio_button_group = QButtonGroup()
- self.radio_button_group.addButton(self.radio_random)
- self.radio_button_group.addButton(self.radio_door)
- self.radio_button_group.addButton(self.radio_corner)
-
- radio_group.setLayout(radio_layout)
- main_layout.addWidget(radio_group)
-
- # 窗口列表 - 支持多选
- list_group = QGroupBox('窗口列表 (霸器-开头) - 可多选')
- list_layout = QVBoxLayout()
-
- self.window_list = QListWidget()
- self.window_list.setSelectionMode(QListWidget.MultiSelection) # 改为多选模式
- self.window_list.itemDoubleClicked.connect(self.show_selected_window)
- list_layout.addWidget(self.window_list)
-
- # 添加全选/取消全选按钮
- select_layout = QHBoxLayout()
- self.select_all_btn = QPushButton('全选')
- self.select_all_btn.clicked.connect(self.select_all_items)
- select_layout.addWidget(self.select_all_btn)
-
- self.deselect_all_btn = QPushButton('取消全选')
- self.deselect_all_btn.clicked.connect(self.deselect_all_items)
- select_layout.addWidget(self.deselect_all_btn)
-
- self.selected_count_label = QLabel('已选: 0 个窗口')
- self.selected_count_label.setStyleSheet('color: #00b4d8;')
- select_layout.addWidget(self.selected_count_label)
- select_layout.addStretch()
-
- list_layout.addLayout(select_layout)
-
- list_group.setLayout(list_layout)
- main_layout.addWidget(list_group)
-
- # 操作按钮区域
- action_group = QGroupBox('操作')
- action_layout = QHBoxLayout()
-
- self.start_btn = QPushButton('▶️ 开始批量执行')
- self.start_btn.setObjectName('startBtn')
- self.start_btn.clicked.connect(self.start_auto_click)
- action_layout.addWidget(self.start_btn)
-
- self.stop_btn = QPushButton('⏹️ 停止')
- self.stop_btn.setObjectName('stopBtn')
- self.stop_btn.clicked.connect(self.stop_auto_click)
- self.stop_btn.setEnabled(False)
- action_layout.addWidget(self.stop_btn)
-
- self.show_btn = QPushButton('👁️ 显示选中窗口')
- self.show_btn.setObjectName('showBtn')
- self.show_btn.clicked.connect(self.show_selected_window)
- action_layout.addWidget(self.show_btn)
-
- action_group.setLayout(action_layout)
- main_layout.addWidget(action_group)
-
- # 日志区域
- log_group = QGroupBox('运行日志')
- log_layout = QVBoxLayout()
-
- self.log_text = QTextEdit()
- self.log_text.setReadOnly(True)
- self.log_text.setMaximumHeight(150)
- log_layout.addWidget(self.log_text)
-
- log_group.setLayout(log_layout)
- main_layout.addWidget(log_group)
-
- # 状态栏
- self.status_label = QLabel('就绪')
- self.status_label.setStyleSheet('color: #888; margin: 5px;')
- main_layout.addWidget(self.status_label)
-
- # 自动加载
- self.load_processes()
-
- # 工作线程信号
- self.signals = WorkerSignals()
- self.signals.status.connect(self.update_status)
- self.signals.progress.connect(self.update_progress)
- self.signals.finished.connect(self.on_finished)
-
- def select_all_items(self):
- """全选所有窗口"""
- for i in range(self.window_list.count()):
- item = self.window_list.item(i)
- if not item.isHidden():
- item.setSelected(True)
- self.update_selected_count()
-
- def deselect_all_items(self):
- """取消全选"""
- self.window_list.clearSelection()
- self.update_selected_count()
-
- def update_selected_count(self):
- """更新已选数量"""
- count = len(self.window_list.selectedItems())
- self.selected_count_label.setText(f'已选: {count} 个窗口')
-
- def get_window_title(self, hwnd):
- """获取窗口标题"""
- try:
- return win32gui.GetWindowText(hwnd)
- except:
- return ''
-
- def is_window_visible(self, hwnd):
- """检查窗口是否可见"""
- try:
- return win32gui.IsWindowVisible(hwnd)
- except:
- return False
-
- def enum_all_windows_callback(self, hwnd, windows_list):
- """枚举所有窗口的回调函数(包括隐藏窗口)"""
- if win32gui.IsWindow(hwnd):
- title = self.get_window_title(hwnd)
- if title: # 只记录有标题的窗口
- windows_list.append((hwnd, title))
- return True
-
- def load_processes(self):
- """加载所有进程窗口(包括隐藏的)"""
- try:
- self.window_list.clear()
- self.window_handles = []
- self.all_windows = []
-
- windows_list = []
- win32gui.EnumWindows(self.enum_all_windows_callback, windows_list)
-
- self.all_windows = windows_list.copy()
-
- # 筛选以"霸器-"开头的窗口
- baqi_windows = [(hwnd, title) for hwnd, title in windows_list if title.startswith('霸器-')]
-
- if not baqi_windows:
- self.status_label.setText(f'未找到以"霸器-"开头的窗口 (共找到 {len(windows_list)} 个窗口)')
- self.log_text.append(f'⚠️ 未找到霸器窗口,共找到 {len(windows_list)} 个窗口')
- return
-
- # 按标题排序
- baqi_windows.sort(key=lambda x: x[1])
-
- for hwnd, title in baqi_windows:
- item = QListWidgetItem(title)
- item.setData(Qt.UserRole, hwnd)
- visible = self.is_window_visible(hwnd)
- status_text = " ✓" if visible else " ✗"
- item.setText(title + status_text)
- item.setData(Qt.UserRole + 1, visible)
- self.window_list.addItem(item)
- self.window_handles.append(hwnd)
-
- visible_count = sum(1 for _, title in baqi_windows if self.is_window_visible(_))
- hidden_count = len(baqi_windows) - visible_count
-
- self.status_label.setText(f'找到 {len(baqi_windows)} 个"霸器-"窗口 (可见: {visible_count}, 隐藏: {hidden_count})')
- self.log_text.append(f'✅ 加载完成,找到 {len(baqi_windows)} 个霸器窗口')
-
- # 应用显示模式过滤
- self.apply_show_mode()
- self.update_selected_count()
-
- except Exception as e:
- QMessageBox.critical(self, '错误', f'加载进程失败: {str(e)}')
- self.status_label.setText('加载失败')
- self.log_text.append(f'❌ 加载失败: {str(e)}')
-
- def apply_show_mode(self):
- """应用显示模式过滤"""
- mode = self.show_mode_combo.currentText()
- for i in range(self.window_list.count()):
- item = self.window_list.item(i)
- visible = item.data(Qt.UserRole + 1)
-
- if mode == '所有窗口':
- item.setHidden(False)
- elif mode == '仅可见窗口':
- item.setHidden(not visible)
- elif mode == '仅隐藏窗口':
- item.setHidden(visible)
- self.update_selected_count()
-
- def on_show_mode_changed(self):
- """显示模式改变时重新过滤"""
- self.apply_show_mode()
-
- def filter_list(self):
- """根据输入过滤列表"""
- filter_text = self.filter_input.text().lower()
- for i in range(self.window_list.count()):
- item = self.window_list.item(i)
- title = item.text().replace(' ✓', '').replace(' ✗', '')
- if filter_text in title.lower():
- item.setHidden(False)
- else:
- item.setHidden(True)
- self.apply_show_mode()
-
- def get_selected_windows(self):
- """获取所有选中的窗口"""
- selected_items = self.window_list.selectedItems()
- windows = []
- for item in selected_items:
- hwnd = item.data(Qt.UserRole)
- title = item.text().replace(' ✓', '').replace(' ✗', '')
- windows.append((hwnd, title))
- return windows
-
- def show_selected_window(self):
- """显示选中的窗口(只显示第一个选中的)"""
- selected = self.get_selected_windows()
- if not selected:
- QMessageBox.warning(self, '警告', '请先选择窗口')
- return
-
- hwnd, title = selected[0]
- try:
- win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
- win32gui.SetForegroundWindow(hwnd)
- if win32gui.IsIconic(hwnd):
- win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
-
- self.status_label.setText(f'已显示窗口: {title}')
- self.log_text.append(f'👁️ 显示窗口: {title}')
- self.refresh_window_visibility()
-
- except Exception as e:
- QMessageBox.critical(self, '错误', f'显示窗口失败: {str(e)}')
-
- def refresh_window_visibility(self):
- """刷新窗口中显示的可见状态"""
- for i in range(self.window_list.count()):
- item = self.window_list.item(i)
- hwnd = item.data(Qt.UserRole)
- title = item.text().replace(' ✓', '').replace(' ✗', '')
- visible = self.is_window_visible(hwnd)
- status_text = " ✓" if visible else " ✗"
- item.setText(title + status_text)
- item.setData(Qt.UserRole + 1, visible)
-
- self.apply_show_mode()
-
- def minimize_window(self, hwnd):
- """最小化窗口"""
- try:
- win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
- self.signals.status.emit(f'📉 已最小化窗口')
- return True
- except Exception as e:
- self.signals.status.emit(f'❌ 最小化失败: {str(e)}')
- return False
-
- def click_at_position(self, hwnd, x_offset, y_offset, button='left'):
- """
- 封装的点击函数
- :param hwnd: 窗口句柄
- :param x_offset: X轴偏移量
- :param y_offset: Y轴偏移量
- :param button: 'left' 或 'right'
- """
- # 获取窗口位置
- rect = win32gui.GetWindowRect(hwnd)
- window_x = rect[0]
- window_y = rect[1]
-
- # 计算点击位置
- click_x = window_x + x_offset
- click_y = window_y + y_offset
-
- # 移动鼠标到目标位置
- win32api.SetCursorPos((click_x, click_y))
- time.sleep(0.2)
-
- # 模拟鼠标点击
- if button == 'left':
- win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, click_x, click_y, 0, 0)
- time.sleep(0.1)
- win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, click_x, click_y, 0, 0)
- self.signals.status.emit(f'🖱️ 左键点击: ({click_x}, {click_y})')
- elif button == 'right':
- win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN, click_x, click_y, 0, 0)
- time.sleep(0.1)
- win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP, click_x, click_y, 0, 0)
- self.signals.status.emit(f'🖱️ 右键点击: ({click_x}, {click_y})')
-
- return click_x, click_y
-
- def get_pixel_color(self, hwnd, x_offset, y_offset):
- try:
- # 获取窗口位置
- rect = win32gui.GetWindowRect(hwnd)
- window_x = rect[0]
- window_y = rect[1]
-
- # 计算屏幕坐标
- screen_x = window_x + x_offset
- screen_y = window_y + y_offset
-
- # 获取桌面DC
- hdc = win32gui.GetDC(0) # 0 表示桌面
-
- color_ref = win32gui.GetPixel(hdc, screen_x, screen_y)
-
- win32gui.ReleaseDC(0, hdc)
-
- red = color_ref & 0xFF
- green = (color_ref >> 8) & 0xFF
- blue = (color_ref >> 16) & 0xFF
-
- return f"{red:02X}{green:02X}{blue:02X}"
-
- except Exception as e:
- self.log_text.append(f'❌ 取色失败: {str(e)}')
- return "000000"
-
- def check_and_click(self, hwnd, check_x, check_y, target_color,
- click_x, click_y, button='left', check_type='equal'):
- """
- 检查颜色并执行点击
-
- :param hwnd: 窗口句柄
- :param check_x: 检查颜色的X偏移
- :param check_y: 检查颜色的Y偏移
- :param target_color: 目标颜色 (如 "FFFFFF")
- :param click_x: 点击的X偏移
- :param click_y: 点击的Y偏移
- :param button: 'left' 或 'right'
- :param check_type: 'equal' 或 'not_equal'
- :return: 是否执行了点击
- """
- # 获取当前颜色
- current_color = self.get_pixel_color(hwnd, check_x, check_y)
-
- self.log_text.append(f'🎨 检测位置({check_x},{check_y})颜色: {current_color} (目标: {target_color})')
-
- should_click = False
- if check_type == 'equal':
- should_click = (current_color == target_color)
- elif check_type == 'not_equal':
- should_click = (current_color != target_color)
-
- if should_click:
- self.log_text.append(f'✅ 条件满足,执行点击 ({click_x}, {click_y})')
- self.click_at_position(hwnd, click_x, click_y, button)
- return True
- else:
- self.log_text.append(f'❌ 条件不满足,跳过点击')
- return False
-
- def start_auto_click(self):
- """开始自动点击 - 批量执行"""
- if self.is_running:
- return
-
- # 获取所有选中的窗口
- selected_windows = self.get_selected_windows()
- if not selected_windows:
- QMessageBox.warning(self, '警告', '请至少选择一个窗口')
- return
-
- # 检查是否至少选择了一个功能
- if not (self.cb_molong.isChecked() or self.cb_feicui.isChecked() or
- self.cb_jinyan.isChecked() or self.cb_chiyan.isChecked()):
- QMessageBox.warning(self, '警告', '请至少选择一个功能')
- return
-
- self.is_running = True
- self.should_stop = False
- self.start_btn.setEnabled(False)
- self.stop_btn.setEnabled(True)
-
- # 记录选择的选项
- selected = []
- if self.cb_molong.isChecked(): selected.append('争夺魔龙之心')
- if self.cb_feicui.isChecked(): selected.append('翡翠荣耀旗')
- if self.cb_jinyan.isChecked(): selected.append('金岩霸者棋')
- if self.cb_chiyan.isChecked(): selected.append('炽焰战神棋')
-
- # 记录皇宫占位选择
- if self.radio_random.isChecked():
- palace_pos = '随机'
- palace_y = 444
- elif self.radio_door.isChecked():
- palace_pos = '门口'
- palace_y = 457
- else: # corner
- palace_pos = '角落'
- palace_y = 470
-
- self.log_text.append(f'▶️ 开始批量执行,共 {len(selected_windows)} 个窗口')
- self.log_text.append(f'📋 已选功能: {", ".join(selected)}')
- self.log_text.append(f'🏰 皇宫占位: {palace_pos} (Y+{palace_y})')
- self.log_text.append('=' * 50)
-
- # 在新线程中执行
- thread = threading.Thread(target=self.batch_auto_click_worker,
- args=(selected_windows, palace_y))
- thread.daemon = True
- thread.start()
-
- def batch_auto_click_worker(self, selected_windows, palace_y):
- """批量自动点击工作线程"""
- total = len(selected_windows)
-
- for idx, (hwnd, title) in enumerate(selected_windows, 1):
- # 检查是否被停止
- if self.should_stop:
- self.signals.status.emit(f'⏹️ 用户停止执行')
- break
-
- self.signals.status.emit(f'📌 正在处理 [{idx}/{total}] {title}')
- self.signals.progress.emit(idx, total)
-
- try:
- # 执行单个窗口的点击流程
- self.execute_single_window(hwnd, title, palace_y)
-
- # 等待5秒后最小化窗口
- self.signals.status.emit(f'⏳ 等待5秒后最小化窗口...')
- time.sleep(5)
-
- # 最小化窗口
- self.signals.status.emit(f'📉 最小化窗口: {title}')
- self.minimize_window(hwnd)
-
- # 窗口间间隔1秒
- if idx < total and not self.should_stop:
- self.signals.status.emit(f'⏳ 等待1秒后处理下一个窗口...')
- time.sleep(1)
-
- except Exception as e:
- self.signals.status.emit(f'❌ 处理窗口失败: {str(e)}')
- import traceback
- self.log_text.append(traceback.format_exc())
- # 出错后继续下一个窗口
-
- if not self.should_stop:
- self.signals.status.emit(f'✅ 批量执行完成!共处理 {idx if idx < total else total} 个窗口')
- self.signals.finished.emit()
-
- def execute_single_window(self, hwnd, title, palace_y):
- """执行单个窗口的点击流程"""
- # 1. 激活窗口
- self.signals.status.emit(f'🔄 正在激活窗口: {title}')
-
- # 显示窗口
- win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
- if win32gui.IsIconic(hwnd):
- win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
-
- # 激活窗口
- win32gui.SetForegroundWindow(hwnd)
- time.sleep(1) # 等待窗口激活
-
- # 步骤1: 左键点击 X+63, Y+81
- self.click_at_position(hwnd, 29, 41, 'left')
- time.sleep(1)
- self.signals.status.emit(f'📍 步骤1: 左键点击 X+63, Y+81')
- self.click_at_position(hwnd, 63, 81, 'left')
-
- # 等待5秒
- self.signals.status.emit(f'⏳ 等待5秒...')
- time.sleep(5)
-
- # 步骤2: 右键点击 X+413, Y+168
- self.signals.status.emit(f'📍 步骤2: 右键点击 X+413, Y+168')
- self.click_at_position(hwnd, 413, 168, 'right')
-
- # 等待6秒
- self.signals.status.emit(f'⏳ 等待6秒...')
- time.sleep(6)
-
- # 处理"争夺魔龙之心"
- if self.cb_molong.isChecked():
- self.signals.status.emit(f'📍 检查争夺魔龙之心')
- self.check_and_click(
- hwnd=hwnd,
- check_x=642,
- check_y=439,
- target_color="FFFFFF",
- click_x=642,
- click_y=439,
- button='left',
- check_type='equal'
- )
- else:
- self.signals.status.emit(f'📍 未选争夺魔龙之心,执行相反逻辑')
- self.check_and_click(
- hwnd=hwnd,
- check_x=642,
- check_y=437,
- target_color="FFFFFF",
- click_x=642,
- click_y=437,
- button='left',
- check_type='not_equal'
- )
-
- # 等待1秒
- time.sleep(0.2)
-
- # 处理"翡翠荣耀旗"
- if self.cb_feicui.isChecked():
- self.signals.status.emit(f'📍 检查翡翠荣耀旗')
- self.check_and_click(
- hwnd=hwnd,
- check_x=769,
- check_y=386,
- target_color="FFFFFF",
- click_x=769,
- click_y=386,
- button='left',
- check_type='equal'
- )
- else:
- self.signals.status.emit(f'📍 未选翡翠荣耀旗,执行相反逻辑')
- self.check_and_click(
- hwnd=hwnd,
- check_x=769,
- check_y=386,
- target_color="FFFFFF",
- click_x=769,
- click_y=386,
- button='left',
- check_type='not_equal'
- )
-
- # 等待1秒
- time.sleep(0.2)
-
- # 处理"金岩霸者棋"
- if self.cb_jinyan.isChecked():
- self.signals.status.emit(f'📍 检查金岩霸者棋')
- self.check_and_click(
- hwnd=hwnd,
- check_x=769,
- check_y=400,
- target_color="FFFFFF",
- click_x=769,
- click_y=400,
- button='left',
- check_type='equal'
- )
- else:
- self.signals.status.emit(f'📍 未选金岩霸者棋,执行相反逻辑')
- self.check_and_click(
- hwnd=hwnd,
- check_x=769,
- check_y=400,
- target_color="FFFFFF",
- click_x=769,
- click_y=400,
- button='left',
- check_type='not_equal'
- )
-
- # 等待1秒
- time.sleep(0.2)
-
- # 处理"炽焰战神棋"
- if self.cb_chiyan.isChecked():
- self.signals.status.emit(f'📍 检查炽焰战神棋')
- self.check_and_click(
- hwnd=hwnd,
- check_x=767,
- check_y=415,
- target_color="FFFFFF",
- click_x=767,
- click_y=415,
- button='left',
- check_type='equal'
- )
- else:
- self.signals.status.emit(f'📍 未选炽焰战神棋,执行相反逻辑')
- self.check_and_click(
- hwnd=hwnd,
- check_x=767,
- check_y=415,
- target_color="FFFFFF",
- click_x=767,
- click_y=415,
- button='left',
- check_type='not_equal'
- )
-
- # 等待1秒
- time.sleep(0.2)
-
- # 最后点击 X+871, Y+266
- self.signals.status.emit(f'📍 最后点击: X+871, Y+266')
- self.click_at_position(hwnd, 871, 266, 'left')
- time.sleep(0.5)
- self.click_at_position(hwnd, 671, 70, 'right')
- time.sleep(1)
- self.click_at_position(hwnd, 714, 426, 'left')
- time.sleep(1)
-
- # 皇宫占位点击 - 根据选择的选项
- self.signals.status.emit(f'🏰 皇宫占位点击: X+716, Y+{palace_y}')
- self.click_at_position(hwnd, 716, palace_y, 'left')
-
- time.sleep(1)
- self.click_at_position(hwnd, 901, 311, 'left')
- time.sleep(1)
- self.click_at_position(hwnd, 1133, 8, 'left')
-
- self.signals.status.emit(f'✅ 窗口 {title} 执行完成')
-
- def stop_auto_click(self):
- """停止自动点击"""
- self.should_stop = True
- self.is_running = False
- self.start_btn.setEnabled(True)
- self.stop_btn.setEnabled(False)
- self.status_label.setText('正在停止...')
- self.log_text.append('⏹️ 正在停止执行...')
-
- def update_status(self, message):
- """更新状态"""
- self.status_label.setText(message)
- self.log_text.append(message)
- # 滚动到底部
- self.log_text.verticalScrollBar().setValue(
- self.log_text.verticalScrollBar().maximum()
- )
-
- def update_progress(self, current, total):
- """更新进度"""
- self.status_label.setText(f'进度: {current}/{total}')
-
- def on_finished(self):
- """完成回调"""
- self.is_running = False
- self.start_btn.setEnabled(True)
- self.stop_btn.setEnabled(False)
- self.status_label.setText('就绪')
- self.log_text.append('=' * 50)
- def main():
- app = QApplication(sys.argv)
- app.setStyle('Fusion')
-
- window = WindowManagerApp()
- window.show()
-
- sys.exit(app.exec_())
- if __name__ == '__main__':
- main()
|