wpfwannabe
wpfwannabe

Reputation: 14897

Show Win32 popup menu with PNG icons from resources

It's been a long time since I've had to deal with Win32 menus. I need to add some PNG icons to a Win32 context popup menu. Naturally, I want to preserve PNG transparency and all the per-pixel-alpha in the process. Is this possible?

I was thinking on using SetMenuItemBitmaps. Is that the way to go?

I imported my PNGs as "PNG" resources but I can't seem to load them neither with LoadBitmap nor with LoadImage. I found some suggestions about using Gdi+ but obviously I won't be drawing the menu - the system will.

There seems to be a way to get a HBITMAP from a Gdi+ Bitmap but it looks as if all the alpha is getting lost in the process. AFAIK, a HBITMAP can happily host alpha information.

Upvotes: 4

Views: 3176

Answers (2)

Tom Chakam
Tom Chakam

Reputation: 41

Perhaps you could use icon instead?

Here are my reasons for using icons instead of PNGs:

  1. The Win32 API has good support icons, and it relatively much easier to draw icons, since GDI+ is not required.
  2. Icons also support 8-bit transparency (just like PNGs).
  3. Icons can be any size in pixels (just like PNGs).
  4. Icons can easily be embedded in the executable as a resource.
  5. Icons can be edited via Visual Studio.

To load an icon from a resource or a file use:

LoadImage()

To draw the icon, use:

DrawIcon() or DrawIconEx()

Upvotes: 1

Ben
Ben

Reputation: 35663

You need GDI+ to load a PNG. Then you need to create a 32-bit alpha bitmap of the correct size, create a Graphics on the bitmap, and use DrawImage to copy the PNG to the bitmap. That gives you a bitmap with an alpha channel.

Something like this:

Image*  pimgSrc = Image::FromFile("MyIcon.png"L, FALSE);
Bitmap* pbmpImage = new Bitmap(
    iWidth, iHeight, 
    PixelFormat32bppARGB
);
Graphics* pgraphics = Graphics::FromImage(bmpImage))
{
    // This draws the PNG onto the bitmap, scaling it if necessary.
    // You may want to set the scaling quality 
    graphics->DrawImage(
        imageSrc,
        Rectangle(0,0, bmpImage.Width, bmpImage.Height),
        Rectangle(0,0, imgSrc.Width, imgSrc.Height),
        GraphicsUnitPixel
    );
}
// You can now get the HBITMAP from the Bitmap object and use it.
// Don't forget to delete the graphics, image and bitmap when done.

Upvotes: 3

Related Questions