Open Metallicow opened 4 years ago
Reference SampleApp.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
https://stackoverflow.com/questions/23263599/how-to-extract-128x128-icon-bitmap-data-from-exe-in-python
How to get biggest Icon from *.exe since wx.IconLocation seems to be limited to 16 and 32 sizes.
"""
# python Imports.
from __future__ import unicode_literals
import ctypes
import ctypes.util
# pywin32 Imports.
import win32con
import win32api
# import win32gui
USER32 = ctypes.windll.user32
KERNEL32 = ctypes.windll.kernel32
def GetWindowsExeIcon(path):
"""
Get a *.exe icon.
:return: HICON
"""
# memcpy is used to copy data from resource storage to our buffer.
libc = ctypes.CDLL(ctypes.util.find_library('c'))
libc.memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t]
libc.memcpy.restype = ctypes.c_char_p
# Patch FindResourceW, ctypes.windll.kernel32.SizeofResource
FindResourceW = KERNEL32.FindResourceW
FindResourceW.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
FindResourceW.restype = ctypes.c_void_p
SizeofResource = KERNEL32.SizeofResource
SizeofResource.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
SizeofResource.restype = ctypes.c_size_t
# Using LoadLibrary (rather than CreateFile) is required otherwise
# LoadResource, FindResource and others will fail.
hLib = win32api.LoadLibraryEx(path, 0, 2)
# Get the icon groups, default is the first group.
iconGroups = win32api.EnumResourceNames(hLib, win32con.RT_GROUP_ICON)
groupName = iconGroups[0]
print(groupName)
hRes = win32api.LoadResource(hLib, win32con.RT_GROUP_ICON, groupName)
mem_icon_dir = KERNEL32.LockResource(hRes)
# We want 32 bit color icons, not 16 or 256 color.
# Common icon sizes...
# iconSizes = (16, 24, 32, 48, 64, 96, 128, 256, 512, 1024)
iconSizes = (1024,) # Hopefully return the biggest icon....
for iconSize in iconSizes:
iconName = USER32.LookupIconIdFromDirectoryEx(mem_icon_dir, True, iconSize, iconSize, 0x00000000);
hResourceInfo = FindResourceW(hLib, iconName, win32con.RT_ICON)
size = KERNEL32.SizeofResource(hLib, hResourceInfo)
rec = win32api.LoadResource(hLib, win32con.RT_ICON, iconName)
mem_icon = KERNEL32.LockResource(rec)
# Get and return the icon data.
binary_data = (ctypes.c_ubyte * size)()
libc.memcpy(binary_data, mem_icon, size)
hIcon = USER32.CreateIconFromResourceEx(binary_data, size, True, 0x00030000, 0, 0, 0x00000000)
print('hIcon', hIcon)
## info = win32gui.GetIconInfo(hIcon)
## print('info', info)
## bminfo = win32gui.GetObject(info[4])
## print('bminfo', bminfo)
return hIcon
if __name__ == '__main__':
import sys
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString,
pos=wx.DefaultPosition, size=wx.DefaultSize,
style=wx.DEFAULT_FRAME_STYLE, name='frame'):
wx.Frame.__init__(self, parent, id, title, pos, size, style, name)
global gMainWin
gMainWin = self
wxVER = 'wxPython %s' % wx.version()
pyVER = 'python %d.%d.%d.%s' % sys.version_info[0:4]
versionInfos = '%s %s' % (wxVER, pyVER)
self.CreateStatusBar().SetStatusText(versionInfos)
# path = r'C:\Program Files\Internet Explorer\iexplore.exe'
path = r'C:\Program Files\Mozilla Firefox\firefox.exe'
hIcon = GetWindowsExeIcon(path)
icon = wx.Icon()
icon.CreateFromHICON(hIcon)
print(icon.Width)
bmp = wx.Bitmap()
bmp.CopyFromIcon(icon)
print(bmp.GetSize())
bmp = bmp.ConvertToImage().Rescale(128, 128).ConvertToBitmap()
print(bmp.GetSize())
sb = wx.StaticBitmap(self, -1, bmp)
self.SetIcon(icon)
self.Bind(wx.EVT_CLOSE, self.OnDestroy)
def OnDestroy(self, event):
self.Destroy()
app = wx.App(0)
frame = MyFrame(None)
frame.Show()
app.MainLoop()
Description of the problem: wx.Icon only has so many overloads.
Basically I need something like this...
The Problem If a wx.IconLocation is feed to a wx.Icon, then the largest size returned is 32x32 usually. By using pywin32 I have worked around this, but IconLocation should work like desired size when requested.
As far as it seems 32x32 is the biggest icon extracted from... Example:
OBVIOUSLY the icon in the *.exe has sizes to accommodate like 256. I think 512-1024 is highest sizes used sometimes. Anyhow... I need the highest/best resolution in some cases. Would prefer to not use extra pywin32 code I've wrote, but to have it built in. @RobinD42 Is this possible as a overload?....