Ribbon button image with partial transparent pixels

Ribbon button image with partial transparent pixels

jholdawayUKBGN
Contributor Contributor
524 Views
2 Replies
Message 1 of 3

Ribbon button image with partial transparent pixels

jholdawayUKBGN
Contributor
Contributor

Hello,

 

I have seen all the examples of adding a button to the ribbon in Inventor.  I have to set the image using a the picture converter to get a stdole.IPictureDisp.  It works just fine except if my image has partially transparent pixels, the graphic is not correct.

 

Addin.InventorApplication.CommandManager.ControlDefinitions.AddButtonDefinition("my button",
				"myId",
				CommandTypesEnum.kQueryOnlyCmdType,
				Addin.ID,
				"tooltip",
				"tooltip,
				null,
				PictureDispConverter.ToIPictureDisp(Properties.Resources.ManMotion_32),
				ButtonDisplayEnum.kAlwaysDisplayText)


	public sealed class PictureDispConverter
    {
        [DllImport("OleAut32.dll",
            EntryPoint = "OleCreatePictureIndirect",
            ExactSpelling = true,
            PreserveSig = false)]
        private static extern stdole.IPictureDisp
            OleCreatePictureIndirect(
                [MarshalAs(UnmanagedType.AsAny)] object picdesc,
                ref Guid iid,
                [MarshalAs(UnmanagedType.Bool)] bool fOwn);

        static Guid iPictureDispGuid = typeof(stdole.IPictureDisp).GUID;

        private static class PICTDESC
        {
            //Picture Types
            public const short PICTYPE_UNINITIALIZED = -1;
            public const short PICTYPE_NONE = 0;
            public const short PICTYPE_BITMAP = 1;
            public const short PICTYPE_METAFILE = 2;
            public const short PICTYPE_ICON = 3;
            public const short PICTYPE_ENHMETAFILE = 4;

            [StructLayout(LayoutKind.Sequential)]
            public class Icon
            {
                internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Icon));
                internal int picType = PICTDESC.PICTYPE_ICON;
                internal IntPtr hicon = IntPtr.Zero;
                internal int unused1;
                internal int unused2;

                internal Icon(System.Drawing.Icon icon)
                {
                    this.hicon = icon.ToBitmap().GetHicon();
                }
            }

            [StructLayout(LayoutKind.Sequential)]
            public class Bitmap
            {
                internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Bitmap));
                internal int picType = PICTDESC.PICTYPE_BITMAP;
                internal IntPtr hbitmap = IntPtr.Zero;
                internal IntPtr hpal = IntPtr.Zero;
                internal int unused;

                internal Bitmap(System.Drawing.Bitmap bitmap)
                {
                    this.hbitmap = bitmap.GetHbitmap();
                }
            }
        }

        public static stdole.IPictureDisp ToIPictureDisp(System.Drawing.Icon icon)
        {
            PICTDESC.Icon pictIcon = new PICTDESC.Icon(icon);

            return OleCreatePictureIndirect(pictIcon, ref iPictureDispGuid, true);
        }

        public static stdole.IPictureDisp ToIPictureDisp(System.Drawing.Bitmap bmp)
        {
            PICTDESC.Bitmap pictBmp = new PICTDESC.Bitmap(bmp);

            return OleCreatePictureIndirect(pictBmp, ref iPictureDispGuid, true);
        }
    }

 

I have attached the sample png to see what I'm doing wrong.  Any help would be appreciated!. 

0 Likes
Accepted solutions (1)
525 Views
2 Replies
Replies (2)
Message 2 of 3

jholdawayUKBGN
Contributor
Contributor
Accepted solution

Here is the fix after playing around.  It seems you need to use an actual .ico file, and that PictureDispConverter needs to be updated with the following for the icon.

 

[StructLayout(LayoutKind.Sequential)]
            public class Icon
            {
                internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Icon));
                internal int picType = PICTDESC.PICTYPE_ICON;
                internal IntPtr hicon = IntPtr.Zero;
                internal int unused1;
                internal int unused2;

                internal Icon(System.Drawing.Icon icon)
                {
                    this.hicon = icon.Handle;
                }
            }
Message 3 of 3

MjDeck
Autodesk
Autodesk

Thanks @jholdawayUKBGN . That makes a big difference.

One note: it looks like the handle returned directly from the icon might not always be valid. This seems to depend on how the icon was created. I recommend replacing the line:

 

  this.hicon = icon.Handle;

 

 with this:

 

  System.Drawing.Icon newIcon = icon.Clone() as System.Drawing.Icon;
  this.hicon = newIcon.Handle;

 


Mike Deck
Software Developer
Autodesk, Inc.

0 Likes