diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e41b655f100dc6f053631b2f53985a0e350e7c43 --- /dev/null +++ b/config/__init__.py @@ -0,0 +1,32 @@ +from .app_config import * + +__all__=[ + # 应用程序基本信息 + APP_VERSION, + APP_NAME, + DEFAULT_WINDOW_TITLE, + + # 路径配置 + DESKTOP_ICO_PATH, RESOURCES_PATH, FILE_ICO_PATH, + CONFIG_FILE, BUGS_REPORT_DIR, EMPTY_XLSX_TEMPLATE, + + # Windows API 常量 + SM_CXSCREEN, SM_CYSCREEN, GWL_EXSTYLE, + WS_EX_TOOLWINDOW, WS_EX_APPWINDOW, + + # 动画和界面常量 + ANIMATION_STEPS, ANIMATION_DELAY, WINDOW_WIDTH_RATIO, + WINDOW_HEIGHT_RATIO, WINDOW_POSITION_RATIO, TOLERANCE, + CORNER_SIZE, WAIT_TIMEOUT, SLEEP_INTERVAL, MOUSE_CHECK_INTERVAL, + + # 文件类型配置 + SCRIPTS_TYPE, FILE_ICO, + + # 系统应用程序和命令配置 + SYSTEM_APPS, SYSTEM_COMMANDS, MIHOYO_GAMES, + + # 默认配置函数 + get_default_config + +] + diff --git a/config/app_config.py b/config/app_config.py new file mode 100644 index 0000000000000000000000000000000000000000..4cd366da1fc27a3da08c831cf3b6565e193bd2ba --- /dev/null +++ b/config/app_config.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- +""" +EasyDesktop 配置文件 +包含应用程序的所有配置常量和默认设置 +""" + +# ===== 应用程序基本信息 ===== +APP_VERSION = "1.8.0" +APP_NAME = "EasyDesktop" +DEFAULT_WINDOW_TITLE = "EasyDesktop" + +# ===== 路径配置 ===== +DESKTOP_ICO_PATH = "./desktopICO/" +RESOURCES_PATH = "./resources/" +FILE_ICO_PATH = "./resources/file_icos/" +CONFIG_FILE = "config.json" +BUGS_REPORT_DIR = "bugs_report" +EMPTY_XLSX_TEMPLATE = "resources/empty.xlsx" + +# ===== Windows API 常量 ===== +SM_CXSCREEN = 0 # 屏幕宽度 +SM_CYSCREEN = 1 # 屏幕高度 +GWL_EXSTYLE = -20 +WS_EX_TOOLWINDOW = 0x00000080 +WS_EX_APPWINDOW = 0x00040000 + +# ===== 动画和界面常量 ===== +ANIMATION_STEPS = 60 +ANIMATION_DELAY = 0.003 +WINDOW_WIDTH_RATIO = 0.65 +WINDOW_HEIGHT_RATIO = 0.4 +WINDOW_POSITION_RATIO = 0.1 +TOLERANCE = 5 # 像素容差 +CORNER_SIZE = 100 # 角落区域的边长 +WAIT_TIMEOUT = 3 # 等待超时时间(秒) +SLEEP_INTERVAL = 0.4 # 循环间隔(秒) +MOUSE_CHECK_INTERVAL = 0.1 # 鼠标检查间隔(秒) + +# ===== 支持的脚本文件类型 ===== +SCRIPTS_TYPE = [ + ".py", + ".java", + ".c", + ".vbs", + ".cpp", + ".h", + ".hpp", + ".cs", + ".php", + ".rb", + ".go", + ".swift", + ".kt", + ".m", + ".pl", + ".r", + ".sh", + ".bash", + ".zsh", + ".lua", + ".scala", + ".groovy", + ".dart", + ".rs", + ".jl", + ".hs", + ".f", + ".f90", + ".f95", + ".v", + ".vhd", + ".clj", + ".ex", + ".exs", + ".elm", + ".purs", + ".erl", + ".hrl", + ".fs", + ".fsx", + ".fsi", + ".ml", + ".mli", + ".pas", + ".pp", + ".d", + ".nim", + ".cr", + ".cbl", + ".cob", + ".ada", + ".adb", + ".ads", +] + +# ===== 文件图标映射 ===== +FILE_ICO = { + ".mp3": "./resources/file_icos/mp3.png", + ".mp4": "./resources/file_icos/mp4.png", + ".mkv": "./resources/file_icos/mkv.png", + ".m4a": "./resources/file_icos/m4a.png", + ".doc": "./resources/file_icos/doc.png", + ".docx": "./resources/file_icos/docx.png", + ".xls": "./resources/file_icos/xls.png", + ".xlsx": "./resources/file_icos/xlsx.png", + ".pdf": "./resources/file_icos/pdf.png", + ".ppt": "./resources/file_icos/ppt.png", + ".pptx": "./resources/file_icos/pptx.png", + ".zip": "./resources/file_icos/zip.png", + ".rar": "./resources/file_icos/zip.png", + ".png": "./resources/file_icos/image.png", + ".jpg": "./resources/file_icos/image.png", + ".jpeg": "./resources/file_icos/image.png", + ".gif": "./resources/file_icos/image.png", + ".txt": "./resources/file_icos/txt.png", + ".html": "./resources/file_icos/html.png", + ".css": "./resources/file_icos/css.png", + ".js": "./resources/file_icos/js.png", + ".bat": "./resources/file_icos/bat.png", + "unkonw": "./resources/file_icos/unkonw.png", +} + +# ===== 应用程序默认配置 ===== +def get_default_config(width, height): + """ + 获取默认配置字典 + + Args: + width (int): 窗口宽度 + height (int): 窗口高度 + + Returns: + dict: 默认配置字典 + """ + return { + "theme": "light", + "language": "zh-CN", + "follow_sys": True, + "view": "block", + "auto_start": False, + "use_bg": False, + "bg": "", + "ms_ef": 0, + "ign_update": "", + "width": width, + "height": height, + "full_screen": False, + "fdr": True, + "cf_type": "1", + "out_cf_type": "1", + "show_sysApp": False, + "scale": 100, + "df_dir": "desktop", + "df_dir_name": "桌面", + "of_s": True, + } + +# ===== 系统应用程序配置 ===== +SYSTEM_APPS = [ + { + "fileName": "此电脑", + "fileType": "应用程序", + "file": "_.exe", + "filePath": "此电脑", + "ico": "./resources/file_icos/cdn.png", + "sysApp": True, + }, + { + "fileName": "控制面板", + "fileType": "应用程序", + "file": "_.exe", + "filePath": "控制面板", + "ico": "./resources/file_icos/kzmb.png", + "sysApp": True, + }, + { + "fileName": "回收站", + "fileType": "应用程序", + "file": "_.exe", + "filePath": "回收站", + "ico": "./resources/file_icos/rbs.png", + "sysApp": True, + }, +] + +# ===== Windows 系统组件命令 ===== +SYSTEM_COMMANDS = { + "此电脑": r"explorer.exe shell:MyComputerFolder", + "控制面板": r"explorer.exe shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}", + "回收站": r"explorer.exe shell:RecycleBinFolder", +} + +# ===== 米哈游游戏图标映射 ===== +MIHOYO_GAMES = { + "原神": "./resources/file_icos/ys.ico", + "Genshin Impact": "./resources/file_icos/ys.ico", + "星穹铁道": "./resources/file_icos/sr.ico", + "Star Rail": "./resources/file_icos/sr.ico", + "绝区零": "./resources/file_icos/zzz.ico", + "Zero": "./resources/file_icos/zzz.ico", + "崩坏3": "./resources/file_icos/bh3.ico", + "Honkai Impact 3": "./resources/file_icos/bh3.ico", + "default": "./resources/file_icos/mhy_lancher.ico", +} \ No newline at end of file diff --git a/easyDesktop.py b/easyDesktop.py index e07f697ad4bf6eff09a2d5e721861bfbab6557cb..4acd6627bb9af7f38bcc4a9dccf2ab7bc25b3151 100644 --- a/easyDesktop.py +++ b/easyDesktop.py @@ -4,173 +4,124 @@ import win32com.client import win32gui import win32api import win32con -# import win32event import time import webview import pystray import subprocess -from pypinyin import pinyin, Style ,lazy_pinyin +from pypinyin import pinyin, Style, lazy_pinyin import shutil import darkdetect import json from PIL import Image import winreg as reg import sys -from easygui import msgbox,buttonbox +from easygui import msgbox, buttonbox from ctypes import windll from threading import Thread from requests import get as requests_get import webbrowser -from pyautogui import size import keyboard import send2trash import re import win32ui -import pygetwindow as gw +import config as cfg + + +has_opened_window = False +key_quick_start = False +has_cleared_fit = False +fullscreen_close = False +resize_window = None +ignore_action = False +loaded_exe_cache = {} +window_state = False +moving = False +icon = None +hwnd = None +os.environ["FUSION_LOG"] = "1" +os.environ["FUSION_LOG_PATH"] = "/logs/" -# def is_already_running(): -# mutex_name = windll.kernel32.CreateMutexW(None, False,"EasyDesktop_Mutex_UniqueName") -# try: -# mutex = win32event.CreateMutex(None, False, mutex_name) -# last_error = win32api.GetLastError() - -# if last_error == win32event.ERROR_ALREADY_EXISTS: -# return False -# return True -# except: -# return True -# if is_already_running(): -# os._exit(0) try: - json.dump("",open("test.json","w",encoding="utf-8")) + json.dump("", open("test.json", "w", encoding="utf-8")) except PermissionError: - msgbox("遇到权限问题,请以管理员身份运行或将软件安装到非C盘目录,否则将无法使用自定义背景及设置保存功能。","EasyDesktop") + msgbox( + "遇到权限问题,请以管理员身份运行或将软件安装到非C盘目录,否则将无法使用自定义背景及设置保存功能。", + cfg.APP_NAME, + ) finally: if os.path.exists("test.json"): os.remove("test.json") -icon = None -hwnd = None -os.environ["FUSION_LOG"] = "1" -os.environ["FUSION_LOG_PATH"] = "/logs/" + try: - dll_path = os.environ.get('PYTHONNET_PYDLL') + dll_path = os.environ.get("PYTHONNET_PYDLL") if dll_path and os.path.exists(dll_path): windll(dll_path) # 测试直接加载 except: msgbox("无法加载pythonnet") + + def get_real_path(): - if getattr(sys, 'frozen', False): + if getattr(sys, "frozen", False): return os.path.dirname(sys.executable) else: return os.path.dirname(os.path.abspath(__file__)) + + os.chdir(get_real_path()) -def get_screenSize(): - r1_width = win32api.GetSystemMetrics(0) - r1_height = win32api.GetSystemMetrics(1) - r2_width,r2_height = size() - if r1_width==r2_width and r1_height==r2_height: - return r2_width,r2_height - else: - add_c_1 = r1_width+r1_width - add_c_2 = r2_height+r2_height - if add_c_1>add_c_2: - return r1_width,r1_height - else: - return r2_width,r2_height - -screen_width,screen_height=get_screenSize() -print(screen_width,screen_height) -width = int(screen_width*0.65) -height = int(screen_height*0.4) -defeat_config = { - "theme":"light", - "language":"zh-CN", - "follow_sys":True, - "theme": "light", - "view":"block", - "auto_start":False, - "use_bg":False, - "bg":"", - "ms_ef":0, - "ign_update":"", - "width":width, - "height":height, - "full_screen":False, - "fdr":True, - "cf_type":"1", - "out_cf_type":"1", - "show_sysApp":False, - "scale":100, - "df_dir":"desktop", - "df_dir_name":"桌面", - "of_s":True - } -if os.path.exists("config.json"): - config = json.load(open("config.json")) - for c_item in defeat_config.keys(): +def get_screen_size(): + # 使用原生 Windows API 获取屏幕尺寸 + screen_width = win32api.GetSystemMetrics(cfg.SM_CXSCREEN) + screen_height = win32api.GetSystemMetrics(cfg.SM_CYSCREEN) + return screen_width, screen_height + + +def get_active_window(): + """获取当前活动窗口的句柄,如果没有则返回 None""" + hwnd = win32gui.GetForegroundWindow() + return hwnd if hwnd else None + + +screen_width, screen_height = get_screen_size() +print(screen_width, screen_height) +width = int(screen_width * cfg.WINDOW_WIDTH_RATIO) +height = int(screen_height * cfg.WINDOW_HEIGHT_RATIO) +default_config = cfg.get_default_config(width, height) +if os.path.exists(cfg.CONFIG_FILE): + config = json.load(open(cfg.CONFIG_FILE)) + for c_item in default_config.keys(): if c_item not in config.keys(): - config[c_item] = defeat_config[c_item] - json.dump(config, open("config.json", "w")) + config[c_item] = default_config[c_item] + json.dump(config, open(cfg.CONFIG_FILE, "w")) else: - config = defeat_config - json.dump(config, open("config.json", "w")) + config = default_config + json.dump(config, open(cfg.CONFIG_FILE, "w")) + -had_open_win = False -key_quik_start = False -had_clear_fit = False -fullS_close = False -resize_window = None -ignore_action = False -had_load_exe = {} -window_state = False -moving = False -file_ico_path = "./resources/file_icos/" -scripts_type=[".py",".java",".c",".vbs",".cpp",".h",".hpp",".cs",".php",".rb",".go",".swift",".kt",".m",".pl",".r",".sh",".bash",".zsh",".lua",".scala",".groovy",".dart",".rs",".jl",".hs",".f",".f90",".f95",".v",".vhd",".clj",".ex",".exs",".elm",".purs",".erl",".hrl",".fs",".fsx",".fsi",".ml",".mli",".pas",".pp",".d",".nim",".cr",".cbl",".cob",".ada",".adb",".ads"] -file_ico = { - ".mp3":"./resources/file_icos/mp3.png", - ".mp4":"./resources/file_icos/mp4.png", - ".mkv":"./resources/file_icos/mkv.png", - ".m4a":"./resources/file_icos/m4a.png", - ".doc":"./resources/file_icos/doc.png", - ".docx":"./resources/file_icos/docx.png", - ".xls":"./resources/file_icos/xls.png", - ".xlsx":"./resources/file_icos/xlsx.png", - ".pdf":"./resources/file_icos/pdf.png", - ".ppt":"./resources/file_icos/ppt.png", - ".pptx":"./resources/file_icos/pptx.png", - - ".zip":"./resources/file_icos/zip.png", - ".rar":"./resources/file_icos/zip.png", - ".png":"./resources/file_icos/image.png", - ".jpg":"./resources/file_icos/image.png", - ".jpeg":"./resources/file_icos/image.png", - ".gif":"./resources/file_icos/image.png", - - ".txt":"./resources/file_icos/txt.png", - ".html":"./resources/file_icos/html.png", - ".css":"./resources/file_icos/css.png", - ".js":"./resources/file_icos/js.png", - ".bat":"./resources/file_icos/bat.png", - - "unkonw":"./resources/file_icos/unkonw.png" -} def putOut_window(cf): - global key_quik_start,config,window_state,fullS_close + global key_quick_start, config, window_state, fullscreen_close if cf == config["cf_type"]: if window_state == False: - key_quik_start = True + key_quick_start = True else: - fullS_close = True + fullscreen_close = True + + def key_cf2(): putOut_window("2") + + def key_cf3(): putOut_window("3") -keyboard.add_hotkey('windows+shift',key_cf2) -keyboard.add_hotkey('windows+`',key_cf3) + + +keyboard.add_hotkey("windows+shift", key_cf2) +keyboard.add_hotkey("windows+`", key_cf3) + + def get_sfb(): windll.user32.SetProcessDPIAware() try: @@ -180,57 +131,87 @@ def get_sfb(): return scaling_percentage except AttributeError: return 1.5 + + def turn_png(file_path): try: # 检查文件是否存在 if not os.path.exists(file_path): print(f"错误:文件 '{file_path}' 不存在") return False - + # 检查文件扩展名是否为ico - if not file_path.lower().endswith('.ico'): + if not file_path.lower().endswith(".ico"): print(f"错误:文件 '{file_path}' 不是ICO文件") return False - - # 打开ICO文件 - with Image.open(file_path) as img: - png_path = os.path.splitext(file_path)[0] + '.png' - img.save(png_path, 'PNG') - # os.remove(file_path) - return png_path - + + # 打开ICO文件并抑制警告 + import warnings + with warnings.catch_warnings(): + warnings.simplefilter("ignore", UserWarning) + with Image.open(file_path) as img: + # 获取最大尺寸的图标 + if hasattr(img, 'size') and img.size[0] > 0: + png_path = os.path.splitext(file_path)[0] + ".png" + img.save(png_path, "PNG") + return png_path + else: + return "./resources/file_icos/exe.png" + except Exception as e: - print(f"转换过程中发生错误: {str(e)}") - return "/resources/file_icos/exe.png" + print(f"转换ICO到PNG过程中发生错误: {str(e)}") + return "./resources/file_icos/exe.png" + + def get_desktop_path(): shell = win32com.client.Dispatch("WScript.Shell") return shell.SpecialFolders("Desktop") -def get_icon(exe_path,name): + + +def get_icon(exe_path, name): try: - dir_name = os.path.dirname(exe_path).replace("/","-").replace(R"\\","-").replace(":","-") - if not os.path.exists("./desktopICO/"+dir_name): - os.makedirs("./desktopICO/"+dir_name) - output_path = "./desktopICO/"+dir_name+"/"+name+'.ico' - extractor = IconExtractor(exe_path) - extractor.export_icon(output_path) - output_path=turn_png(output_path) - had_load_exe[exe_path]=output_path - return output_path + dir_name = os.path.dirname(exe_path).replace("/", "-").replace(R"\\", "-").replace(":", "-") + if not os.path.exists(cfg.DESKTOP_ICO_PATH + dir_name): + os.makedirs(cfg.DESKTOP_ICO_PATH + dir_name) + output_path = cfg.DESKTOP_ICO_PATH + dir_name + "/" + name + ".ico" + + # 检查exe文件是否存在 + if not os.path.exists(exe_path): + print(f"警告:EXE文件不存在 {exe_path}") + return "./resources/file_icos/exe.png" + + try: + extractor = IconExtractor(exe_path) + extractor.export_icon(output_path) + output_path = turn_png(output_path) + if output_path and output_path != "./resources/file_icos/exe.png": + loaded_exe_cache[exe_path] = output_path + return output_path + else: + # 如果转换失败,使用默认图标 + print(f"图标转换失败,使用默认图标: {exe_path}") + return "./resources/file_icos/exe.png" + except Exception as extract_error: + print(f"图标提取失败: {extract_error} - {exe_path}") + return "./resources/file_icos/exe.png" + except Exception as e: - print(e, "\n", exe_path) - return "/resources/file_icos/exe.png" + print(f"获取图标时发生未知错误: {e} - {exe_path}") + return "./resources/file_icos/exe.png" + + def get_url_icon(url_path): print(url_path) - dir_name = os.path.dirname(url_path).replace("/","-").replace(R"\\","-").replace(":","-") + dir_name = os.path.dirname(url_path).replace("/", "-").replace(R"\\", "-").replace(":", "-") # 解析 .url 文件 icon_file = None icon_index = 0 try: - with open(url_path, 'r', encoding='utf-8') as f: + with open(url_path, "r", encoding="utf-8") as f: content = f.read() - icon_match = re.search(r'IconFile\s*=\s*(.*)', content, re.IGNORECASE) - index_match = re.search(r'IconIndex\s*=\s*(\d+)', content, re.IGNORECASE) - + icon_match = re.search(r"IconFile\s*=\s*(.*)", content, re.IGNORECASE) + index_match = re.search(r"IconIndex\s*=\s*(\d+)", content, re.IGNORECASE) + if icon_match: icon_file = icon_match.group(1).strip() if icon_file.startswith('"') and icon_file.endswith('"'): @@ -239,7 +220,7 @@ def get_url_icon(url_path): if not os.path.isabs(icon_file): base_dir = os.path.dirname(os.path.abspath(url_path)) icon_file = os.path.join(base_dir, icon_file) - + if index_match: icon_index = int(index_match.group(1)) except Exception as e: @@ -266,23 +247,21 @@ def get_url_icon(url_path): hdc.DrawIcon((0, 0), hicon) bmp_info = hbmp.GetInfo() bmp_bytes = hbmp.GetBitmapBits(True) - image = Image.frombuffer( - 'RGBA', - (bmp_info['bmWidth'], bmp_info['bmHeight']), - bmp_bytes, 'raw', 'BGRA', 0, 1 - ) - + image = Image.frombuffer("RGBA", (bmp_info["bmWidth"], bmp_info["bmHeight"]), bmp_bytes, "raw", "BGRA", 0, 1) + # 清理资源 win32gui.DestroyIcon(hicon) del hdc del hbmp - if not os.path.exists("./desktopICO/"+dir_name): - os.makedirs("./desktopICO/"+dir_name) - image.save("./desktopICO/"+dir_name+"/"+os.path.basename(url_path)+'.png') - return "./desktopICO/"+dir_name+"/"+os.path.basename(url_path)+'.png' + if not os.path.exists(cfg.DESKTOP_ICO_PATH + dir_name): + os.makedirs(cfg.DESKTOP_ICO_PATH + dir_name) + image.save(cfg.DESKTOP_ICO_PATH + dir_name + "/" + os.path.basename(url_path) + ".png") + return cfg.DESKTOP_ICO_PATH + dir_name + "/" + os.path.basename(url_path) + ".png" except Exception as e: print(f"提取图标失败: {e}") return "/resources/file_icos/exe.png" + + def get_shortcut_target(shortcut_path): if not os.path.exists(shortcut_path): raise FileNotFoundError(f"快捷方式文件 {shortcut_path} 不存在") @@ -291,33 +270,36 @@ def get_shortcut_target(shortcut_path): shortcut = shell.CreateShortcut(shortcut_path) return shortcut.TargetPath + def match_ico(file_name): extension = os.path.splitext(file_name)[1] - if extension in file_ico: - return file_ico[extension] - elif extension in scripts_type: - return "/resources/file_icos/script.png" + if extension in cfg.FILE_ICO: + return cfg.FILE_ICO[extension] + elif extension in cfg.SCRIPTS_TYPE: + return "./resources/file_icos/script.png" else: - return file_ico["unkonw"] -def check_recover(data,match): + return cfg.FILE_ICO["unkonw"] + + +def check_recover(data, match): result = False for d in data: - if d["filePath"]==match["filePath"] and d["fileName"]==match["fileName"]: + if d["filePath"] == match["filePath"] and d["fileName"] == match["fileName"]: result = True break return result + + def update_inf(dir_path): global config out_data = [] exe_data = [] dir_data = [] file_data = [] - # if os.path.exists("desktopICO"): - # os.remove("desktopICO") - # os.mkdir("desktopICO") + if dir_path == "desktop": get_count = 2 - path_list = [desktop_path,public_desktop] + path_list = [desktop_path, public_desktop] else: get_count = 1 path_list = [dir_path] @@ -336,116 +318,189 @@ def update_inf(dir_path): if ".exe" == extension: # 针对米哈游游戏的适配 if "miHoYo" in target_path and "launcher" in target_path: - if "原神" in item or "Genshin Impact" in item: - exe_icon = "./resources/file_icos/ys.ico" - elif "星穹铁道" in item or "Star Rail" in item: - exe_icon = "./resources/file_icos/sr.ico" - elif "绝区零" in item or "Zero" in item: - exe_icon = "./resources/file_icos/zzz.ico" - elif "崩坏3" in item or "Honkai Impact 3" in item: - exe_icon = "./resources/file_icos/bh3.ico" - else: - exe_icon = "./resources/file_icos/mhy_lancher.ico" - exe_data.append({"fileName":filename,"fileType":extension,"file":os.path.basename(target_path),"filePath":full_path,"ico":exe_icon}) + exe_icon = cfg.MIHOYO_GAMES["default"] # 默认值 + for game_name, icon_path in cfg.MIHOYO_GAMES.items(): + if game_name != "default" and game_name in item: + exe_icon = icon_path + break + exe_data.append( + { + "fileName": filename, + "fileType": extension, + "file": os.path.basename(target_path), + "filePath": full_path, + "ico": exe_icon, + } + ) else: - if not target_path in had_load_exe: - exe_icon=get_icon(target_path,item) + if not target_path in loaded_exe_cache: + exe_icon = get_icon(target_path, item) else: - exe_icon = had_load_exe[target_path] - exe_data.append({"fileName":filename,"fileType":extension,"file":os.path.basename(target_path),"filePath":full_path,"ico":exe_icon}) + exe_icon = loaded_exe_cache[target_path] + exe_data.append( + { + "fileName": filename, + "fileType": extension, + "file": os.path.basename(target_path), + "filePath": full_path, + "ico": exe_icon, + } + ) continue elif ".url" == extension: icon_image = get_url_icon(target_path) - exe_data.append({"fileName":filename,"fileType":extension,"file":os.path.basename(full_path),"filePath":full_path,"ico":icon_image}) + exe_data.append( + { + "fileName": filename, + "fileType": extension, + "file": os.path.basename(full_path), + "filePath": full_path, + "ico": icon_image, + } + ) else: if os.path.isfile(target_path): - file_data.append({"fileName":filename,"fileType":extension,"file":item,"filePath":target_path,"ico":match_ico(item)}) + file_data.append( + { + "fileName": filename, + "fileType": extension, + "file": item, + "filePath": target_path, + "ico": match_ico(item), + } + ) else: - dir_data.append({"fileName":os.path.basename(full_path),"fileType":"文件夹","file":item,"filePath":target_path,"ico":"./resources/file_icos/dir.png","mark":1}) + dir_data.append( + { + "fileName": os.path.basename(full_path), + "fileType": "文件夹", + "file": item, + "filePath": target_path, + "ico": "./resources/file_icos/dir.png", + "mark": 1, + } + ) continue elif ".url" == extension: icon_image = get_url_icon(full_path) - exe_data.append({"fileName":filename,"fileType":extension,"file":os.path.basename(full_path),"filePath":full_path,"ico":icon_image}) + exe_data.append( + { + "fileName": filename, + "fileType": extension, + "file": os.path.basename(full_path), + "filePath": full_path, + "ico": icon_image, + } + ) else: - file_data.append({"fileName":filename,"fileType":extension,"file":item,"filePath":full_path,"ico":match_ico(item)}) + file_data.append( + { + "fileName": filename, + "fileType": extension, + "file": item, + "filePath": full_path, + "ico": match_ico(item), + } + ) else: - dir_data.append({"fileName":item,"fileType":"文件夹","file":item,"filePath":full_path,"ico":"./resources/file_icos/dir.png","mark":2}) + dir_data.append( + { + "fileName": item, + "fileType": "文件夹", + "file": item, + "filePath": full_path, + "ico": "./resources/file_icos/dir.png", + "mark": 2, + } + ) # if config["show_sysApp"]==True: - if config["show_sysApp"]==True and (dir_path=="desktop" or dir_path=="" or dir_path=="/" or dir_path==desktop_path or dir_path==public_desktop): - sys_app_data=[ - {"fileName":"此电脑","fileType":"应用程序","file":"_.exe","filePath":"此电脑","ico":"./resources/file_icos/cdn.png","sysApp":True}, - {"fileName":"控制面板","fileType":"应用程序","file":"_.exe","filePath":"控制面板","ico":"./resources/file_icos/kzmb.png","sysApp":True}, - {"fileName":"回收站","fileType":"应用程序","file":"_.exe","filePath":"回收站","ico":"./resources/file_icos/rbs.png","sysApp":True} - ] - for item in sys_app_data: + if config["show_sysApp"] == True and ( + dir_path == "desktop" + or dir_path == "" + or dir_path == "/" + or dir_path == desktop_path + or dir_path == public_desktop + ): + for item in cfg.SYSTEM_APPS: out_data.append(item) for item in exe_data: - if check_recover(out_data,item)==True: + if check_recover(out_data, item) == True: continue out_data.append(item) for item in dir_data: - if check_recover(out_data,item)==True: + if check_recover(out_data, item) == True: continue out_data.append(item) for item in file_data: - if check_recover(out_data,item)==True: + if check_recover(out_data, item) == True: continue out_data.append(item) return out_data -GWL_EXSTYLE = -20 -WS_EX_TOOLWINDOW = 0x00000080 -WS_EX_APPWINDOW = 0x00040000 + + def hide_from_taskbar(window): hwnd = windll.user32.FindWindowW(None, window.title) - style = windll.user32.GetWindowLongW(hwnd, GWL_EXSTYLE) - style = (style | WS_EX_TOOLWINDOW) & ~WS_EX_APPWINDOW - windll.user32.SetWindowLongW(hwnd, GWL_EXSTYLE, style) + style = windll.user32.GetWindowLongW(hwnd, cfg.GWL_EXSTYLE) + style = (style | cfg.WS_EX_TOOLWINDOW) & ~cfg.WS_EX_APPWINDOW + windll.user32.SetWindowLongW(hwnd, cfg.GWL_EXSTYLE, style) + + def is_focused_window_fullscreen(): try: # 获取当前获焦窗口 - active_window = gw.getActiveWindow() - - if not active_window: + active_hwnd = get_active_window() + + if not active_hwnd: return False - screen_width, screen_height = get_screenSize() - window = active_window - if window.title == "Program Manager" or window.title == "": + + # 获取窗口标题 + window_title = win32gui.GetWindowText(active_hwnd) + if window_title == "Program Manager" or window_title == "": return False - window_left, window_top = window.left, window.top - window_width, window_height = window.width, window.height + + # 获取窗口尺寸和位置信息 + rect = win32gui.GetWindowRect(active_hwnd) + window_left, window_top = rect[0], rect[1] + window_width, window_height = rect[2] - rect[0], rect[3] - rect[1] + screen_width, screen_height = get_screen_size() # 检查窗口是否覆盖整个屏幕(允许几个像素的误差) - tolerance = 5 # 像素容差 - return (abs(window_left) <= tolerance and - abs(window_top) <= tolerance and - abs(window_width - screen_width) <= tolerance and - abs(window_height - screen_height) <= tolerance) - + tolerance = cfg.TOLERANCE # 像素容差 + return ( + abs(window_left) <= tolerance + and abs(window_top) <= tolerance + and abs(window_width - screen_width) <= tolerance + and abs(window_height - screen_height) <= tolerance + ) + except Exception as e: print(f"检测全屏时出错: {e}") return False + + def is_ed_focused(): - active_window = gw.getActiveWindow() - if not active_window: - return False - if active_window.title == "easyDesktop": - return True - else: + active_hwnd = get_active_window() + if not active_hwnd: return False + window_title = win32gui.GetWindowText(active_hwnd) + return window_title == cfg.DEFAULT_WINDOW_TITLE + + def is_desktop_and_mouse_in_corner(): try: - screen_width = win32api.GetSystemMetrics(0) - screen_height = win32api.GetSystemMetrics(1) - corner_size = 100 # 角落区域的边长 + screen_width = win32api.GetSystemMetrics(cfg.SM_CXSCREEN) + screen_height = win32api.GetSystemMetrics(cfg.SM_CYSCREEN) + corner_size = cfg.CORNER_SIZE # 角落区域的边长 corner_rect = (0, screen_height - corner_size, corner_size, screen_height) mouse_x, mouse_y = win32api.GetCursorPos() - in_corner = (corner_rect[0] <= mouse_x <= corner_rect[2] and - corner_rect[1] <= mouse_y <= corner_rect[3]) + in_corner = corner_rect[0] <= mouse_x <= corner_rect[2] and corner_rect[1] <= mouse_y <= corner_rect[3] return in_corner except Exception as e: print(f"Error: {e}") return False + + def is_mouse_in_easyDesktop(): - hwnd = win32gui.FindWindow(None, "easyDesktop") + hwnd = win32gui.FindWindow(None, cfg.DEFAULT_WINDOW_TITLE) if not hwnd: return False try: @@ -456,82 +511,101 @@ def is_mouse_in_easyDesktop(): return in_window except: return False + + def wait_open(): - global key_quik_start,config + global key_quick_start, config start_wait_time = int(time.time()) - had_reflesh = False + had_refresh = False while True: - if int(time.time())-start_wait_time>3: - if had_reflesh==False: + if int(time.time()) - start_wait_time > cfg.WAIT_TIMEOUT: + if had_refresh == False: window.evaluate_js("document.getElementById('b2d').click()") - had_reflesh = True - if config["fdr"]==True: - if is_focused_window_fullscreen()==True: + had_refresh = True + if config["fdr"] == True: + if is_focused_window_fullscreen() == True: time.sleep(1) continue - if config["cf_type"]=="2" or config["cf_type"]=="3": - if key_quik_start==True: + if config["cf_type"] == "2" or config["cf_type"] == "3": + if key_quick_start == True: out_window() break else: if is_desktop_and_mouse_in_corner(): out_window() break - if window_state==True: + if window_state == True: break - time.sleep(0.4) + time.sleep(cfg.SLEEP_INTERVAL) + + def ease_out_quad(t): # 缓动函数 return t * (2 - t) + def get_window_rect(hwnd): # 获取窗口矩形区域 rect = win32gui.GetWindowRect(hwnd) return { - 'left': rect[0], - 'top': rect[1], - 'right': rect[2], - 'bottom': rect[3], - 'width': rect[2] - rect[0], - 'height': rect[3] - rect[1] + "left": rect[0], + "top": rect[1], + "right": rect[2], + "bottom": rect[3], + "width": rect[2] - rect[0], + "height": rect[3] - rect[1], } -def animate_window(hwnd, start_x, start_y, end_x, end_y, width, height, steps=60, delay=0.003): - global window,config - screen_width, screen_height = get_screenSize() + +def animate_window(hwnd, start_x, start_y, end_x, end_y, width, height, steps=cfg.ANIMATION_STEPS, delay=cfg.ANIMATION_DELAY): + global window, config + screen_width, screen_height = get_screen_size() for i in range(steps + 1): progress = i / steps eased_progress = ease_out_quad(progress) current_x = start_x + (end_x - start_x) * eased_progress current_y = start_y + (end_y - start_y) * eased_progress - if config["full_screen"]==True: - if start_x