HICON to QPixmap
I found it necessary to convert an Windows HICON to a QPixmap so I could actually use it with Qt. Qt is great but lacks this for some reason. Here you go:
#define WIN32_MEAN_AND_LEAN //necessary to avoid compiler errors
#include <windows.h>
namespace Win32
{
static
QPixmap pixmap( const HICON &icon, bool alpha = true )
{
try {
ICONINFO info;
bool const b = ::GetIconInfo( icon, &info );
QPixmap pixmap = alpha
? fancyPants( info )
: QPixmap::fromWinHBITMAP( info.hbmColor, QPixmap::NoAlpha );
// gah Win32 is annoying!
::DeleteObject( info.hbmColor );
::DeleteObject( info.hbmMask );
::DestroyIcon( icon );
return pixmap;
}
catch (...)
{
return QPixmap();
}
}
QPixmap
associatedIcon( const QString &path )
{
// performance tuned using:
//http://www.codeguru.com/Cpp/COM-Tech/shell/article.php/c4511/
SHFILEINFO file_info;
::SHGetFileInfo(
(wchar_t*)path.utf16(),
FILE_ATTRIBUTE_NORMAL,
&file_info,
sizeof(SHFILEINFO),
SHGFI_USEFILEATTRIBUTES | SHGFI_ICON | SHGFI_LARGEICON );
return pixmap( file_info.hIcon );
}
static QPixmap
fancyPants( ICONINFO const &icon_info )
{
int result;
HBITMAP h_bitmap = icon_info.hbmColor;
/// adapted from qpixmap_win.cpp so we can have a _non_ premultiplied alpha
/// conversion and also apply the icon mask to bitmaps with no alpha channel
/// remaining comments are Trolltech originals
////// get dimensions
BITMAP bitmap;
memset( &bitmap, 0, sizeof(BITMAP) );
result = GetObjectW( h_bitmap, sizeof(BITMAP), &bitmap );
if (!result)
return QPixmap();
int const w = bitmap.bmWidth;
int const h = bitmap.bmHeight;
//////
BITMAPINFO info;
memset( &info, 0, sizeof(info) );
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biWidth = w;
info.bmiHeader.biHeight = -h;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = w * h * 4;
// Get bitmap bits
uchar *data = (uchar*)qMalloc( info.bmiHeader.biSizeImage );
result = GetDIBits( qt_win_display_dc(), h_bitmap, 0, h, data, &info, DIB_RGB_COLORS );
QPixmap p;
if (result) {
// test for a completely invisible image
// we need to do this because there is apparently no way to determine
// if an icon's bitmaps have alpha channels or not. If they don't the
// alpha bits are set to 0 by default and the icon becomes invisible
// so we do this long check. I've investigated everything, the bitmaps
// don't seem to carry the BITMAPV4HEADER as they should, that would tell
// us what we want to know if it was there, but apparently MS are SHIT SHIT
const int N = info.bmiHeader.biSizeImage;
int x;
for (x = 3; x < N; x += 4)
if (data[x] != 0)
break;
if (x < N)
p = QPixmap::fromImage( QImage( data, w, h, QImage::Format_ARGB32 ) );
else {
QImage image( data, w, h, QImage::Format_RGB32 );
QImage mask = image.createHeuristicMask();
mask.invertPixels(); //prolly efficient as is a 1bpp bitmap really
image.setAlphaChannel( mask );
p = QPixmap::fromImage( image );
}
// force the pixmap to make a deep copy of the image data
// otherwise `delete data` will corrupt the pixmap
QPixmap copy = p;
copy.detach();
p = copy;
}
qFree( data );
return p;
}
}
That took me a while to figure out. So enjoy the fruits of my labour!

Hi,
Thanks for the post! This method works great except for one thing: for old-style icons with 1-bpp transparency, the black color goes completely transparent, giving the icons a weird “cropped” look.
For example, in Windows XP, the icon for .BAT files has a black border on the bottom and right. This border goes completely transparent at some point during the conversion to QPixmap. This is more noticeable for me, because I am using SHGFI_SMALLICON, so a sizeable chunk of some icons just goes “missing”!
Any idea how to fix it? Thanks!
Daniel February 13th, 2007 at 23:47Diid you try both pixmap( foo, true ) and pixmap( foo, false ), as one handles transparency and the other doesn’t. I can’t remember exactly all the details as I wrote this a while ago. I recall I had to add the bool as there was no way to detect this I could determine.
Max Howell February 14th, 2007 at 11:02Yeah, I tried both alpha settings, plus messed around a bit without much success. Luckily, it seems Qt is now doing the hard work for us in Qt 4.3. Check out the new convertHIconToPixmap() function in src\gui\image\qpixmap_win.cpp from the latest Qt snapshot. It includes all the necessary craziness to detect alpha and whatnot. Not sure when Qt 4.3 will be out, but you can just copy+paste that function and use it in an older Qt 4 program.
Daniel February 15th, 2007 at 23:40[...] Re: Retrieving a file’s icon yep forgot that. i prefer this solution: http://www.methylblue.com/blog/hicon-to-qpixmap/ [...]
Retrieving a file's icon - Qt Centre Forum October 30th, 2007 at 8:19