|
|
@@ -29,12 +29,12 @@ class WindowManagerApp(QMainWindow):
|
|
|
self.is_running = False
|
|
|
self.should_stop = False # 停止标志
|
|
|
self.initUI()
|
|
|
-
|
|
|
+
|
|
|
def initUI(self):
|
|
|
"""初始化界面"""
|
|
|
self.setWindowTitle('霸器窗口自动点击工具 - 多窗口批量执行')
|
|
|
- self.setGeometry(100, 100, 950, 750)
|
|
|
-
|
|
|
+ self.setGeometry(100, 100, 950, 800)
|
|
|
+
|
|
|
# 设置主窗口样式
|
|
|
self.setStyleSheet("""
|
|
|
QMainWindow {
|
|
|
@@ -92,6 +92,28 @@ class WindowManagerApp(QMainWindow):
|
|
|
QPushButton#stopBtn:hover {
|
|
|
background-color: #e14448;
|
|
|
}
|
|
|
+ QPushButton#funcBtn {
|
|
|
+ background-color: #8b5cf6;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 10px 20px;
|
|
|
+ }
|
|
|
+ QPushButton#funcBtn:hover {
|
|
|
+ background-color: #7c3aed;
|
|
|
+ }
|
|
|
+ QPushButton#funcBtn:disabled {
|
|
|
+ background-color: #555;
|
|
|
+ }
|
|
|
+ QPushButton#palaceBtn {
|
|
|
+ background-color: #f59e0b;
|
|
|
+ font-size: 13px;
|
|
|
+ padding: 10px 20px;
|
|
|
+ }
|
|
|
+ QPushButton#palaceBtn:hover {
|
|
|
+ background-color: #d97706;
|
|
|
+ }
|
|
|
+ QPushButton#palaceBtn:disabled {
|
|
|
+ background-color: #555;
|
|
|
+ }
|
|
|
QListWidget {
|
|
|
background-color: #3c3c3c;
|
|
|
color: #ffffff;
|
|
|
@@ -163,12 +185,12 @@ class WindowManagerApp(QMainWindow):
|
|
|
font-size: 10pt;
|
|
|
}
|
|
|
""")
|
|
|
-
|
|
|
+
|
|
|
# 创建中央窗口
|
|
|
central_widget = QWidget()
|
|
|
self.setCentralWidget(central_widget)
|
|
|
main_layout = QVBoxLayout(central_widget)
|
|
|
-
|
|
|
+
|
|
|
# 标题
|
|
|
title_label = QLabel('霸器窗口自动点击工具 - 批量执行')
|
|
|
title_label.setAlignment(Qt.AlignCenter)
|
|
|
@@ -176,158 +198,188 @@ class WindowManagerApp(QMainWindow):
|
|
|
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('功能选择')
|
|
|
+
|
|
|
+ # ==================== 功能选择区域 ====================
|
|
|
+ func_group = QGroupBox('功能选择 (联赛相关)')
|
|
|
+ func_main_layout = QVBoxLayout()
|
|
|
+
|
|
|
+ # 复选框
|
|
|
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('皇宫占位位置')
|
|
|
+
|
|
|
+ checkbox_layout.addStretch()
|
|
|
+ func_main_layout.addLayout(checkbox_layout)
|
|
|
+
|
|
|
+ # 功能选择执行按钮
|
|
|
+ func_btn_layout = QHBoxLayout()
|
|
|
+ self.func_btn = QPushButton('⚡ 单独执行功能选择')
|
|
|
+ self.func_btn.setObjectName('funcBtn')
|
|
|
+ self.func_btn.clicked.connect(lambda: self.start_batch('function'))
|
|
|
+ func_btn_layout.addWidget(self.func_btn)
|
|
|
+ func_btn_layout.addStretch()
|
|
|
+ func_main_layout.addLayout(func_btn_layout)
|
|
|
+
|
|
|
+ func_group.setLayout(func_main_layout)
|
|
|
+ main_layout.addWidget(func_group)
|
|
|
+
|
|
|
+ # ==================== 皇宫占位区域 ====================
|
|
|
+ palace_group = QGroupBox('皇宫占位位置')
|
|
|
+ palace_main_layout = QVBoxLayout()
|
|
|
+
|
|
|
+ # 单选按钮
|
|
|
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)
|
|
|
-
|
|
|
+
|
|
|
+ radio_layout.addStretch()
|
|
|
+ palace_main_layout.addLayout(radio_layout)
|
|
|
+
|
|
|
+ # 皇宫占位执行按钮
|
|
|
+ palace_btn_layout = QHBoxLayout()
|
|
|
+ self.palace_btn = QPushButton('👑 单独执行皇宫占位')
|
|
|
+ self.palace_btn.setObjectName('palaceBtn')
|
|
|
+ self.palace_btn.clicked.connect(lambda: self.start_batch('palace'))
|
|
|
+ palace_btn_layout.addWidget(self.palace_btn)
|
|
|
+ palace_btn_layout.addStretch()
|
|
|
+ palace_main_layout.addLayout(palace_btn_layout)
|
|
|
+
|
|
|
+ palace_group.setLayout(palace_main_layout)
|
|
|
+ main_layout.addWidget(palace_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_group = QGroupBox('批量操作')
|
|
|
action_layout = QHBoxLayout()
|
|
|
-
|
|
|
- self.start_btn = QPushButton('▶️ 开始批量执行')
|
|
|
+
|
|
|
+ self.start_btn = QPushButton('▶️ 全部执行 (功能+皇宫)')
|
|
|
self.start_btn.setObjectName('startBtn')
|
|
|
- self.start_btn.clicked.connect(self.start_auto_click)
|
|
|
+ self.start_btn.clicked.connect(lambda: self.start_batch('all'))
|
|
|
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()):
|
|
|
@@ -335,31 +387,31 @@ class WindowManagerApp(QMainWindow):
|
|
|
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):
|
|
|
@@ -367,30 +419,30 @@ class WindowManagerApp(QMainWindow):
|
|
|
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)
|
|
|
@@ -400,29 +452,29 @@ class WindowManagerApp(QMainWindow):
|
|
|
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 == '仅可见窗口':
|
|
|
@@ -430,11 +482,11 @@ class WindowManagerApp(QMainWindow):
|
|
|
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()
|
|
|
@@ -446,7 +498,7 @@ class WindowManagerApp(QMainWindow):
|
|
|
else:
|
|
|
item.setHidden(True)
|
|
|
self.apply_show_mode()
|
|
|
-
|
|
|
+
|
|
|
def get_selected_windows(self):
|
|
|
"""获取所有选中的窗口"""
|
|
|
selected_items = self.window_list.selectedItems()
|
|
|
@@ -456,28 +508,28 @@ class WindowManagerApp(QMainWindow):
|
|
|
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()):
|
|
|
@@ -488,9 +540,9 @@ class WindowManagerApp(QMainWindow):
|
|
|
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:
|
|
|
@@ -500,7 +552,7 @@ class WindowManagerApp(QMainWindow):
|
|
|
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'):
|
|
|
"""
|
|
|
封装的点击函数
|
|
|
@@ -513,15 +565,15 @@ class WindowManagerApp(QMainWindow):
|
|
|
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)
|
|
|
@@ -533,42 +585,42 @@ class WindowManagerApp(QMainWindow):
|
|
|
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偏移
|
|
|
@@ -581,15 +633,15 @@ class WindowManagerApp(QMainWindow):
|
|
|
"""
|
|
|
# 获取当前颜色
|
|
|
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)
|
|
|
@@ -597,36 +649,47 @@ class WindowManagerApp(QMainWindow):
|
|
|
else:
|
|
|
self.log_text.append(f'❌ 条件不满足,跳过点击')
|
|
|
return False
|
|
|
-
|
|
|
- def start_auto_click(self):
|
|
|
- """开始自动点击 - 批量执行"""
|
|
|
+
|
|
|
+ def start_batch(self, mode):
|
|
|
+ """开始批量执行 - 支持单独模式
|
|
|
+ mode: 'all' | 'function' | 'palace'
|
|
|
+ """
|
|
|
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
|
|
|
-
|
|
|
+
|
|
|
+ # 根据模式验证
|
|
|
+ if mode == 'function':
|
|
|
+ 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
|
|
|
+ elif mode == 'all':
|
|
|
+ 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
|
|
|
+ # palace 模式不需要额外验证
|
|
|
+
|
|
|
self.is_running = True
|
|
|
self.should_stop = False
|
|
|
self.start_btn.setEnabled(False)
|
|
|
+ self.func_btn.setEnabled(False)
|
|
|
+ self.palace_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 = '随机'
|
|
|
@@ -637,90 +700,143 @@ class WindowManagerApp(QMainWindow):
|
|
|
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})')
|
|
|
+
|
|
|
+ # 根据模式显示不同的日志
|
|
|
+ if mode == 'all':
|
|
|
+ self.log_text.append(f'▶️ 开始【全部执行】,共 {len(selected_windows)} 个窗口')
|
|
|
+ self.log_text.append(f'📋 已选功能: {", ".join(selected) if selected else "无"}')
|
|
|
+ self.log_text.append(f'🏰 皇宫占位: {palace_pos} (Y+{palace_y})')
|
|
|
+ elif mode == 'function':
|
|
|
+ self.log_text.append(f'▶️ 开始【单独执行功能选择】,共 {len(selected_windows)} 个窗口')
|
|
|
+ self.log_text.append(f'📋 已选功能: {", ".join(selected)}')
|
|
|
+ elif mode == 'palace':
|
|
|
+ self.log_text.append(f'▶️ 开始【单独执行皇宫占位】,共 {len(selected_windows)} 个窗口')
|
|
|
+ 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))
|
|
|
+ args=(selected_windows, palace_y, mode))
|
|
|
thread.daemon = True
|
|
|
thread.start()
|
|
|
-
|
|
|
- def batch_auto_click_worker(self, selected_windows, palace_y):
|
|
|
- """批量自动点击工作线程"""
|
|
|
+
|
|
|
+ def batch_auto_click_worker(self, selected_windows, palace_y, mode):
|
|
|
+ """批量自动点击工作线程
|
|
|
+ mode: 'all' | 'function' | 'palace'
|
|
|
+ """
|
|
|
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)
|
|
|
-
|
|
|
+ # 根据模式执行不同的流程
|
|
|
+ if mode == 'all':
|
|
|
+ # 全部执行:功能 + 皇宫
|
|
|
+ self.execute_single_window_all(hwnd, title, palace_y)
|
|
|
+ elif mode == 'function':
|
|
|
+ # 只执行功能选择
|
|
|
+ self.execute_single_window_function(hwnd, title)
|
|
|
+ elif mode == 'palace':
|
|
|
+ # 只执行皇宫占位
|
|
|
+ self.execute_single_window_palace(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. 激活窗口
|
|
|
+
|
|
|
+ def activate_window(self, hwnd, title):
|
|
|
+ """激活窗口"""
|
|
|
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) # 等待窗口激活
|
|
|
-
|
|
|
+
|
|
|
+ def execute_single_window_all(self, hwnd, title, palace_y):
|
|
|
+ """执行单个窗口的完整流程(功能+皇宫)"""
|
|
|
+ # 1. 激活窗口
|
|
|
+ self.activate_window(hwnd, title)
|
|
|
+
|
|
|
+ # 执行功能选择部分
|
|
|
+ self._do_function_clicks(hwnd)
|
|
|
+
|
|
|
+ # 执行皇宫占位部分
|
|
|
+ self._do_palace_clicks(hwnd, palace_y)
|
|
|
+
|
|
|
+ self.signals.status.emit(f'✅ 窗口 {title} 全部执行完成')
|
|
|
+
|
|
|
+ def execute_single_window_function(self, hwnd, title):
|
|
|
+ """只执行功能选择部分"""
|
|
|
+ # 1. 激活窗口
|
|
|
+ self.activate_window(hwnd, title)
|
|
|
+
|
|
|
+ # 执行功能选择部分
|
|
|
+ self._do_function_clicks(hwnd)
|
|
|
+
|
|
|
+ self.signals.status.emit(f'✅ 窗口 {title} 功能选择执行完成')
|
|
|
+
|
|
|
+ def execute_single_window_palace(self, hwnd, title, palace_y):
|
|
|
+ """只执行皇宫占位部分"""
|
|
|
+ # 1. 激活窗口
|
|
|
+ self.activate_window(hwnd, title)
|
|
|
+
|
|
|
+ # 执行皇宫占位部分
|
|
|
+ self._do_palace_clicks(hwnd, palace_y)
|
|
|
+
|
|
|
+ self.signals.status.emit(f'✅ 窗口 {title} 皇宫占位执行完成')
|
|
|
+
|
|
|
+ def _do_function_clicks(self, hwnd):
|
|
|
+ """功能选择的点击逻辑(可复用)"""
|
|
|
# 步骤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'📍 检查争夺魔龙之心')
|
|
|
@@ -746,10 +862,10 @@ class WindowManagerApp(QMainWindow):
|
|
|
button='left',
|
|
|
check_type='not_equal'
|
|
|
)
|
|
|
-
|
|
|
+
|
|
|
# 等待1秒
|
|
|
time.sleep(0.2)
|
|
|
-
|
|
|
+
|
|
|
# 处理"翡翠荣耀旗"
|
|
|
if self.cb_feicui.isChecked():
|
|
|
self.signals.status.emit(f'📍 检查翡翠荣耀旗')
|
|
|
@@ -775,10 +891,10 @@ class WindowManagerApp(QMainWindow):
|
|
|
button='left',
|
|
|
check_type='not_equal'
|
|
|
)
|
|
|
-
|
|
|
+
|
|
|
# 等待1秒
|
|
|
time.sleep(0.2)
|
|
|
-
|
|
|
+
|
|
|
# 处理"金岩霸者棋"
|
|
|
if self.cb_jinyan.isChecked():
|
|
|
self.signals.status.emit(f'📍 检查金岩霸者棋')
|
|
|
@@ -804,10 +920,10 @@ class WindowManagerApp(QMainWindow):
|
|
|
button='left',
|
|
|
check_type='not_equal'
|
|
|
)
|
|
|
-
|
|
|
+
|
|
|
# 等待1秒
|
|
|
time.sleep(0.2)
|
|
|
-
|
|
|
+
|
|
|
# 处理"炽焰战神棋"
|
|
|
if self.cb_chiyan.isChecked():
|
|
|
self.signals.status.emit(f'📍 检查炽焰战神棋')
|
|
|
@@ -833,14 +949,16 @@ class WindowManagerApp(QMainWindow):
|
|
|
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')
|
|
|
|
|
|
+ def _do_palace_clicks(self, hwnd, palace_y):
|
|
|
+ """皇宫占位的点击逻辑(可复用)"""
|
|
|
time.sleep(0.5)
|
|
|
self.click_at_position(hwnd, 671, 70, 'right')
|
|
|
|
|
|
@@ -848,28 +966,28 @@ class WindowManagerApp(QMainWindow):
|
|
|
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.func_btn.setEnabled(True)
|
|
|
+ self.palace_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)
|
|
|
@@ -878,15 +996,17 @@ class WindowManagerApp(QMainWindow):
|
|
|
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.func_btn.setEnabled(True)
|
|
|
+ self.palace_btn.setEnabled(True)
|
|
|
self.stop_btn.setEnabled(False)
|
|
|
self.status_label.setText('就绪')
|
|
|
self.log_text.append('=' * 50)
|
|
|
@@ -895,10 +1015,10 @@ class WindowManagerApp(QMainWindow):
|
|
|
def main():
|
|
|
app = QApplication(sys.argv)
|
|
|
app.setStyle('Fusion')
|
|
|
-
|
|
|
+
|
|
|
window = WindowManagerApp()
|
|
|
window.show()
|
|
|
-
|
|
|
+
|
|
|
sys.exit(app.exec_())
|
|
|
|
|
|
|