- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hello,
I am struggeling with embedding icon inside a button added to Ribbon. The code works as inteded until I try to set the button icon. Here's what did to achieve my Goal:
1. Created working code, which creates a button in Asseble Tab, in "RF AUTO" Panel.
Now I want the button to include the icon inside of it:
1. I've created "Resources folder", then put icons ("icon32.ico" and "icon16.ico" files in 16x16 and 32x32 px resolution) and set the "built action property" as "Embedded Resource" in their properties in Visual Studio.
2. Used the code from Mode the machine: https://modthemachine.typepad.com/my_weblog/2012/02/bitmaps-without-vb6-icontoipicture.html to create IPictureDisp needed for button images.
3. Then created IPictureDisp objects using GetIconfromResource method and passed them to "AddButtonDefinition" method:
//Indicating embeded icons
string icon16ResourceName = "InventorAddIn4.Resources.tank16";
string icon32ResourceName = "InventorAddIn4.Resources.tank32";
//Using PictureDisp converter
stdole.IPictureDisp smallic = PictureDispConverter.ToIPictureDisp(GetIconFromResource(icon16ResourceName));
stdole.IPictureDisp bigicon = PictureDispConverter.ToIPictureDisp(GetIconFromResource(icon32ResourceName));
// Create the button definition and include small and big icons
assembleButton = inventorApp.CommandManager.ControlDefinitions.AddButtonDefinition(
"Assemble",
"InventorAddIn.SimpleAssembleAddIn.AssembleButton",
CommandTypesEnum.kFileOperationsCmdType,
"814846a1-b3bd-4636-9196-12c47fb59596", "Assemble components", "Assemble components in assembly",
smallic,
bigicon
);
So the complete Code looks like:
using System;
using System.Runtime.InteropServices;
using Inventor;
using Microsoft.Win32;
using System.IO;
using stdole;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
namespace InventorAddIn5
{
/// <summary>
/// This is the primary AddIn Server class that implements the ApplicationAddInServer interface
/// that all Inventor AddIns are required to implement. The communication between Inventor and
/// the AddIn is via the methods on this interface.
/// </summary>
[GuidAttribute("814846a1-b3bd-4636-9196-12c47fb59596")]
public class StandardAddInServer : Inventor.ApplicationAddInServer
{
// Inventor application object.
private Inventor.Application inventorApp;
private ButtonDefinition assembleButton;
private UserInterfaceEvents uiEvents;
public StandardAddInServer()
{
}
#region ApplicationAddInServer Members
public void Activate(Inventor.ApplicationAddInSite addInSiteObject, bool firstTime)
{
inventorApp = addInSiteObject.Application;
uiEvents = inventorApp.UserInterfaceManager.UserInterfaceEvents;
//Indicating embeded icons
string icon16ResourceName = "InventorAddIn4.Resources.tank16";
string icon32ResourceName = "InventorAddIn4.Resources.tank32";
//Using PictureDisp converter
stdole.IPictureDisp smallic = PictureDispConverter.ToIPictureDisp(GetIconFromResource(icon16ResourceName));
stdole.IPictureDisp bigicon = PictureDispConverter.ToIPictureDisp(GetIconFromResource(icon32ResourceName));
// Create the button definition and include small and big icons
assembleButton = inventorApp.CommandManager.ControlDefinitions.AddButtonDefinition(
"Assemble",
"InventorAddIn.SimpleAssembleAddIn.AssembleButton",
CommandTypesEnum.kFileOperationsCmdType,
"814846a1-b3bd-4636-9196-12c47fb59596", "Assemble components", "Assemble components in assembly",
smallic,
bigicon
);
//assembleButton.DisplayName = "Assemble components";
//assembleButton.Description = "Assemble components in assembly";
//assembleButton.TooltipText = "Assemble components";
// Attach the button click event
//assembleButton.LargeIcon = "xx";
assembleButton.OnExecute += AssembleButton_OnExecute;
// Add the button to the ribbon
if (firstTime)
{
RibbonTab assembleTab = inventorApp.UserInterfaceManager.Ribbons["Assembly"].RibbonTabs["id_TabAssemble"];
RibbonPanel panel = assembleTab.RibbonPanels.Add("RF AUTO", "InventorAddIn.SimpleAssembleAddIn.AssemblePanel", "814846a1-b3bd-4636-9196-12c47fb59596");
panel.CommandControls.AddButton(assembleButton, true, true);
}
}
public Icon GetIconFromResource(string resourceName)
{
Assembly assembly = Assembly.GetExecutingAssembly();
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
return new Icon(stream);
}
}
public void Deactivate()
{
// This method is called by Inventor when the AddIn is unloaded.
// The AddIn will be unloaded either manually by the user or
// when the Inventor session is terminated
// TODO: Add ApplicationAddInServer.Deactivate implementation
// Release objects.
assembleButton.Delete();
System.Runtime.InteropServices.Marshal.ReleaseComObject(uiEvents);
uiEvents = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(inventorApp);
inventorApp = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
private void AssembleButton_OnExecute(NameValueMap context)
{
MessageBox.Show("Assemble button clicked! 08_18");
// Implement your assembling logic here
}
public void ExecuteCommand(int commandID)
{
// Note:this method is now obsolete, you should use the
// ControlDefinition functionality for implementing commands.
}
public object Automation
{
// This property is provided to allow the AddIn to expose an API
// of its own to other programs. Typically, this would be done by
// implementing the AddIn's API interface in a class and returning
// that class object through this property.
get
{
// TODO: Add ApplicationAddInServer.Automation getter implementation
return null;
}
}
#endregion
}
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);
}
}
}
Have no idea where did I made a mistake. I feel helpless. The addin is loaded/deleted after code adaptation for displaying button icon. Could you please indicate the required changes ?
Kind Regards,
Jaromir
Solved! Go to Solution.