吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7467|回复: 57
收起左侧

[原创工具] 便携工具箱 自动识别文件夹和可执行程序

  [复制链接]
暗夜硝烟 发表于 2025-3-22 18:40
本帖最后由 暗夜硝烟 于 2025-3-23 15:06 编辑


只需要在同目录建立文件夹放入可执行exe、bat、等程序,运行该程序自动识别分类,无需配置文件。

下载地址:
https://wwvl.lanzout.com/iVLxH2rc7nbi
密码:52pj


image.png

image.png

编译exe用的是:
人懒所以做个python打包exe工具,支持复杂程序打包 1.1
https://www.52pojie.cn/thread-2007933-1-1.html
(出处: 吾爱破解论坛)

[Python] 纯文本查看 复制代码
import os
import sys
import tkinter as tk
from tkinter import ttk
import win32ui
import win32gui
from PIL import Image, ImageTk
import subprocess
from win32com.client import Dispatch

def get_current_path():
    """自动获取当前程序路径的通用方法"""
    try:
        # 打包后的情况
        if getattr(sys, 'frozen', False):
            return os.path.dirname(sys.executable)  # 返回EXE所在目录
        # 开发环境
        return os.path.dirname(os.path.abspath(__file__))  # 返回脚本所在目录
    except Exception as e:
        print(f"路径获取失败: {e}")
        return os.getcwd()  # 退回当前工作目录

def get_exe_icon(exe_path):
    """从exe文件中提取图标"""
    try:
        # 提取图标
        large, small = win32gui.ExtractIconEx(exe_path, 0)
        win32gui.DestroyIcon(small[0])
        
        # 创建设备上下文
        hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
        hbmp = win32ui.CreateBitmap()
        hbmp.CreateCompatibleBitmap(hdc, 32, 32)
        
        # 在设备上下文中绘制图标
        hdc = hdc.CreateCompatibleDC()
        hdc.SelectObject(hbmp)
        hdc.DrawIcon((0, 0), large[0])
        
        # 获取位图信息和位图数据
        bmpinfo = hbmp.GetInfo()
        bmpstr = hbmp.GetBitmapBits(True)
        
        # 创建PIL图像对象
        img = Image.frombuffer(
            'RGBA',
            (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
            bmpstr, 'raw', 'BGRA', 0, 1
        )
        
        return img
    except Exception as e:
        print(f"提取图标失败: {e}")
        return None

class UniformButton(tk.Frame):
    """统一尺寸的程序按钮组件"""
    def __init__(self, parent, text, image, command):
        super().__init__(parent, bg="white", highlightthickness=0)
        
        # 固定按钮尺寸
        self.button_width = 70
        self.button_height = 90
        self.max_chars = 10
        self.max_lines = 2
        
        self.config(width=self.button_width, height=self.button_height)
        self.pack_propagate(False)
        
        # 主容器
        self.content_frame = tk.Frame(self, bg="white")
        self.content_frame.pack(fill=tk.BOTH, expand=True)

        # 图标区域
        self.icon_label = tk.Label(self.content_frame, 
                                 image=image, 
                                 bg="white",
                                 borderwidth=0)
        self.icon_label.image = image
        self.icon_label.pack(pady=(5, 2), expand=True)

        # 文本区域
        processed_text = self.process_text(text)
        self.text_label = tk.Label(self.content_frame, 
                                 text=processed_text,
                                 wraplength=self.button_width-15,
                                 justify="center",
                                 font=("微软雅黑", 8),
                                 bg="white",
                                 borderwidth=0)
        self.text_label.pack(pady=(0, 5))

        # 事件绑定
        self.bind_all_children("<Button-1>", lambda e: command())
        self.bind("<Enter>", self.on_enter)
        self.bind("<Leave>", self.on_leave)

    def bind_all_children(self, event, handler):
        for child in self.winfo_children():
            child.bind(event, handler)
            if isinstance(child, tk.Frame):
                for subchild in child.winfo_children():
                    subchild.bind(event, handler)

    def process_text(self, text):
        text = text[:20]
        words = text.split()
        lines = []
        current_line = []
        
        for word in words:
            if len(word) > self.max_chars:
                chunks = [word[i:i+self.max_chars] for i in range(0, len(word), self.max_chars)]
                current_line.extend(chunks)
            else:
                current_line.append(word)
            
            if sum(len(w) for w in current_line) + (len(current_line)-1) > self.max_chars:
                lines.append(" ".join(current_line[:-1]))
                current_line = [current_line[-1]]
            
            if len(lines) >= self.max_lines:
                break
        
        if current_line and len(lines) < self.max_lines:
            lines.append(" ".join(current_line))
        
        return "\n".join(lines[:self.max_lines]) + ("..." if len(text) > 20 else "")

    def on_enter(self, event):  
        # pylint: disable=unused-argument
        self.config(bg="#e0e0e0")
        self.content_frame.config(bg="#e0e0e0")
        for child in self.content_frame.winfo_children():
            child.config(bg="#e0e0e0")

    def on_leave(self, event):  
        # pylint: disable=unused-argument
        self.config(bg="white")
        self.content_frame.config(bg="white")
        for child in self.content_frame.winfo_children():
            child.config(bg="white")


class AppLauncher:
    def __init__(self, root):
        self.root = root
        self.root.title("便携工具箱     by:姬御风")
        self.root.geometry("530x400")
        self.root.resizable(False, False)
        self.icon_size = 32
        
        # 设置窗口图标
        self.set_window_icon()
        
        # 主界面
        self.main_frame = ttk.Frame(root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 初始化默认图标
        self.default_icon = self.get_default_icon()
        
        # 组件初始化
        self.create_category_panel()
        self.create_program_panel()
        
        # 数据初始化
        self.current_dir = get_current_path()  # 使用通用路径获取方法
        self.scan_directory()
        self.populate_categories()
        self.show_category("所有程序")

    def set_window_icon(self):
        """设置窗口图标"""
        try:
            # 使用与编译后的exe相同的图标
            exe_path = sys.executable
            icon_img = get_exe_icon(exe_path)
            if icon_img:
                icon_img.save('temp_icon.ico', 'ICO')
                self.root.iconbitmap('temp_icon.ico')
                os.remove('temp_icon.ico')
            else:
                print("无法提取exe图标,使用默认图标")
                self.root.iconbitmap('icon/app.ico')
        except Exception as e:
            print(f"设置窗口图标失败: {e}")

    def resolve_shortcut(self, path):
        """解析快捷方式"""
        try:
            shell = Dispatch('WScript.Shell')
            shortcut = shell.CreateShortCut(path)
            return shortcut.TargetPath
        except Exception as _e:
            print(f"快捷方式解析失败: {path}")
            return None

    def get_program_icon(self, path):
        """增强图标获取"""
        try:
            # 处理快捷方式
            if path.lower().endswith('.lnk'):
                target = self.resolve_shortcut(path)
                if target and os.path.exists(target):
                    path = target
            
            # 获取图标
            large, _ = win32gui.ExtractIconEx(path, 0)
            if not large:
                raise Exception("No icons found")
                
            hicon = large[0]
            hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
            hbmp = win32ui.CreateBitmap()
            hbmp.CreateCompatibleBitmap(hdc, self.icon_size, self.icon_size)
            hdc = hdc.CreateCompatibleDC()
            hdc.SelectObject(hbmp)
            hdc.DrawIcon((0, 0), hicon)
            
            bmpstr = hbmp.GetBitmapBits(True)
            img = Image.frombuffer('RGBA', (self.icon_size, self.icon_size), 
                                 bmpstr, 'raw', 'BGRA', 0, 1)
            return ImageTk.PhotoImage(img)
        except Exception as _e:  
            print(f"图标加载失败: {os.path.basename(path)}")
            return self.default_icon

    def get_default_icon(self):
        """系统默认图标"""
        try:
            # 使用文件夹图标
            shell32 = "C:\\Windows\\System32\\shell32.dll"
            large, _ = win32gui.ExtractIconEx(shell32, 3)
            hicon = large[0]
            
            hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
            hbmp = win32ui.CreateBitmap()
            hbmp.CreateCompatibleBitmap(hdc, self.icon_size, self.icon_size)
            hdc = hdc.CreateCompatibleDC()
            hdc.SelectObject(hbmp)
            hdc.DrawIcon((0, 0), hicon)
            
            bmpstr = hbmp.GetBitmapBits(True)
            img = Image.frombuffer('RGBA', (self.icon_size, self.icon_size),
                                 bmpstr, 'raw', 'BGRA', 0, 1)
            return ImageTk.PhotoImage(img)
        except Exception as _e:  
            print(f"默认图标加载失败: {_e}")
            return ImageTk.PhotoImage(Image.new('RGBA', (self.icon_size, self.icon_size), (240, 240, 240)))

    def create_category_panel(self):
        """分类面板(宽度99)"""
        self.category_frame = ttk.Frame(self.main_frame, width=99)
        self.category_frame.pack(side=tk.LEFT, fill=tk.Y, padx=3)
        
        self.category_canvas = tk.Canvas(self.category_frame, 
                                       width=99,
                                       highlightthickness=0)
        scrollbar = ttk.Scrollbar(self.category_frame, 
                                orient="vertical", 
                                command=self.category_canvas.yview)
        self.category_container = ttk.Frame(self.category_canvas)
        
        self.category_container.bind("<Configure>", 
            lambda e: self.category_canvas.configure(
                scrollregion=self.category_canvas.bbox("all"),
                width=99
            ))
        
        self.category_canvas.create_window((0,0), 
                                        window=self.category_container, 
                                        anchor="nw",
                                        width=99)
        self.category_canvas.configure(yscrollcommand=scrollbar.set)
        
        self.category_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        ttk.Label(self.category_container, 
                text="应用分类", 
                font=("微软雅黑", 9),
                padding=3).pack(pady=5)

    def create_program_panel(self):
        """程序显示面板"""
        self.program_frame = ttk.Frame(self.main_frame)
        self.program_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        self.program_canvas = tk.Canvas(self.program_frame, 
                                     highlightthickness=0)
        scrollbar = ttk.Scrollbar(self.program_frame, 
                                orient="vertical", 
                                command=self.program_canvas.yview)
        self.program_container = ttk.Frame(self.program_canvas)
        
        self.program_container.bind("<Configure>", 
            lambda e: self.program_canvas.configure(
                scrollregion=self.program_canvas.bbox("all")
            ))
        
        self.program_canvas.create_window((0,0), 
                                       window=self.program_container, 
                                       anchor="nw")
        self.program_canvas.configure(yscrollcommand=scrollbar.set)
        
        self.program_canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

    def scan_directory(self):
        """扫描目录"""
        self.categories = {"所有程序": []}
        executable_ext = ['.exe', '.bat', '.cmd', '.lnk']
        
        for item in os.listdir(self.current_dir):
            path = os.path.join(self.current_dir, item)
            
            if os.path.isdir(path):
                self.categories[item] = []
                for root, _, files in os.walk(path):
                    for file in files:
                        if os.path.splitext(file)[1].lower() in executable_ext:
                            full_path = os.path.join(root, file)
                            self.categories[item].append({
                                "name": os.path.splitext(file)[0],
                                "path": full_path
                            })
                            self.categories["所有程序"].append({
                                "name": os.path.splitext(file)[0],
                                "path": full_path
                            })
            else:
                if os.path.splitext(item)[1].lower() in executable_ext:
                    self.categories["所有程序"].append({
                        "name": os.path.splitext(item)[0],
                        "path": path
                    })

    def populate_categories(self):
        """填充分类"""
        for category in self.categories.keys():
            btn = ttk.Button(
                self.category_container,
                text=category,
                command=lambda c=category: self.show_category(c),
                width=12
            )
            btn.pack(fill=tk.X, padx=2, pady=2)

    def show_category(self, category):
        """显示分类"""
        for widget in self.program_container.winfo_children():
            widget.destroy()
            
        programs = self.categories.get(category, [])
        
        if not programs:
            ttk.Label(self.program_container, text="该分类暂无应用").pack(pady=50)
            return
        
        max_columns = 5
        row = col = 0
        
        for idx, program in enumerate(programs):
            col = idx % max_columns
            row = idx // max_columns
            
            button = UniformButton(
                parent=self.program_container,
                text=program["name"],
                image=self.get_program_icon(program["path"]),
                command=lambda p=program["path"]: self.launch_program(p)
            )
            button.grid(row=row, column=col, padx=3, pady=3, sticky="nsew")
            
            self.program_container.grid_columnconfigure(col, weight=1)
            self.program_container.grid_rowconfigure(row, weight=1)

    def launch_program(self, path):
        """启动程序"""
        try:
            subprocess.Popen(f'"{path}"', shell=True)
        except Exception as _e:  
            print(f"启动失败: {_e}")


if __name__ == "__main__":
    root_window = tk.Tk()  
    style = ttk.Style()
    style.configure("TButton", 
                  padding=3, 
                  font=("微软雅黑", 8),
                  width=12)
    style.map("TButton",
            background=[('active', '#f0f0f0')])
    AppLauncher(root_window)
    root_window.mainloop()

免费评分

参与人数 11吾爱币 +15 热心值 +9 收起 理由
段亚栋 + 1 我很赞同!
webdav01 + 1 + 1 支持,就是体积太大了
suke521 + 1 谢谢@Thanks!
x443681912 + 1 + 1 不但想要你的工具箱,而且想要你的工具。望楼主慷慨解囊忍痛割爱!
wyvern + 1 + 1 热心回复!
viconly + 1 + 1 谢谢@Thanks!
rgyjc + 1 + 1 谢谢@Thanks!
ysxc666 + 1 我很赞同!
Issacclark1 + 1 谢谢@Thanks!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
asdskf + 1 + 1 感谢分享~太牛了

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

tsyhome 发表于 2025-3-23 07:51
有点意思,下载试试!
kboylang 发表于 2025-3-23 09:52
平心而论,工具确实很一般需要进一步优化。但还是很感谢分享,首先不能最大话。其次,但扫描的软件和文件夹只针对这个软件所在的文件夹的范围?其他的也看不见。也有BUG需要处理一下,比如多层文件夹它是识别不了的,点击进去是空白。还有,点击部分已安装软件会被360检测拦截"访问的网站域名:r13850507371.6600.org"?
realcsnake 发表于 2025-3-22 19:20
dysunb 发表于 2025-3-22 19:22
这个工具使用率不会太高吧
hubin151587 发表于 2025-3-22 20:43
根据备用很好,使用率不高
dsfive 发表于 2025-3-22 21:14

感谢分享!!
fireflying1984 发表于 2025-3-22 21:59
相当于自己收集的工具软件的整理显示快捷图标?
blhying 发表于 2025-3-22 22:45
看介绍,这个工具放在U盘里用好象很不错的样子!U盘里的东西也可以直接列出来?
xiaoshuimian 发表于 2025-3-22 22:58
好像没完全看懂
执手偕老 发表于 2025-3-22 23:26
意思就是可以自己扩展升级的便携工具箱吧?这个装机很方便
yctx2050 发表于 2025-3-23 00:23
本帖最后由 yctx2050 于 2025-3-23 00:39 编辑

感谢楼主分享
文件自动识别成文件夹了

能不能增加网址自动识别?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-20 01:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表