The GDI+ Bitmap class has a nice constructor that takes in a HICON. The problem is that it doesn’t preserve alpha values– icons such as the Firefox icon that have semi-transparent shadows show up with completely black shadows. This code will get you the icon with proper transparency:

Gdiplus::Bitmap *WindowsSystem::GetIconPixelData(HICON hIcon)
{
	ICONINFO iconInfo;
	GetIconInfo(hIcon, &iconInfo);

	BITMAP iconBmp;
	GetObject(iconInfo.hbmColor, sizeof(BITMAP),&iconBmp);
	
	Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(iconBmp.bmWidth,iconBmp.bmHeight,PixelFormat32bppARGB);

	bool hasAlpha = false;
	{
		// We have to read the raw pixels of the bitmap to get proper transparency information
		// (not sure why, all we're doing is copying one bitmap into another)

		Gdiplus::Bitmap colorBitmap(iconInfo.hbmColor, NULL);
		Gdiplus::BitmapData bmpData;
		Gdiplus::Rect bmBounds(0, 0, colorBitmap.GetWidth(), colorBitmap.GetHeight());

		colorBitmap.LockBits(&bmBounds, Gdiplus::ImageLockModeRead, colorBitmap.GetPixelFormat(), &bmpData);
		for (int y = 0; y < colorBitmap.GetHeight(); y++)
		{
			byte *pixelBytes = (byte*)bmpData.Scan0 + y*bmpData.Stride;

			for (int x = 0; x SetPixel(x, y, Gdiplus::Color(*pixel));
				hasAlpha = hasAlpha || (pixelBytes[3] > 0 && pixelBytes[3] < 255);
			}
		}
		colorBitmap.UnlockBits(&bmpData);
	}

	if (!hasAlpha)
	{
		// If there's no alpha transparency information, we need to use the mask
		// to turn back on visible pixels

		Gdiplus::Bitmap maskBitmap(iconInfo.hbmMask,NULL);
		Gdiplus::Color cMask, cBitmap;
		for (int y = 0; y < maskBitmap.GetHeight(); y++)
		{
			for (int x = 0; x GetPixel(x, y, &cBitmap); 
					cBitmap.SetValue(cBitmap.GetValue() | 0xFF000000); // turn alpha to opaque (i.e. 0xFF)
					bitmap->SetPixel(x, y, cBitmap);
				}
			}
		}

	}

	return bitmap ;

}
Follow

Get every new post delivered to your Inbox.