You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python动态创建带图标的.lnk按钮仅最后一个生效问题求助

问题描述
  • 目标:编写脚本读取运行目录下的.lnk文件,为每个文件创建带对应exe图标的按钮,点击按钮可启动该快捷方式,实现Windows任务栏快捷弹出菜单。
  • 问题:不为tk.Button设置image参数时所有按钮正常工作,一旦添加图标,仅最后创建的按钮能触发点击事件,前几个按钮点击无响应。
  • 现象:前两个按钮点击无任何反应,第三个按钮正常工作;注释掉添加图标的代码后,所有按钮均可正常打开对应的快捷方式。
代码实现
import tkinter as tk
import os
import pyautogui
from win32api import GetSystemMetrics
from PIL import Image, ImageTk
import win32com.client
import win32gui
import win32ui


def execlink(linkpath):
    os.startfile(linkpath)


class IconExtractor:
    def __init__(self):
        self.photo = None
        self.root = None
        self.label = None

    def extract_icon(self, exe_path, ico_path):
        icon_handles, num_icons = win32gui.ExtractIconEx(exe_path, 0)
        if icon_handles:
            h_icon = icon_handles[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), h_icon)
            hbmp.SaveBitmapFile(hdc, ico_path)
            win32gui.DestroyIcon(h_icon)
        else:
            print("No icons found in the executable.")

    def on_closing(self):
        self.root.destroy()

    def main(self, lnk_path, ico_path):
        shell = win32com.client.Dispatch("WScript.Shell")
        shortcut = shell.CreateShortCut(lnk_path)
        target_path = shortcut.TargetPath

        if os.path.exists(target_path):
            self.extract_icon(target_path, ico_path)
            if os.path.exists(ico_path):
                with Image.open(ico_path) as img:
                    img = img.convert("RGBA")
                    self.photo = ImageTk.PhotoImage(img)
        else:
            print("Failed to retrieve the target path.")


class LinksMenu:
    def __init__(self):
        self.MainWindow = tk.Tk()
        self.MainWindow.geometry("100x40+" + str(pyautogui.position()[0]) + "+100")
        self.MainWindow.overrideredirect(True)
        self.MainWindow.bind("<KeyPress>", self.closing)

        self.btnframe = tk.Frame(self.MainWindow)
        self.btnframe.configure(bg='')
        self.btnframe.columnconfigure(0, weight=1)

        count = 1
        files = [File for File in os.listdir('.') if os.path.isfile(File)]

        for File in files:
            if File[-4:] == ".lnk":
                GetImage.main(os.path.realpath(File),
                              os.path.dirname(os.path.realpath(File)) + '\\' + File[0:-4] + '.ico')
                newbutton = tk.Button(
                    self.btnframe,
                    name=File[0:-4].lower() + 'btn',
                    text=File[0:-4],
                    compound=tk.LEFT,
                    image=GetImage.photo,
                    font=('Arial', 14),
                    bg='DodgerBlue4',
                    command=lambda m=os.path.realpath(File): [execlink(m), self.close_after_choice()]
                )
                newbutton.grid(
                    padx=2,
                    pady=2,
                    row=count,
                    column=0,
                    sticky=tk.W+tk.E
                )
                count += 1

        self.btnframe.pack(fill='x')
        self.MainWindow.geometry(
            "300x" + str(count*45) + "+" + str(pyautogui.position()[0]) + "+" + str(GetSystemMetrics(1)-(count*45))
        )
        self.MainWindow.configure(bg='')
        self.MainWindow.mainloop()

    def closing(self, event):
        if event.state == 8 and event.keysym == "Escape":
            self.MainWindow.destroy()

    def close_after_choice(self):
        self.MainWindow.destroy()


if __name__ == "__main__":
    GetImage = IconExtractor()
    LinksMenu()
已尝试的解决方法
  • 将图标保存为png后通过文件路径读取
  • 将图片存入新对象再添加到tk.Button
  • 在内存中将图标转为png后添加到按钮
  • 不动态创建按钮(排除重复使用对象名的问题)
  • 销毁用于获取图片的对象

注:图标提取代码由ChatGPT辅助生成。

内容的提问来源于stack exchange,提问作者TempusFugit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:42:34