如何用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', '在图像文件中找不到指定的资源类型。')
那么,加载图标的正确方法或语法是什么呢?
另外请注意,我没有使用任何图形用户界面工具包 - 只是通过PyWin32使用Windows API。
4 个回答
如果你在使用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,我觉得这可能是个bug。在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)