I was in the process of adding this functionality in order to make a pull request, but sadly there were some limitations, and I don't know enough about ctypes to use it effectively.
So far, I imagine it working like this: It would support PyQt5 and PySide2. There can be a simple flag that can be passed useQtResource, which can flag to use a Qt resource instead.
Now, awesomely enough, Qt comes with its own function toHICON. Great, right? Yes, but unfortunately, for whoever knows what reason, PySide2 (the official Qt Python bindings supported by Nokia) doesn't make QtWin available, whereas PyQt does! If the user is using PyQt, you could probably still make use of the toHICON function.
--
P.S. for sake of completeness, here's a toHICON code example.
Please note that if you choose to use the toHICON function for PyQt, you will have to include an additional flag useQtapi='pyside2' (or pyqt5). Why? Because the lovely qtpy (qtpy is a import library which allows you to abstract away the differences between API's, so you don't have to write or test for multiple APIs, thus, we wouldn't have to specify which API to use) also decided not to include QtWin! Seriously? Why's everybody forgetting to include important modules in their official distributions?
As for PySide2, as are the cirucmstances, I've found a way to get the raw image data from the resources. QResource(':/resource.ico').data().tobytes() will get you the raw image data represented as a Python string. Using this, I managed to cobble together a ctypes interface to convert it into a HICON using CreateIconFromResourceEx. The code looks like the following:
Looks lovely right? It works, but ... Yeah. It only works on PNG images, not on ICO images. :/ Frustrating. After several searching and API lookups, I found this piece of C code for ICO files.
I managed to Pythonize it, but, I should warn you, iconData + offset isn't actually valid, because you cant concatenate a bytes and an int data type. I had to use offset.to_bytes(len(offset), byteorder=sys.byteorder). Well, this passed the test... No Exceptions, BUT, HICON is always 0. Anyways, no matter what I try to do, I can't get this to work with an ICO file. Yeah, I could just write the file to the disk and read it again, but that's just UGLY.
CreateIconFromResourceEx = windll.user32.CreateIconFromResourceEx
LookupIconIdFromDirectoryEx = windll.user32.LookupIconIdFromDirectoryEx
size_x, size_y = 32, 32
LR_DEFAULTCOLOR = 0
imgData = QResource(icon_path).data().tobytes()
# works
offset = LookupIconIdFromDirectoryEx(iconData, 1, size_x, size_y, LR_DEFAULTCOLOR)
# "works", as in, won't return an exception, but it ALWAYS returns 0 (using ICO files)
hicon = CreateIconFromResourceEx(iconData + offset.to_bytes(len(offset), byteorder=sys.byteorder), 0, 1, 0x30000, size_x, size_y, LR_DEFAULTCOLOR)
So, this is where I'm at. I can do all this AS LONG as the image is a PNG, not ICO. Also, since I don't have PyQt5, I can't get toHICON, but that shouldn't be too hard for you to implement.
Any suggestions for fixing this? I'll be glad to throw a pull request if we can solve this. Please help me make this a reality.
-- Speaking of which, your code can only read an ICO image, not an PNG image. It would be nice if it supported PNG as well. As I tested PNG above, I know it works with the system as long as you can convert it to a HICON.
-- Also, I know absolutely nothing about C or ctypes, so please forgive any "obvious mistakes".
Probably the most important question: Why?
Because when you compile Python programs to an exe, and you use Qt, you will want to use the resource system (after all, you don't want raw files lying around when it can become part of the code).
I was in the process of adding this functionality in order to make a pull request, but sadly there were some limitations, and I don't know enough about ctypes to use it effectively.
So far, I imagine it working like this: It would support PyQt5 and PySide2. There can be a simple flag that can be passed
useQtResource
, which can flag to use a Qt resource instead.Now, awesomely enough, Qt comes with its own function
toHICON
. Great, right? Yes, but unfortunately, for whoever knows what reason, PySide2 (the official Qt Python bindings supported by Nokia) doesn't make QtWin available, whereas PyQt does! If the user is using PyQt, you could probably still make use of thetoHICON
function.-- P.S. for sake of completeness, here's a
toHICON
code example.Pretty simple isn't it?
--
Please note that if you choose to use the
toHICON
function for PyQt, you will have to include an additional flaguseQtapi='pyside2'
(or pyqt5). Why? Because the lovelyqtpy
(qtpy is a import library which allows you to abstract away the differences between API's, so you don't have to write or test for multiple APIs, thus, we wouldn't have to specify which API to use) also decided not to includeQtWin
! Seriously? Why's everybody forgetting to include important modules in their official distributions?As for PySide2, as are the cirucmstances, I've found a way to get the raw image data from the resources.
QResource(':/resource.ico').data().tobytes()
will get you the raw image data represented as a Python string. Using this, I managed to cobble together a ctypes interface to convert it into a HICON usingCreateIconFromResourceEx
. The code looks like the following:Looks lovely right? It works, but ... Yeah. It only works on PNG images, not on ICO images. :/ Frustrating. After several searching and API lookups, I found this piece of C code for ICO files.
I managed to Pythonize it, but, I should warn you,
iconData + offset
isn't actually valid, because you cant concatenate abytes
and anint
data type. I had to useoffset.to_bytes(len(offset), byteorder=sys.byteorder)
. Well, this passed the test... No Exceptions, BUT,HICON
is always 0. Anyways, no matter what I try to do, I can't get this to work with an ICO file. Yeah, I could just write the file to the disk and read it again, but that's just UGLY.So, this is where I'm at. I can do all this AS LONG as the image is a PNG, not ICO. Also, since I don't have PyQt5, I can't get
toHICON
, but that shouldn't be too hard for you to implement.Any suggestions for fixing this? I'll be glad to throw a pull request if we can solve this. Please help me make this a reality.
-- Speaking of which, your code can only read an ICO image, not an PNG image. It would be nice if it supported PNG as well. As I tested PNG above, I know it works with the system as long as you can convert it to a HICON.
-- Also, I know absolutely nothing about C or ctypes, so please forgive any "obvious mistakes".
Probably the most important question: Why?
Because when you compile Python programs to an exe, and you use Qt, you will want to use the resource system (after all, you don't want raw files lying around when it can become part of the code).