如何使用PyWin32从exe文件加载嵌入式图标?
我有一个用py2exe生成的exe文件。在setup.py中,我指定要在exe中嵌入的图标:
windows=[{'script': 'my_script.py','icon_resources': [(0, 'my_icon.ico')], ...
我尝试使用以下方式加载图标:
hinst = win32api.GetModuleHandle(None) hicon = win32gui.LoadImage(hinst, 0, win32con.IMAGE_ICON, 0, 0, win32con.LR_DEFAULTSIZE)
但这会产生(非常不确定的)错误:
pywintypes.error:(0,'LoadImage','没有错误消息可用')
如果我尝试将0指定为字符串
hicon = win32gui.LoadImage(hinst, '0', win32con.IMAGE_ICON, 0, 0, win32con.LR_DEFAULTSIZE)
然后我得到错误:
pywintypes.error:(1813,'LoadImage','在图像文件中找不到指定的资源类型。')
那么,加载图标的正确方法/语法是什么?
另外请注意,我不使用任何GUI工具包,而是通过PyWin32使用Windows API。
解决方案
我们应该将图标ID设置为非0的值:
'icon_resources': [(42, 'my_icon.ico')]
Windows资源ID必须介于1到32767之间。
如果我们使用的是wxPython,则可以使用以下简单代码:
wx.Icon(sys.argv[0], wx.BITMAP_TYPE_ICO)
我通常有检查其是否从EXE运行的代码,并采取相应的措施:
def get_app_icon(): if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe": return wx.Icon(sys.argv[0], wx.BITMAP_TYPE_ICO) else: return wx.Icon("gfx/myapp.ico", wx.BITMAP_TYPE_ICO)
好吧,好吧...我安装了py2exe,我认为这是一个错误。在py2exe_util.c中,它们应该将rt_icon_id
初始化为1而不是0。现在,无法使用LoadIcon / LoadImage加载第一个图标的第一种格式。
如果这不是已知问题,我会通知开发人员。
同时,一种解决方法是在setup.py中两次包含相同的图标:
'icon_resources': [(1, 'my_icon.ico'), (2, 'my_icon.ico')]
我们可以加载第二个,而Windows将使用第一个作为外壳图标。但请记住要使用非零ID。 :)
@efotinis:你是对的。
这是一种解决方法,直到py2exe得到修复并且我们不想两次包含相同的图标:
hicon = win32gui.CreateIconFromResource(win32api.LoadResource(None, win32con.RT_ICON, 1), True)
请注意,1不是我们在setup.py中为图标提供的ID(即图标组ID),而是py2exe自动为每个图标组中的每个图标分配的资源ID。至少我是这样理解的。
如果要创建具有指定大小的图标(因为CreateIconFromResource使用系统默认的图标大小),则需要使用CreateIconFromResourceEx,该方法无法通过PyWin32使用:
icon_res = win32api.LoadResource(None, win32con.RT_ICON, 1) hicon = ctypes.windll.user32.CreateIconFromResourceEx(icon_res, len(icon_res), True, 0x00030000, 16, 16, win32con.LR_DEFAULTCOLOR)