我在内存中有一个图标(RGB或我希望通过PIL / Pillow的任何格式)我想和它一起使用
win32gui.Shell_NotifyIcon
需要HICON
。
如何将RGB像素转换为HICON?
或者,即使这很浪费,我甚至不介意通过临时文件进行往返并使用win32gui.LoadImage
重新加载它,如下所示:
from PIL import Image
#create example image with empty pixels:
img = Image.frombuffer("RGB", (32, 32), "\0"*32*32*3, "raw", "RGB", 0, 1)
img = img.convert("P")
img = img.resize((64, 64), Image.ANTIALIAS)
img.save("C:\\temp.ico", format="bmp")
import win32gui, win32api, win32con
flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
win32gui.LoadImage(None, "C:\\temp.ico", win32con.IMAGE_ICON, 0, 0, flags)
但这失败了:pywintypes.error: (0, 'LoadImage', 'No error message available')
我找不到可以写入的图片格式,然后可以LoadImage
模式在IMAGE_ICON
模式下正确读回和使用。似乎LoadImage
仅支持该模式下的ICO
个文件:我可以将PNG
或BMP
数据读回IMAGE_BITMAP
,但无法使用生成的句柄按Shell_NotifyIcon
。
有没有办法将IMAGE
转换为HICON
? (在记忆中)
答案 0 :(得分:1)
我不知道我是如何错过的,但是有一个名为CreateIcon的函数将像素数据作为输入,虽然pywin32的win32gui中缺少这个函数,但是有一个{{}相反,这也是一样好。
因此代码变得简单(仍然使用临时文件):
img = win32gui.LoadImage(None, "C:\\tmp.bmp", win32con.IMAGE_BITMAP, 0, 0, flags)
pyiconinfo = (True, 0, 0, img, img)
hicon = win32gui.CreateIconIndirect(pyiconinfo)
为了在不使用临时文件的情况下将PIL图像中的RGB像素转换为位图,我使用了这个代码(是的,这样做很慢,但它相对简单易读,而且在这种情况下我真的不太关心性能):
def img_to_bitmap(image, pixel_value):
hdc = win32gui.CreateCompatibleDC(0)
dc = win32gui.GetDC(0)
hbm = win32gui.CreateCompatibleBitmap(dc, size, size)
hbm_save = win32gui.SelectObject(hdc, hbm)
for x in range(size):
for y in range(size):
pixel = image.getpixel((x, y))
v = pixel_value(pixel)
win32gui.SetPixelV(hdc, x, y, v)
win32gui.SelectObject(hdc, hbm_save)
win32gui.ReleaseDC(self.hwnd, hdc)
win32gui.ReleaseDC(self.hwnd, dc)
return hbm
对于那些关心性能的人来说,更好的解决方案可能涉及CreateIconIndirect或CreateDIBitmap
现在可以在SetDIBits的set_icon_from_data
方法中找到更完整的代码,它可以处理将Alpha通道拆分为自己的位图,这样我们也可以正确显示透明图像。