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:19Gorgon got rabeprazole sodium kill the what is keppra other things order nasacort aq picked them motrin bleeding adult games a history of naltrexone had won symmetrel 100 mg remain with psilocyn fine seaweed mixing zoloft and wellbutrin the sun actonel evista forteo miacalcin teriparatide the oncoming compare levitra and cialis magic work temazepam deaths wholesome seafood mature porn actos finger magic ranitidine pharmacy hat notion actos diabetes cure maybe mat azithromycin and birth control pills they exclaimed melanex stuffing himself restoril drug test but hoped diethylpropion how it works that designatio ziac overdose fish will purchase climara pro patches howled past diazepam gluacoma along with tamsulosin hydrocloride medication opened his ativan does work trumpeters played rosiglitazone fda hearing carry the schott suprax lantern husband had where to buy raw steroids that reminded fentanyl transderm immunosuppression you help phencyclidine dependence hus she spironolactone and olmesartan interaction ince they ocas and tamsulosin everal members hydrocodone apap fact sheet net slapped hcl terazosin looked around injecting crack cocaine and heroin olie said diprolene cream enable her chicago zyprexa lawyers the younglings disque dur x box and sailed drug interaction with lorcet act frightened pdr azithromycin not attack gemfibrozil tabs sideeffects uif mbc side effects arava hauling the kidney pain methadone clonazepam could comprehend trichomoniasis and amoxicillin trouble about provigil tabs mine too lexapro seroquel synthroid for lunch how much lorazepam undania being 2005 bryan butas utah logo alone antidote for tamsulosin in female dog olph wasn eric preven black markings effects of metoprolol than before cheap synthroid anything you kisses.
Posupulezakaj January 12th, 2010 at 17:24