Skip to content

Commit

Permalink
1. 功能更新: 新增 在游戏中按下ALT+F4时, 直接退出游戏, 而无需等待5秒
Browse files Browse the repository at this point in the history
  • Loading branch information
Hpero4 committed Oct 10, 2023
1 parent c165e59 commit 5e5fd76
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 47 deletions.
48 changes: 27 additions & 21 deletions app/common/hook.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import ctypes
import sys
import json
import os
import threading
import time
from ctypes import wintypes
import pygetwindow as gw
import psutil
import win32con
from pyuac import main_requires_admin
import argparse

# if not ctypes.windll.shell32.IsUserAnAdmin():
# # 如果当前的 Python 进程不是以管理员权限运行,那么以管理员权限重新启动它
# ctypes.windll.shell32.ShellExecuteW(win32con.SW_HIDE, "runas", sys.executable, __file__, None, 1)
# sys.exit()
parser = argparse.ArgumentParser()

parser.add_argument("-p", "--pid", help="master process PID")

args = parser.parse_args()

user32 = ctypes.WinDLL('user32', use_last_error=True)

Expand All @@ -36,42 +38,29 @@ def LowLevelKeyboardProc(nCode, wParam, lParam):
if nCode == 0: # HC_ACTION
KBDLLHOOKSTRUCT_p = ctypes.cast(lParam, ctypes.POINTER(KBDLLHOOKSTRUCT))
vkCode = KBDLLHOOKSTRUCT_p.contents.vkCode
# print("hook")
# print(f"0x{wParam:X}")
if wParam in [0x104, 0x100]: # WM_KEYDOWN
print(f"0x{vkCode:X} Down")
keys_pressed.add(vkCode)
elif wParam == 0x101: # WM_KEYUP
print(f"0x{vkCode:X} Up")
keys_pressed.discard(vkCode)
if 0xA4 in keys_pressed and 0x73 in keys_pressed: # Alt and F4
# if 0xA4 in keys_pressed and 0x74 in keys_pressed: # Alt and F5 debug
print('Alt and F4 keys pressed together')
keys_pressed.discard(0xA4)
keys_pressed.discard(0x73) # F4
active_window_title = gw.getActiveWindow().title
print(active_window_title)
if active_window_title != "League of Legends (TM) Client":
return user32.CallNextHookEx(None, ctypes.c_int(nCode), wintypes.WPARAM(wParam), wintypes.LPARAM(lParam))

# 检查进程是否存在并且窗口标题匹配
print("active hit")
for proc in psutil.process_iter():
# print(f"{proc.name()}:::{proc.pid}")
if proc.name() == "League of Legends.exe":
print("proc found")
time.sleep(.2)
proc.kill()
# break
return
return -1
return user32.CallNextHookEx(None, ctypes.c_int(nCode), wintypes.WPARAM(wParam), wintypes.LPARAM(lParam))


LowLevelKeyboardProc = ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_int, wintypes.WPARAM, wintypes.LPARAM)(
LowLevelKeyboardProc)


@main_requires_admin
def start_hook():
hHook = user32.SetWindowsHookExW(idHook, LowLevelKeyboardProc, None, 0)
if not hHook:
Expand All @@ -83,4 +72,21 @@ def start_hook():


if __name__ == '__main__':
def _():
while True:
with open(fr"{os.getcwd()}\app\config\config.json", "r", encoding="utf-8") as f:
js = json.loads(f.read())
if not js.get("Functions", {}).get("ForceDisconnection"): # 关闭了设置
os._exit(0)

for proc in psutil.process_iter():
if proc.pid == int(args.pid):
break
else:
os._exit(0) # 随主进程退出
time.sleep(.5)

threading.Thread(target=_, daemon=True).start()

start_hook()

21 changes: 14 additions & 7 deletions app/view/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class MainWindow(FluentWindow):
showUpdateMessageBox = pyqtSignal(dict)
checkUpdateFailed = pyqtSignal()
showLcuConnectError = pyqtSignal(str, BaseException)
forceDisconnectionSwitch = pyqtSignal()

def __init__(self):
super().__init__()
Expand Down Expand Up @@ -83,11 +84,8 @@ def __init__(self):
threading.Thread(target=self.checkUpdate).start()
threading.Thread(target=self.pollingConnectTimeout,
daemon=True).start()
threading.Thread(target=self.hookManager,
daemon=True).start()

hookPath = rf"{os.getcwd()}\app\common\hook.py"
print(hookPath)
self.__onHookSwitchChange()

def __initInterface(self):
self.__lockInterface()
Expand Down Expand Up @@ -181,6 +179,9 @@ def __conncetSignalToSlot(self):
self.setMicaEffectEnabled)
self.stackedWidget.currentChanged.connect(
self.__onCurrentStackedChanged)
self.auxiliaryFuncInterface.forceDisconnectionCard.switchButton.checkedChanged.connect(
self.__onHookSwitchChange
)

def __initWindow(self):
self.resize(1134, 826)
Expand Down Expand Up @@ -240,10 +241,16 @@ def checkUpdate(self):
if releasesInfo:
self.showUpdateMessageBox.emit(releasesInfo)

def hookManager(self):
def __onHookSwitchChange(self):
if cfg.get(cfg.forceDisconnection):
ctypes.windll.shell32.ShellExecuteW(
win32con.SW_HIDE, "runas", sys.executable, rf"{os.getcwd()}\app\common\hook.py", None, 1)
if "python.exe" in sys.executable: # 未打包
ctypes.windll.shell32.ShellExecuteW(
win32con.SW_HIDE, "runas", sys.executable, rf"{os.getcwd()}\app\common\hook.py -p {os.getpid()}",
None, 0)
else: # 已打包
ctypes.windll.shell32.ShellExecuteW(
win32con.SW_HIDE, "runas", sys.executable, rf"-p {os.getpid()}",
None, 0)

def __onCheckUpdateFailed(self):
InfoBar.warning(
Expand Down
66 changes: 48 additions & 18 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,66 @@
# coding:utf-8
import argparse
import json
import sys
import os
import threading
import time

import psutil
from PyQt5.QtCore import Qt, QLocale, QTranslator
from PyQt5.QtWidgets import QApplication
from qfluentwidgets import FluentTranslator

from app.common.hook import start_hook
from app.view.main_window import MainWindow
from app.common.config import cfg

parser = argparse.ArgumentParser()

parser.add_argument("-p", "--pid", help="master process PID")

args = parser.parse_args()

if __name__ == '__main__':
if cfg.get(cfg.dpiScale) == "Auto":
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
# 传 PID参数 则拉起子进程, 否则运行 GUI
if args.pid:
def _():
while True:
with open(fr"{os.getcwd()}\app\config\config.json", "r", encoding="utf-8") as f:
js = json.loads(f.read())
if not js.get("Functions", {}).get("ForceDisconnection"):
os._exit(0) # 关闭了该设置

for proc in psutil.process_iter():
if proc.pid == int(args.pid):
break
else:
os._exit(0) # 随主进程退出
time.sleep(.3)
threading.Thread(target=_, daemon=True).start()
start_hook()
else:
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "0"
os.environ["QT_SCALE_FACTOR"] = str(cfg.get(cfg.dpiScale))
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
if cfg.get(cfg.dpiScale) == "Auto":
QApplication.setHighDpiScaleFactorRoundingPolicy(
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
else:
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "0"
os.environ["QT_SCALE_FACTOR"] = str(cfg.get(cfg.dpiScale))
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings)

locale = cfg.get(cfg.language).value
translator = FluentTranslator(locale)
lolHelperTranslator = QTranslator()
lolHelperTranslator.load(locale, "Seraphine", ".", "./app/resource/i18n")
locale = cfg.get(cfg.language).value
translator = FluentTranslator(locale)
lolHelperTranslator = QTranslator()
lolHelperTranslator.load(locale, "Seraphine", ".", "./app/resource/i18n")

app.installTranslator(translator)
app.installTranslator(lolHelperTranslator)
app.installTranslator(translator)
app.installTranslator(lolHelperTranslator)

w = MainWindow()
w.show()
w = MainWindow()
w.show()

app.exec_()
app.exec_()
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ PyQt-Fluent-Widgets==1.2.0
Requests==2.31.0
willump==1.4.0
pygetwindow==0.0.9
pyuac==0.0.3

0 comments on commit 5e5fd76

Please sign in to comment.