Search code examples
pythonpyside

HICON/HBITMAP to QIcon/QPixmap/QImage/Anything with a Q in it


I'm trying to get 48x48 or 256x256 icons from files in Windows and have come across what seems like a dead-end. At the moment I have a HICON handle(since PySides QFileIconProvider only returns 32x32 icons) in python which I would like to show in a pyside window but functions like QPixmap.fromHICON/HBITMAP are not implemented and also seems to have been removed from the source since Qt 4.8(?). Also, I'm trying to avoid having to save the icon to a file.

So, is there any way to get a HICON or possibly any other things you can turn it into, to any kind of PySide object?

EDIT: I've been trying to simply rewrite the old function fromWinHBITMAP function in python but it isn't going great. I'm uncertain how I should translate the src line into python and I don't either have any idea how I change the value of the memory buffer returned by QImage.scanLine()

for (int y=0; y<h; ++y) {
            QRgb *dest = (QRgb *) image.scanLine(y);
            const QRgb *src = (const QRgb *) (data + y * bytes_per_line);
            for (int x=0; x<w; ++x) {
                dest[x] = src[x] | mask;
            }
        }

At the moment I create a PyCBITMAP from the HICON with the win32api and retrieves the list of bits.

for y in range(0, hIcon.height):
    dest = i.scanLine(y)
    src = bitmapbits[y*hIcon.widthBytes:(y*hIcon.widthBytes)+hIcon.widthBytes]

    for x in range(0, hIcon.width):
        dest[x] = bytes(ctypes.c_uint32(src[x] | 0))

This results in "ValueError: cannot modify size of memoryview object"

The source for the function be found here: http://www.qtcentre.org/threads/19188-Converting-from-HBitmap-to-a-QPixmap?p=94747#post94747


Solution

  • Fixed it!

    def iconToQImage(hIcon):
        hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
        hbmp = win32ui.CreateBitmap()
        hbmp.CreateCompatibleBitmap(hdc, hIcon.width, hIcon.height)
        hdc = hdc.CreateCompatibleDC()
        hdc.SelectObject(hbmp)
    
        win32gui.DrawIconEx(hdc.GetHandleOutput(), 0, 0, hIcon.hIcon, hIcon.width, hIcon.height, 0, None, 0x0003)
    
        bitmapbits = hbmp.GetBitmapBits(True)
        image = QtGui.QImage(bitmapbits, hIcon.width, hIcon.height, QtGui.QImage.Format_ARGB32_Premultiplied)
        return image