This project has moved. For the latest updates, please go here.

How to use a transparent bitmap for the shell context menu icon?

Feb 12, 2011 at 3:47 AM

Hi.

I am wondering how I can use a transparent bitmap for the shell context menu icon?

For example,

Take the sample bmp here:
http://msbuildshellex.codeplex.com/SourceControl/BrowseLatest
1.2\MSBuildShellExtension\menuicon.bmp
The following code displays the 16x16 icon as expected:
VvvSample\ContextMenu.cs constructor
using (Bitmap largeBitmap = new Bitmap(typeof(ContextMenu), "menuicon.bmp"))
{
bitmapMenuIcon = new Bitmap(largeBitmap, new Size(16, 16));
}
But it uses a white background instead of the expected transparency.
Any ideas?
Thank you! :)

Feb 27, 2011 at 11:24 AM
The following seems to work when using white as the transparent color:

bitmapMenuIcon = new Bitmap(typeof(ContextMenu), "menuicon.bmp");
bitmapMenuIcon.MakeTransparent(Color.White);

Thank you!
Mar 3, 2011 at 4:37 AM

Actually, MakeTransparent causes strange behavior.  :(

On Windows XP 32-bit and Windows XP 64-bit, it causes the white parts of the image to display blue for some reason.

On Windows 7 32-bit it is does not work as expected; the white background still appears.

On Windows 7 64-bit it works until you move the mouse over the icon, at which time the white background re-appears.

Any advice?

Thank you.

Mar 3, 2011 at 5:51 AM

Here are some links that may help.

http://www.ms-news.net/f2749/transparent-image-in-shell-extension-context-menu-4081247.html

http://www.ms-news.net/f3615/transparent-menu-bitmaps-2025832.html

I'm thinking that we have to call SetMenuInfo with the MNS_CHECKORBMP style on MENUINFO, specify the MIIM_BITMAP mask, and set the bitmap in hbmpItem of the MENUITEMINFO structure.

Mar 12, 2011 at 4:37 AM

I've uploaded patch #8719 that partially resolves this issue, but leaves the text misaligned.

 

Can anyone see what is wrong or missing?

 

Thank you!

Mar 14, 2011 at 1:24 AM

I've uploaded patch #8733 that replaces the previous patch.

This patch works as expected.

Thank you.

Feb 23, 2012 at 2:05 PM
Edited Feb 23, 2012 at 2:22 PM

In my code, rather than ovverriding the drawing process, I'm using this hack to get transparent bitmaps:  

private static IntPtr GetHbitmap(Bitmap bitmap)
{
    int width = 16;
    int height = 16;

    // On XP images are scaled to 12x12 pixels
    if (Environment.OSVersion.Version.Major < 6)
    {
        width = 12;
        height = 12;
    }

    using (var tmp = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format24bppRgb))
    using (var graphics = Graphics.FromImage(tmp))
    {
        graphics.InterpolationMode = InterpolationMode.Bicubic;
        graphics.Clear(SystemColors.Menu);
        graphics.DrawImage(bitmap, 0, 0, width, height);
	return tmp.GetHbitmap();
    }
}

//...

int IContextMenu.QueryContextMenu(
    IntPtr hMenu,
    uint iMenu,
    uint idCmdFirst,
    uint idCmdLast,
    uint uFlags)
{
    // ...
   
    var mii = new MENUITEMINFO();
   
    //...
   
    if (menuItem.Hbitmap != IntPtr.Zero)
    {
        if (Environment.OSVersion.Version.Major < 6)
        {
            mii.hbmpChecked = menuItem.Hbitmap;
            mii.hbmpUnchecked = menuItem.Hbitmap;
            mii.fMask |= MIIM.MIIM_CHECKMARKS;
        }
        else
        {
            mii.hbmpItem = menuItem.Hbitmap;
            mii.fMask |= MIIM.MIIM_BITMAP;
        }
    }
}

 

It seems to work fine (tested on XP x86 and Seven x64).
Transparency is not the best on XP when you move the mouse over the icon, but I think it's acceptable.