增加微信多开功能
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
"""
|
||||
微信多开对话框
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
||||
QPushButton, QSpinBox, QFileDialog, QTextEdit, QWidget
|
||||
)
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtGui import QIcon
|
||||
import ui.theme as theme
|
||||
from db import database
|
||||
|
||||
_DB_KEY_PATH = "wechat_multi_path"
|
||||
_DB_KEY_COUNT = "wechat_multi_count"
|
||||
|
||||
_DEFAULT_PATHS = [
|
||||
r"D:\Softwares\Tencent\Weixin\Weixin.exe",
|
||||
r"C:\Program Files\Tencent\WeChat\WeChat.exe",
|
||||
r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe",
|
||||
]
|
||||
|
||||
_USAGE = """使用说明:
|
||||
|
||||
1. 填写微信 Weixin.exe 的完整路径。
|
||||
点击右侧「浏览」按钮可以直接选择文件。
|
||||
|
||||
2. 设置多开数量(建议不超过 5 个,
|
||||
数量过多可能导致电脑卡顿)。
|
||||
|
||||
3. 点击「开始多开」,程序会依次启动
|
||||
对应数量的微信进程。
|
||||
|
||||
4. 每个微信实例需要单独登录账号。
|
||||
|
||||
注意:微信官方不支持多开,使用本功能
|
||||
请自行承担相关风险。
|
||||
"""
|
||||
|
||||
|
||||
def _detect_wechat() -> str:
|
||||
"""尝试自动检测微信路径。"""
|
||||
saved = database.get_setting(_DB_KEY_PATH, "")
|
||||
if saved and os.path.isfile(saved):
|
||||
return saved
|
||||
for p in _DEFAULT_PATHS:
|
||||
if os.path.isfile(p):
|
||||
return p
|
||||
return ""
|
||||
|
||||
|
||||
class WechatMultiDialog(QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("微信多开")
|
||||
self.setMinimumWidth(460)
|
||||
self.setWindowFlags(
|
||||
Qt.WindowType.Dialog | Qt.WindowType.FramelessWindowHint
|
||||
)
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
self._drag_pos = None
|
||||
self._build()
|
||||
self._apply_theme()
|
||||
|
||||
def _build(self):
|
||||
saved_path = _detect_wechat()
|
||||
saved_count = int(database.get_setting(_DB_KEY_COUNT, "2"))
|
||||
|
||||
root = QVBoxLayout(self)
|
||||
root.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self._card = QWidget()
|
||||
self._card.setObjectName("wechat_card")
|
||||
card_layout = QVBoxLayout(self._card)
|
||||
card_layout.setContentsMargins(20, 16, 20, 16)
|
||||
card_layout.setSpacing(12)
|
||||
|
||||
# 标题栏
|
||||
title_row = QHBoxLayout()
|
||||
lbl_title = QLabel("微信多开")
|
||||
lbl_title.setStyleSheet("font-size:14px; font-weight:bold;")
|
||||
close_btn = QPushButton("✕")
|
||||
close_btn.setFixedSize(24, 24)
|
||||
close_btn.setStyleSheet("border:none; background:transparent; font-size:13px;")
|
||||
close_btn.clicked.connect(self.reject)
|
||||
title_row.addWidget(lbl_title)
|
||||
title_row.addStretch()
|
||||
title_row.addWidget(close_btn)
|
||||
card_layout.addLayout(title_row)
|
||||
|
||||
# 路径
|
||||
card_layout.addWidget(QLabel("微信程序路径(Weixin.exe):"))
|
||||
path_row = QHBoxLayout()
|
||||
self._path_edit = QLineEdit(saved_path)
|
||||
self._path_edit.setPlaceholderText("请输入或浏览 Weixin.exe 路径")
|
||||
browse_btn = QPushButton("浏览")
|
||||
browse_btn.setFixedWidth(56)
|
||||
browse_btn.clicked.connect(self._browse)
|
||||
path_row.addWidget(self._path_edit)
|
||||
path_row.addWidget(browse_btn)
|
||||
card_layout.addLayout(path_row)
|
||||
|
||||
# 数量
|
||||
count_row = QHBoxLayout()
|
||||
count_row.addWidget(QLabel("多开数量:"))
|
||||
self._spin = QSpinBox()
|
||||
self._spin.setRange(2, 9)
|
||||
self._spin.setValue(saved_count)
|
||||
self._spin.setFixedWidth(70)
|
||||
count_row.addWidget(self._spin)
|
||||
count_row.addStretch()
|
||||
card_layout.addLayout(count_row)
|
||||
|
||||
# 使用说明
|
||||
usage = QTextEdit()
|
||||
usage.setReadOnly(True)
|
||||
usage.setPlainText(_USAGE)
|
||||
usage.setFixedHeight(150)
|
||||
usage.setStyleSheet("font-size:11px; border-radius:6px;")
|
||||
card_layout.addWidget(usage)
|
||||
|
||||
# 按钮行
|
||||
btn_row = QHBoxLayout()
|
||||
btn_row.addStretch()
|
||||
self._start_btn = QPushButton("开始多开")
|
||||
self._start_btn.setFixedHeight(32)
|
||||
self._start_btn.setMinimumWidth(90)
|
||||
self._start_btn.clicked.connect(self._start)
|
||||
cancel_btn = QPushButton("取消")
|
||||
cancel_btn.setFixedHeight(32)
|
||||
cancel_btn.setMinimumWidth(70)
|
||||
cancel_btn.clicked.connect(self.reject)
|
||||
btn_row.addWidget(self._start_btn)
|
||||
btn_row.addWidget(cancel_btn)
|
||||
card_layout.addLayout(btn_row)
|
||||
|
||||
root.addWidget(self._card)
|
||||
|
||||
def _apply_theme(self):
|
||||
t = theme.current()
|
||||
is_dark = theme.name() == "dark"
|
||||
self._card.setStyleSheet(f"""
|
||||
QWidget#wechat_card {{
|
||||
background: {t['panel_bg']};
|
||||
border-radius: 10px;
|
||||
border: 1px solid {t['panel_border']};
|
||||
}}
|
||||
QLabel {{ color: {t['search_color']}; background: transparent; }}
|
||||
QLineEdit {{
|
||||
background: {t['search_bg']};
|
||||
border: 1px solid {t['search_border']};
|
||||
border-radius: 5px;
|
||||
color: {t['search_color']};
|
||||
padding: 4px 8px;
|
||||
}}
|
||||
QSpinBox {{
|
||||
background: {t['search_bg']};
|
||||
border: 1px solid {t['search_border']};
|
||||
border-radius: 5px;
|
||||
color: {t['search_color']};
|
||||
padding: 2px 4px;
|
||||
}}
|
||||
QTextEdit {{
|
||||
background: {t['search_bg']};
|
||||
color: {t['search_color']};
|
||||
border: 1px solid {t['search_border']};
|
||||
}}
|
||||
QPushButton {{
|
||||
border: 1px solid {t['search_border']};
|
||||
border-radius: 5px;
|
||||
color: {t['btn_color']};
|
||||
background: {t['search_bg']};
|
||||
font-size: 12px;
|
||||
padding: 0 10px;
|
||||
}}
|
||||
QPushButton:hover {{ background: {t['header_hover']}; }}
|
||||
""")
|
||||
|
||||
def _browse(self):
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self, "选择 Weixin.exe", "", "可执行文件 (*.exe)"
|
||||
)
|
||||
if path:
|
||||
self._path_edit.setText(path)
|
||||
|
||||
def _start(self):
|
||||
exe = self._path_edit.text().strip()
|
||||
count = self._spin.value()
|
||||
|
||||
if not exe:
|
||||
self._path_edit.setPlaceholderText("⚠ 请先填写路径")
|
||||
return
|
||||
if not os.path.isfile(exe):
|
||||
self._path_edit.setStyleSheet(
|
||||
self._path_edit.styleSheet() + "border-color: red;"
|
||||
)
|
||||
return
|
||||
|
||||
# 保存设置
|
||||
database.set_setting(_DB_KEY_PATH, exe)
|
||||
database.set_setting(_DB_KEY_COUNT, str(count))
|
||||
|
||||
# 写临时 bat,连续 start 多次
|
||||
lines = ["@echo off"]
|
||||
for _ in range(count):
|
||||
lines.append(f'start "" "{exe}"')
|
||||
bat_content = "\r\n".join(lines) + "\r\n"
|
||||
|
||||
tmp = tempfile.NamedTemporaryFile(
|
||||
delete=False, suffix=".bat", mode="w", encoding="gbk"
|
||||
)
|
||||
tmp.write(bat_content)
|
||||
tmp.close()
|
||||
|
||||
subprocess.Popen(
|
||||
["cmd", "/c", tmp.name],
|
||||
creationflags=subprocess.CREATE_NO_WINDOW
|
||||
)
|
||||
self.accept()
|
||||
|
||||
# 无边框拖动
|
||||
def mousePressEvent(self, event):
|
||||
if event.button() == Qt.MouseButton.LeftButton:
|
||||
self._drag_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self._drag_pos and event.buttons() & Qt.MouseButton.LeftButton:
|
||||
self.move(event.globalPosition().toPoint() - self._drag_pos)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self._drag_pos = None
|
||||
Reference in New Issue
Block a user