I wanted to make a file browser which has the correct file icons for each file type, instead of just getting them from the file name. This is a bad solution, since it has to call images from disc and may be wrong if the name is different. This method uses the Windows API to get the exact icon. Tested in Python 3.6 in Windows 10.
Let's test this with a few files and folders:
from win32com.shell import shell, shellcon
from PIL import Image, ImageTk
import win32api
import win32con
import win32ui
import win32gui
def get_icon(PATH, size):
SHGFI_ICON = 0x000000100
SHGFI_ICONLOCATION = 0x000001000
if size == "small":
SHIL_SIZE= 0x00001
elif size == "large":
SHIL_SIZE= 0x00002
else:
raise TypeError("Invalid argument for 'size'. Must be equal to 'small' or 'large'")
ret, info = shell.SHGetFileInfo(PATH, 0, SHGFI_ICONLOCATION | SHGFI_ICON | SHIL_SIZE)
hIcon, iIcon, dwAttr, name, typeName = info
ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
hbmp = win32ui.CreateBitmap()
hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_x)
hdc = hdc.CreateCompatibleDC()
hdc.SelectObject(hbmp)
hdc.DrawIcon((0, 0), hIcon)
win32gui.DestroyIcon(hIcon)
bmpinfo = hbmp.GetInfo()
bmpstr = hbmp.GetBitmapBits(True)
img = Image.frombuffer(
"RGBA",
(bmpinfo["bmWidth"], bmpinfo["bmHeight"]),
bmpstr, "raw", "BGRA", 0, 1
)
if size == "small":
img = img.resize((16, 16), Image.ANTIALIAS)
return img
Let's test this with a few files and folders:
The Documents folder. As you can see, it gets the two different image sizes.
The user's folder.
A standard folder.
It automatically gets the default application's icon. Here's VLC for an MP4 file.
Here's an example of an executable, Steam
It also works with removable media, like this SD card.
Finally, the drive with the OS installed.
I originally got the code from this SO post, but as you can see I have modified it a lot. It turns out that if the value of SHIL_SIZE is odd, then it gets the smaller image. If it's even, then it gets the larger size.
My version also returns a PIL image instead of writing to and deleting a temporary file, which uses more disc. It also returns a transparent background.
Comments
Post a Comment