This will address all issues with alpha loss on Windows XP style icons
(32bppARGP format) with regard to Bitmap.FromHicon and
Graphics.DrawImage.
There appears to be a bug in GDI+ with regard to getting the bitmap
image of any icon which results in an image being use that is not the
correct pixel format. This seems to occur with any GDI+ function that
internally has to a convert an image to a bitmap. The solution below
addresses the issue by using GetIconInfo, creating a bitmap which will
contain the correct bits but wrong format, then copy the bitmap bits
to a new bitmap with the correctly format.
The resulting bitmap will work with DrawImage to the screen or to a
Bitmap Graphics object. I haven't tested this with ImageList, it is
likely that this will solve problems with that as well since adding an
icon to an image list requires the flawed internal conversion to a
bitmap.
Below is the C# code that can be added to a class for a simple static
method to return a good bitmap from an icon. I only performs the
special steps if the icon is 32 bit, otherwise it using Bitmap.HIcon
which appears to work for other format.
public struct ICONINFO
{
public int fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
public struct BITMAP
{
public int bmType;
public int bmWidth;
public int bmHeight;
public int bmWidthBytes;
public short bmPlanes;
public short bmBitsPixel;
public int bmBits;
}
[DllImport("gdi32")]
public static extern int GetObject(IntPtr hObject, int nCount, out
BITMAP bitmap);
[DllImport("gdi32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr DeleteObject(IntPtr hObject);
public static Bitmap AlphaBitmapFromIcon(Icon icon)
{
// (Overcome Flaw #1: GDI+ Bitmap.FromHICON mangles the alpha so the
.NET Bitmap.FromHicon will not work)
// Call Win32 to get icon info with contains the icon bitmap, return
null if invalid
ICONINFO iconInfo;
if (GetIconInfo(icon.Handle, out iconInfo)==0)
return null;
// Get BITMAP struct from icon bitmap
BITMAP bitmapData;
GetObject(iconInfo.hbmColor, Marshal.SizeOf(typeof(Win32.BITMAP)),
out bitmapData);
// If not a 32bpp then ok to use Bitmap.FromHicon
if (bitmapData.bmBitsPixel!=32)
{
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
return Bitmap.FromHicon(icon.Handle);
}
// Create .NET wrapped bitmap from ICONINFO bitmap
Bitmap wrapBitmap=Bitmap.FromHbitmap(iconInfo.hbmColor);
// (Overcome Flaw #2: Bitmap.FromHbitmap creates a bitmap with the
correct bits but wrong pixel format)
// Copy bit form flawed bitmap to new bitmap with correct format
BitmapData bmData=wrapBitmap.LockBits(new Rectangle(0,0,
wrapBitmap.Width, wrapBitmap.Height),
ImageLockMode.ReadOnly, wrapBitmap.PixelFormat);
Bitmap dstBitmap=new Bitmap(bmData.Width, bmData.Height,
bmData.Stride, PixelFormat.Format32bppArgb, bmData.Scan0);
wrapBitmap.UnlockBits(bmData);
// Caller must dispose of bitmaps returned in ICONINFO from
GetIconInfo call
DeleteObject(iconInfo.hbmColor);
DeleteObject(iconInfo.hbmMask);
// Return corrected bitmap
return dstBitmap;
}
1. GetIconInfo was missing. I modified a variation I found online.
[DllImport("user32")]
public static extern int GetIconInfo(IntPtr hIcon, ref ICONINFO
piconinfo);
2. To avoid creating an Icon that may corrupt the processed image, I
changed the input parameter from an Icon to an IntPtr. You're calling
for an icon, when all you need is its handler: same as the output made
by "ExtractIcon" (shell32.dll function). Rather than create an icon
first, create a handler from a source Bitmap or icon handler.
Changed lines...
a. New function call: public static Bitmap AlphaBitmapFromIcon(IntPtr
iconHandle)
b. Change all the "icon.Handle" to "iconHandle"
*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Michael Adams <cwolf...@yahoo.com> wrote in message news:<#85MMNsc...@TK2MSFTNGP10.phx.gbl>...
(scroll to the bottom; I threw it with the "other" programs)
Anyhow, as you will see, I have your code "borged" in there to try to
avoid the bug, but to no avail. No doubt the Icon-Bitmap bug is related.