VB.net Addins button image not loading. Eventhough two programs are exactly identical in structure

VB.net Addins button image not loading. Eventhough two programs are exactly identical in structure

sanil_heartbeats
Contributor Contributor
1,174 Views
5 Replies
Message 1 of 6

VB.net Addins button image not loading. Eventhough two programs are exactly identical in structure

sanil_heartbeats
Contributor
Contributor

Product: Inventor Professional 2021 Everything updated till 21-06-2021

Windows 10 20H2 OS

 

I was trying to create TWO addins as per my office requirement.

 

AddPartQty2021

DrawnUpdate2021

 

The first one was to add a custom value to iproperty . I was successful with that and everything was fine. Now I started my second addin programming starting from scratch. Ie started using the VB.net development template. (ie PROGRAM-ID, GUID, ASSEMBLY GUID all are unique. ie different from each other.).

 

I wanted to initially complete the button loading and then later add the click event details. But, when I compiled the second addin, it loads successfully and displays the messagebox on click as per my program. except for the icon in the panel. The Addin name is shown, but not the icon image. I am adding the standard addin server file content below. Somebody, please help me find out know why the second addin icon doesn't show up.

 

sanilheartbeats_0-1624296433501.png

 

sanilheartbeats_1-1624296473199.png

 

Imports Inventor
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Namespace AddPartQty2021
    <ProgIdAttribute("AddPartQty2021.StandardAddInServer"), _
    GuidAttribute("24b9e07a-13f3-42c7-9aa8-82b2b965cb40")> _
    Public Class StandardAddInServer
        Implements Inventor.ApplicationAddInServer

        Private WithEvents m_uiEvents As UserInterfaceEvents
        'Private WithEvents m_sampleButton As ButtonDefinition

        Private WithEvents m_PrtQtyButton As ButtonDefinition
        Private WithEvents m_DrwPrtQtyButton As ButtonDefinition
        Private WithEvents AddPartQty As frmAddPartQty = Nothing

#Region "ApplicationAddInServer Members"

        ' This method is called by Inventor when it loads the AddIn. The AddInSiteObject provides access  
        ' to the Inventor Application object. The FirstTime flag indicates if the AddIn is loaded for
        ' the first time. However, with the introduction of the ribbon this argument is always true.
        Public Sub Activate(ByVal addInSiteObject As Inventor.ApplicationAddInSite, ByVal firstTime As Boolean) Implements Inventor.ApplicationAddInServer.Activate
            ' Initialize AddIn members.
            g_inventorApplication = addInSiteObject.Application

            ' Connect to the user-interface events to handle a ribbon reset.
            m_uiEvents = g_inventorApplication.UserInterfaceManager.UserInterfaceEvents

            ' TODO: Add button definitions.

            ' Sample to illustrate creating a button definition.
            'Dim largeIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.YourBigImage)
            'Dim smallIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.YourSmallImage)
            'Dim controlDefs As Inventor.ControlDefinitions = g_inventorApplication.CommandManager.ControlDefinitions
            'm_sampleButton = controlDefs.AddButtonDefinition("Command Name", "Internal Name", CommandTypesEnum.kShapeEditCmdType, AddInClientID)

            Try : m_PrtQtyButton = CreateButton("Part" & vbCr & "Quantity", "PrtQtyButton_ID", Inventor.CommandTypesEnum.kNonShapeEditCmdType,
                True, AddInClientID, "Add Part Quantity", "Add Part Quantity",
                "AddPartQty2021.AddPartQty2021_16x16.png", "AddPartQty2021.AddPartQty2021_32x32.png", Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) : Catch : End Try

            Try : m_DrwPrtQtyButton = CreateButton("Part" & vbCr & "Quantity", "DrwPrtQtyButton_ID", Inventor.CommandTypesEnum.kNonShapeEditCmdType,
                True, AddInClientID, "Add Part Quantity", "Add Part Quantity",
                "AddPartQty2021.AddPartQty2021_16x16.png", "AddPartQty2021.AddPartQty2021_32x32.png", Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) : Catch : End Try

            ' Add to the user interface, if it's the first time.
            If firstTime Then
                AddToUserInterface()
            End If
        End Sub

        ' 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.
        Public Sub Deactivate() Implements Inventor.ApplicationAddInServer.Deactivate

            ' TODO:  Add ApplicationAddInServer.Deactivate implementation

            ' Release objects.
            m_uiEvents = Nothing
            g_inventorApplication = Nothing

            System.GC.Collect()
            System.GC.WaitForPendingFinalizers()
        End Sub

        ' 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.
        Public ReadOnly Property Automation() As Object Implements Inventor.ApplicationAddInServer.Automation
            Get
                Return Nothing
            End Get
        End Property

        ' Note:this method is now obsolete, you should use the 
        ' ControlDefinition functionality for implementing commands.
        Public Sub ExecuteCommand(ByVal commandID As Integer) Implements Inventor.ApplicationAddInServer.ExecuteCommand
        End Sub

#End Region

#Region "Button Creation"
        Public Function CreateButton(ByRef strBtnDisplayName As String, ByRef strBtnInternalName As String, ByRef eBtnType As Inventor.CommandTypesEnum, ByRef blnAutoAddToGUI As Boolean, Optional ByRef strBtnClientId As String = "", Optional ByRef strBtnDescription As String = "", Optional ByRef strBtnToolTipText As String = "", Optional ByRef strBtnStdIcon As String = "", Optional ByRef strBtnLrgIcon As String = "", Optional ByRef eBtnDisplayEnum As Inventor.ButtonDisplayEnum = Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) As Inventor.ButtonDefinition

            Dim StandardIconIPictureDisp As Object = System.Type.Missing
            Dim LargeIconIPictureDisp As Object = System.Type.Missing
            Try
                If Not strBtnStdIcon Is Nothing Then
                    Dim StandardIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnStdIcon)
                    Dim StandardIconImage As System.Drawing.Image = New System.Drawing.Bitmap(StandardIconStream)

                    StandardIconIPictureDisp = ImageToPictureConverter.Convert(StandardIconImage)
                End If
            Catch ex As Exception
            End Try

            Try
                If Not strBtnLrgIcon Is Nothing Then
                    Dim LargeIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnLrgIcon)
                    Dim LargeIconImage As System.Drawing.Image = New System.Drawing.Bitmap(LargeIconStream)

                    LargeIconIPictureDisp = ImageToPictureConverter.Convert(LargeIconImage)
                End If
            Catch
            End Try

            CreateButton = g_inventorApplication.CommandManager.ControlDefinitions.AddButtonDefinition(strBtnDisplayName, strBtnInternalName, eBtnType, strBtnClientId, strBtnDescription, strBtnToolTipText, StandardIconIPictureDisp, LargeIconIPictureDisp, eBtnDisplayEnum)

            If CreateButton Is Nothing Then
                MsgBox("Failed to create Button:" & strBtnDisplayName)
            End If

        End Function
#End Region

#Region "ImageToPictureConverter"
        Public NotInheritable Class ImageToPictureConverter
            Inherits System.Windows.Forms.AxHost

            Private Sub New()
                MyBase.New(Nothing)
            End Sub

            Public Shared Function Convert(ByVal image As System.Drawing.Image) As stdole.IPictureDisp
                Return CType(System.Windows.Forms.AxHost.GetIPictureDispFromPicture(image), stdole.IPictureDisp)
            End Function

        End Class
#End Region

#Region "User interface definition"
        ' Sub where the user-interface creation is done.  This is called when
        ' the add-in loaded and also if the user interface is reset.
        Private Sub AddToUserInterface()
            ' This is where you'll add code to add buttons to the ribbon.

            '** Sample to illustrate creating a button on a new panel of the Tools tab of the Part ribbon.

            Dim userInterfaceMgr As UserInterfaceManager = g_inventorApplication.UserInterfaceManager
            '' userInterfaceMgr = g_inventorApplication.UserInterfaceManager

#Region "Add Button to Part Interface"

            '' Get the part ribbon.
            Dim invPrtRibbon As Ribbon = userInterfaceMgr.Ribbons.Item("Part")

            '' Get the "Tools" tab.
            'Dim toolsTab As RibbonTab = partRibbon.RibbonTabs.Item("id_TabTools")

            ' Check to see if the "Add-Ins" tab already exists in Part interface and create it if it doesn't.
            Dim invPrtAddInsTab As RibbonTab = Nothing
            Try
                invPrtAddInsTab = invPrtRibbon.RibbonTabs.Item("id_AddInsTab")
            Catch ex As Exception
            End Try

            If invPrtAddInsTab Is Nothing Then
                '  Create a new Add-Ins tab
                invPrtAddInsTab = invPrtRibbon.RibbonTabs.Add("Add-Ins", "id_AddInsTab", AddInClientID)
            End If

            '' Create a new panel.
            'Dim customPanel As RibbonPanel = toolsTab.RibbonPanels.Add("Sample", "MysSample", AddInClientID)

            ' Check to see if the "IP General Tools" panel already exists in Part interface and create it if it doesn't.
            Dim invPrtPanel As RibbonPanel = Nothing
            Try
                invPrtPanel = invPrtAddInsTab.RibbonPanels.Item("id_PanelD_General")
            Catch ex As Exception
            End Try

            If invPrtPanel Is Nothing Then
                ' Create a new panel.
                invPrtPanel = invPrtAddInsTab.RibbonPanels.Add("IP General Tools", "id_PanelD_General", AddInClientID)
            End If

            '' Add a button.
            'customPanel.CommandControls.AddButton(m_sampleButton)

            ' Add a button in Part interface.
            If Not m_PrtQtyButton Is Nothing Then
                invPrtPanel.CommandControls.AddButton(m_PrtQtyButton, True, True, ,)
            End If

#End Region

#Region "Add Button to Drawing Interface"

            '' Get the drawing ribbon
            Dim invDrwRibbon As Ribbon = userInterfaceMgr.Ribbons.Item("Drawing")

            ' Check to see if the "Add-Ins" tab already exists in Drawing interface and create it if it doesn't.
            Dim invDrwAddInsTab As RibbonTab = Nothing
            Try
                invDrwAddInsTab = invDrwRibbon.RibbonTabs.Item("id_AddInsTab")
            Catch ex As Exception
            End Try

            If invDrwAddInsTab Is Nothing Then
                '  Create a new Add-Ins tab
                invDrwAddInsTab = invDrwRibbon.RibbonTabs.Add("Add-Ins", "id_AddInsTab", AddInClientID)
            End If

            ' Check to see if the "IP General Tools" panel already exists in Drawing interface and create it if it doesn't.
            Dim invDrwPanel As RibbonPanel = Nothing
            Try
                invDrwPanel = invDrwAddInsTab.RibbonPanels.Item("id_PanelD_General")
            Catch ex As Exception
            End Try

            If invDrwPanel Is Nothing Then
                ' Create a new panel.
                invDrwPanel = invDrwAddInsTab.RibbonPanels.Add("IP General Tools", "id_PanelD_General", AddInClientID)
            End If

            ' Add a button in Drawing interface.
            If Not m_DrwPrtQtyButton Is Nothing Then
                invDrwPanel.CommandControls.AddButton(m_DrwPrtQtyButton, True, True, ,)
            End If
#End Region

        End Sub

        Private Sub m_uiEvents_OnResetRibbonInterface(Context As NameValueMap) Handles m_uiEvents.OnResetRibbonInterface
            ' The ribbon was reset, so add back the add-ins user-interface.
            AddToUserInterface()
        End Sub

        ' Sample handler for the button.
        'Private Sub m_sampleButton_OnExecute(Context As NameValueMap) Handles m_sampleButton.OnExecute
        '    MsgBox("Button was clicked.")
        'End Sub

#Region "Part Button Execute"

        Private Sub m_PartQtyButton_OnExecute(Context As NameValueMap) Handles m_PrtQtyButton.OnExecute

            Try
                AddPartQty = New frmAddPartQty
                'AddPartQty.Show(New WindowWrapper(g_inventorApplication.MainFrameHWND))
                Dim owner As New Windows.Forms.NativeWindow
                owner.AssignHandle(g_inventorApplication.MainFrameHWND)
                AddPartQty.Show(owner)

            Catch ex As Exception

                MsgBox(ex.Message & "on button click")

            End Try

        End Sub
#End Region

#Region "Drw Part Button Execute"

        Private Sub m_DrwPartQtyButton_OnExecute(Context As NameValueMap) Handles m_DrwPrtQtyButton.OnExecute

            Try
                AddPartQty = New frmAddPartQty
                'AddPartQty.Show(New WindowWrapper(g_inventorApplication.MainFrameHWND))
                Dim owner As New Windows.Forms.NativeWindow
                owner.AssignHandle(g_inventorApplication.MainFrameHWND)
                AddPartQty.Show(owner)

            Catch ex As Exception

                MsgBox(ex.Message & "on button click")

            End Try

        End Sub

#End Region

#End Region

    End Class
End Namespace


Public Module Globals
    ' Inventor application object.
    Public g_inventorApplication As Inventor.Application

#Region "Function to get the add-in client ID."
    ' This function uses reflection to get the GuidAttribute associated with the add-in.
    Public Function AddInClientID() As String
        Dim guid As String = ""
        Try
            Dim t As Type = GetType(AddPartQty2021.StandardAddInServer)
            Dim customAttributes() As Object = t.GetCustomAttributes(GetType(GuidAttribute), False)
            Dim guidAttribute As GuidAttribute = CType(customAttributes(0), GuidAttribute)
            guid = "{" + guidAttribute.Value.ToString() + "}"
        Catch
        End Try

        Return guid
    End Function
#End Region

#Region "hWnd Wrapper Class"
    ' This class is used to wrap a Win32 hWnd as a .Net IWind32Window class.
    ' This is primarily used for parenting a dialog to the Inventor window.
    '
    ' For example:
    ' myForm.Show(New WindowWrapper(g_inventorApplication.MainFrameHWND))
    '
    Public Class WindowWrapper
        Implements System.Windows.Forms.IWin32Window
        Public Sub New(ByVal handle As IntPtr)
            _hwnd = handle
        End Sub

        Public ReadOnly Property Handle() As IntPtr _
          Implements System.Windows.Forms.IWin32Window.Handle
            Get
                Return _hwnd
            End Get
        End Property

        Private _hwnd As IntPtr
    End Class
#End Region

#Region "Image Converter"
    ' Class used to convert bitmaps and icons from their .Net native types into
    ' an IPictureDisp object which is what the Inventor API requires. A typical
    ' usage is shown below where MyIcon is a bitmap or icon that's available
    ' as a resource of the project.
    '
    ' Dim smallIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.MyIcon)

    Public NotInheritable Class PictureDispConverter
        <DllImport("OleAut32.dll", EntryPoint:="OleCreatePictureIndirect", ExactSpelling:=True, PreserveSig:=False)> _
        Private Shared Function OleCreatePictureIndirect( _
            <MarshalAs(UnmanagedType.AsAny)> ByVal picdesc As Object, _
            ByRef iid As Guid, _
            <MarshalAs(UnmanagedType.Bool)> ByVal fOwn As Boolean) As stdole.IPictureDisp
        End Function

        Shared iPictureDispGuid As Guid = GetType(stdole.IPictureDisp).GUID

        Private NotInheritable Class PICTDESC
            Private Sub New()
            End Sub

            'Picture Types
            Public Const PICTYPE_BITMAP As Short = 1
            Public Const PICTYPE_ICON As Short = 3

            <StructLayout(LayoutKind.Sequential)> _
            Public Class Icon
                Friend cbSizeOfStruct As Integer = Marshal.SizeOf(GetType(PICTDESC.Icon))
                Friend picType As Integer = PICTDESC.PICTYPE_ICON
                Friend hicon As IntPtr = IntPtr.Zero
                Friend unused1 As Integer
                Friend unused2 As Integer

                Friend Sub New(ByVal icon As System.Drawing.Icon)
                    Me.hicon = icon.ToBitmap().GetHicon()
                End Sub
            End Class

            <StructLayout(LayoutKind.Sequential)> _
            Public Class Bitmap
                Friend cbSizeOfStruct As Integer = Marshal.SizeOf(GetType(PICTDESC.Bitmap))
                Friend picType As Integer = PICTDESC.PICTYPE_BITMAP
                Friend hbitmap As IntPtr = IntPtr.Zero
                Friend hpal As IntPtr = IntPtr.Zero
                Friend unused As Integer

                Friend Sub New(ByVal bitmap As System.Drawing.Bitmap)
                    Me.hbitmap = bitmap.GetHbitmap()
                End Sub
            End Class
        End Class

        Public Shared Function ToIPictureDisp(ByVal icon As System.Drawing.Icon) As stdole.IPictureDisp
            Dim pictIcon As New PICTDESC.Icon(icon)
            Return OleCreatePictureIndirect(pictIcon, iPictureDispGuid, True)
        End Function

        Public Shared Function ToIPictureDisp(ByVal bmp As System.Drawing.Bitmap) As stdole.IPictureDisp
            Dim pictBmp As New PICTDESC.Bitmap(bmp)
            Return OleCreatePictureIndirect(pictBmp, iPictureDispGuid, True)
        End Function
    End Class
#End Region

End Module

 

That was the 1st addin It works perfect. Some code updates are still to be done at the interface loading portion compared to the 2nd addin

 

Now below id the second addin

 

sanilheartbeats_2-1624296711864.png

 

Imports Inventor
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Namespace DrawnUpdate2021
    <ProgIdAttribute("DrawnUpdate2021.StandardAddInServer"), _
    GuidAttribute("5f21d961-a7cb-4d96-9f55-c0131d8571d4")> _
    Public Class StandardAddInServer
        Implements Inventor.ApplicationAddInServer

        Private WithEvents m_uiEvents As UserInterfaceEvents
        Private WithEvents m_DrawnPrtButton As ButtonDefinition
        Private WithEvents m_DrwDrawnPrtButton As ButtonDefinition
        'Private WithEvents m_sampleButton As ButtonDefinition

#Region "ApplicationAddInServer Members"

        ' This method is called by Inventor when it loads the AddIn. The AddInSiteObject provides access  
        ' to the Inventor Application object. The FirstTime flag indicates if the AddIn is loaded for
        ' the first time. However, with the introduction of the ribbon this argument is always true.
        Public Sub Activate(ByVal addInSiteObject As Inventor.ApplicationAddInSite, ByVal firstTime As Boolean) Implements Inventor.ApplicationAddInServer.Activate
            ' Initialize AddIn members.
            g_inventorApplication = addInSiteObject.Application

            ' Connect to the user-interface events to handle a ribbon reset.
            m_uiEvents = g_inventorApplication.UserInterfaceManager.UserInterfaceEvents

            ' TODO: Add button definitions.

            ' Sample to illustrate creating a button definition.
            'Dim largeIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.YourBigImage)
            'Dim smallIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.YourSmallImage)
            'Dim controlDefs As Inventor.ControlDefinitions = g_inventorApplication.CommandManager.ControlDefinitions
            'm_sampleButton = controlDefs.AddButtonDefinition("Command Name", "Internal Name", CommandTypesEnum.kShapeEditCmdType, AddInClientID)

            Try : m_DrawnPrtButton = CreateButton("Drawn" & vbCr & "Update", "DrawnPrtButton_ID", Inventor.CommandTypesEnum.kEditMaskCmdType,
                True, AddInClientID, "Update Drawn Name and Date", "Update Drawn Name and Date",
                "DrawnUpdate2021.DrawnUpdate2021_16x16.png", "DrawnUpdate2021.DrawnUpdate2021_32x32.png", Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) : Catch : End Try

            Try : m_DrwDrawnPrtButton = CreateButton("Drawn" & vbCr & "Update", "DrwDrawnPrtButton_ID", Inventor.CommandTypesEnum.kEditMaskCmdType,
                True, AddInClientID, "Update Drawn Name and Date", "Update Drawn Name and Date",
                "DrawnUpdate2021.DrawnUpdate2021_16x16.png", "DrawnUpdate2021.DrawnUpdate2021_32x32.png", Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) : Catch : End Try

            ' Add to the user interface, if it's the first time.
            If firstTime Then
                AddToUserInterface()
            End If
        End Sub

        ' 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.
        Public Sub Deactivate() Implements Inventor.ApplicationAddInServer.Deactivate

            ' TODO:  Add ApplicationAddInServer.Deactivate implementation

            ' Release objects.
            m_uiEvents = Nothing
            g_inventorApplication = Nothing

            System.GC.Collect()
            System.GC.WaitForPendingFinalizers()
        End Sub

        ' 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.
        Public ReadOnly Property Automation() As Object Implements Inventor.ApplicationAddInServer.Automation
            Get
                Return Nothing
            End Get
        End Property

        ' Note:this method is now obsolete, you should use the 
        ' ControlDefinition functionality for implementing commands.
        Public Sub ExecuteCommand(ByVal commandID As Integer) Implements Inventor.ApplicationAddInServer.ExecuteCommand
        End Sub

#End Region

#Region "Button Creation"
        Public Function CreateButton(ByRef strBtnDisplayName As String, ByRef strBtnInternalName As String, ByRef eBtnType As Inventor.CommandTypesEnum, ByRef blnAutoAddToGUI As Boolean, Optional ByRef strBtnClientId As String = "", Optional ByRef strBtnDescription As String = "", Optional ByRef strBtnToolTipText As String = "", Optional ByRef strBtnStdIcon As String = "", Optional ByRef strBtnLrgIcon As String = "", Optional ByRef eBtnDisplayEnum As Inventor.ButtonDisplayEnum = Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) As Inventor.ButtonDefinition

            Dim StandardIconIPictureDisp As Object = System.Type.Missing
            Dim LargeIconIPictureDisp As Object = System.Type.Missing
            Try
                If Not strBtnStdIcon Is Nothing Then
                    Dim StandardIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnStdIcon)
                    Dim StandardIconImage As System.Drawing.Image = New System.Drawing.Bitmap(StandardIconStream)

                    StandardIconIPictureDisp = ImageToPictureConverter.Convert(StandardIconImage)
                End If
            Catch ex As Exception
            End Try

            Try
                If Not strBtnLrgIcon Is Nothing Then
                    Dim LargeIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnLrgIcon)
                    Dim LargeIconImage As System.Drawing.Image = New System.Drawing.Bitmap(LargeIconStream)

                    LargeIconIPictureDisp = ImageToPictureConverter.Convert(LargeIconImage)
                End If
            Catch
            End Try

            CreateButton = g_inventorApplication.CommandManager.ControlDefinitions.AddButtonDefinition(strBtnDisplayName, strBtnInternalName, eBtnType, strBtnClientId, strBtnDescription, strBtnToolTipText, StandardIconIPictureDisp, LargeIconIPictureDisp, eBtnDisplayEnum)

            If CreateButton Is Nothing Then
                MsgBox("Failed to create Button:" & strBtnDisplayName)
            End If

        End Function
#End Region

#Region "ImageToPictureConverter"
        Public NotInheritable Class ImageToPictureConverter
            Inherits System.Windows.Forms.AxHost

            Private Sub New()
                MyBase.New(Nothing)
            End Sub

            Public Shared Function Convert(ByVal image As System.Drawing.Image) As stdole.IPictureDisp
                Return CType(System.Windows.Forms.AxHost.GetIPictureDispFromPicture(image), stdole.IPictureDisp)
            End Function

        End Class
#End Region

#Region "User interface definition"
        ' Sub where the user-interface creation is done.  This is called when
        ' the add-in loaded and also if the user interface is reset.
        Private Sub AddToUserInterface()
            ' This is where you'll add code to add buttons to the ribbon.

            '** Sample to illustrate creating a button on a new panel of the Tools tab of the Part ribbon.

            Dim userInterfaceMgr As UserInterfaceManager = g_inventorApplication.UserInterfaceManager
            '' userInterfaceMgr = g_inventorApplication.UserInterfaceManager

#Region "Add Button to Part Interface"

            '' Get the part ribbon.
            Dim invPrtRibbon As Ribbon = userInterfaceMgr.Ribbons.Item("Part")

            '' Get the "Tools" tab.
            'Dim toolsTab As RibbonTab = partRibbon.RibbonTabs.Item("id_TabTools")

            ' Check to see if the "Add-Ins" tab already exists in Part interface and create it if it doesn't.
            Dim invPrtAddInsTab As RibbonTab = Nothing
            Try
                invPrtAddInsTab = invPrtRibbon.RibbonTabs.Item("id_AddInsTab")
            Catch ex As Exception
                '  Create a new Add-Ins tab
                invPrtAddInsTab = invPrtRibbon.RibbonTabs.Add("Add-Ins", "id_AddInsTab", AddInClientID)
            End Try

            '' Create a new panel.
            'Dim customPanel As RibbonPanel = toolsTab.RibbonPanels.Add("Sample", "MysSample", AddInClientID)

            ' Check to see if the "Sipe" panel already exists in Part interface.
            Dim invPrtPanel As RibbonPanel = Nothing
            Try
                invPrtPanel = invPrtAddInsTab.RibbonPanels.Item("id_PanelP_Sipe")
            Catch ex1 As Exception
                Try
                    ' Check to see if the "IP General Tools" panel already exists in Part interface and create it if it doesn't.
                    invPrtPanel = invPrtAddInsTab.RibbonPanels.Item("id_PanelD_General")
                Catch ex2 As Exception
                    ' Create a new panel.
                    invPrtPanel = invPrtAddInsTab.RibbonPanels.Add("IP General Tools", "id_PanelD_General", AddInClientID)
                End Try
            End Try

            '' Add a button.
            'customPanel.CommandControls.AddButton(m_sampleButton)

            ' Add a button in Part interface.
            If Not m_DrawnPrtButton Is Nothing Then
                invPrtPanel.CommandControls.AddButton(m_DrawnPrtButton, True, True, ,)
            End If

#End Region

#Region "Add Button to Drawing Interface"

            '' Get the drawing ribbon
            Dim invDrwRibbon As Ribbon = userInterfaceMgr.Ribbons.Item("Drawing")

            ' Check to see if the "Add-Ins" tab already exists in Drawing interface and create it if it doesn't.
            Dim invDrwAddInsTab As RibbonTab = Nothing
            Try
                invDrwAddInsTab = invDrwRibbon.RibbonTabs.Item("id_AddInsTab")
            Catch ex As Exception
                '  Create a new Add-Ins tab
                invDrwAddInsTab = invDrwRibbon.RibbonTabs.Add("Add-Ins", "id_AddInsTab", AddInClientID)
            End Try

            ' Check to see if the "SIPE" panel already exists in Drawing interface.
            Dim invDrwPanel As RibbonPanel = Nothing
            Try
                invDrwPanel = invDrwAddInsTab.RibbonPanels.Item("id_PanelP_Sipe")
            Catch ex1 As Exception
                Try
                    ' Check to see if the "IP General Tools" panel already exists in Drawing interface and create it if it doesn't.
                    invDrwPanel = invDrwAddInsTab.RibbonPanels.Item("id_PanelD_General")
                Catch ex2 As Exception
                    ' Create a new panel.
                    invDrwPanel = invDrwAddInsTab.RibbonPanels.Add("IP General Tools", "id_PanelD_General", AddInClientID)
                End Try
            End Try

            ' Add a button in Drawing interface.
            If Not m_DrwDrawnPrtButton Is Nothing Then
                invDrwPanel.CommandControls.AddButton(m_DrwDrawnPrtButton, True, True, ,)
            End If
#End Region
        End Sub

        Private Sub m_uiEvents_OnResetRibbonInterface(Context As NameValueMap) Handles m_uiEvents.OnResetRibbonInterface
            ' The ribbon was reset, so add back the add-ins user-interface.
            AddToUserInterface()
        End Sub

        ' Sample handler for the button.
        'Private Sub m_sampleButton_OnExecute(Context As NameValueMap) Handles m_sampleButton.OnExecute
        '    MsgBox("Button was clicked.")
        'End Sub

#Region "Part Button Execute"

        Private Sub m_DrawnPrtButton_OnExecute(Context As NameValueMap) Handles m_DrawnPrtButton.OnExecute

            MsgBox("Button was clicked.")

        End Sub
#End Region


#Region "Drw Part Button Execute"

        Private Sub m_DrwDrawnPrtButton_OnExecute(Context As NameValueMap) Handles m_DrwDrawnPrtButton.OnExecute

            MsgBox("Button was clicked.")

        End Sub

#End Region

#End Region

    End Class
End Namespace


Public Module Globals
    ' Inventor application object.
    Public g_inventorApplication As Inventor.Application

#Region "Function to get the add-in client ID."
    ' This function uses reflection to get the GuidAttribute associated with the add-in.
    Public Function AddInClientID() As String
        Dim guid As String = ""
        Try
            Dim t As Type = GetType(DrawnUpdate2021.StandardAddInServer)
            Dim customAttributes() As Object = t.GetCustomAttributes(GetType(GuidAttribute), False)
            Dim guidAttribute As GuidAttribute = CType(customAttributes(0), GuidAttribute)
            guid = "{" + guidAttribute.Value.ToString() + "}"
        Catch
        End Try

        Return guid
    End Function
#End Region

#Region "hWnd Wrapper Class"
    ' This class is used to wrap a Win32 hWnd as a .Net IWind32Window class.
    ' This is primarily used for parenting a dialog to the Inventor window.
    '
    ' For example:
    ' myForm.Show(New WindowWrapper(g_inventorApplication.MainFrameHWND))
    '
    Public Class WindowWrapper
        Implements System.Windows.Forms.IWin32Window
        Public Sub New(ByVal handle As IntPtr)
            _hwnd = handle
        End Sub

        Public ReadOnly Property Handle() As IntPtr _
          Implements System.Windows.Forms.IWin32Window.Handle
            Get
                Return _hwnd
            End Get
        End Property

        Private _hwnd As IntPtr
    End Class
#End Region

#Region "Image Converter"
    ' Class used to convert bitmaps and icons from their .Net native types into
    ' an IPictureDisp object which is what the Inventor API requires. A typical
    ' usage is shown below where MyIcon is a bitmap or icon that's available
    ' as a resource of the project.
    '
    ' Dim smallIcon As stdole.IPictureDisp = PictureDispConverter.ToIPictureDisp(My.Resources.MyIcon)

    Public NotInheritable Class PictureDispConverter
        <DllImport("OleAut32.dll", EntryPoint:="OleCreatePictureIndirect", ExactSpelling:=True, PreserveSig:=False)> _
        Private Shared Function OleCreatePictureIndirect( _
            <MarshalAs(UnmanagedType.AsAny)> ByVal picdesc As Object, _
            ByRef iid As Guid, _
            <MarshalAs(UnmanagedType.Bool)> ByVal fOwn As Boolean) As stdole.IPictureDisp
        End Function

        Shared iPictureDispGuid As Guid = GetType(stdole.IPictureDisp).GUID

        Private NotInheritable Class PICTDESC
            Private Sub New()
            End Sub

            'Picture Types
            Public Const PICTYPE_BITMAP As Short = 1
            Public Const PICTYPE_ICON As Short = 3

            <StructLayout(LayoutKind.Sequential)> _
            Public Class Icon
                Friend cbSizeOfStruct As Integer = Marshal.SizeOf(GetType(PICTDESC.Icon))
                Friend picType As Integer = PICTDESC.PICTYPE_ICON
                Friend hicon As IntPtr = IntPtr.Zero
                Friend unused1 As Integer
                Friend unused2 As Integer

                Friend Sub New(ByVal icon As System.Drawing.Icon)
                    Me.hicon = icon.ToBitmap().GetHicon()
                End Sub
            End Class

            <StructLayout(LayoutKind.Sequential)> _
            Public Class Bitmap
                Friend cbSizeOfStruct As Integer = Marshal.SizeOf(GetType(PICTDESC.Bitmap))
                Friend picType As Integer = PICTDESC.PICTYPE_BITMAP
                Friend hbitmap As IntPtr = IntPtr.Zero
                Friend hpal As IntPtr = IntPtr.Zero
                Friend unused As Integer

                Friend Sub New(ByVal bitmap As System.Drawing.Bitmap)
                    Me.hbitmap = bitmap.GetHbitmap()
                End Sub
            End Class
        End Class

        Public Shared Function ToIPictureDisp(ByVal icon As System.Drawing.Icon) As stdole.IPictureDisp
            Dim pictIcon As New PICTDESC.Icon(icon)
            Return OleCreatePictureIndirect(pictIcon, iPictureDispGuid, True)
        End Function

        Public Shared Function ToIPictureDisp(ByVal bmp As System.Drawing.Bitmap) As stdole.IPictureDisp
            Dim pictBmp As New PICTDESC.Bitmap(bmp)
            Return OleCreatePictureIndirect(pictBmp, iPictureDispGuid, True)
        End Function
    End Class
#End Region

End Module

 

Expecting a possible solution .. @adam.nagy @xiaodong_liang ..Just tagging you guys.. because of the innumerous solutions you have provided to different people

0 Likes
Accepted solutions (1)
1,175 Views
5 Replies
Replies (5)
Message 2 of 6

JelteDeJong
Mentor
Mentor

I see a lot of try/catch blocks without any exception handling. My guess is that some thing is going wrong but you don't get notified. For example if your image is not of the correct format you will not get notified about it but your image will be nothing. I would suggest that you add a simple msgbox to you try/catch blocks. Especially in your CreateButton() function. something like this:

Public Function CreateButton(ByRef strBtnDisplayName As String, ByRef strBtnInternalName As String, ByRef eBtnType As Inventor.CommandTypesEnum, ByRef blnAutoAddToGUI As Boolean, Optional ByRef strBtnClientId As String = "", Optional ByRef strBtnDescription As String = "", Optional ByRef strBtnToolTipText As String = "", Optional ByRef strBtnStdIcon As String = "", Optional ByRef strBtnLrgIcon As String = "", Optional ByRef eBtnDisplayEnum As Inventor.ButtonDisplayEnum = Inventor.ButtonDisplayEnum.kDisplayTextInLearningMode) As Inventor.ButtonDefinition

    Dim StandardIconIPictureDisp As Object = System.Type.Missing
    Dim LargeIconIPictureDisp As Object = System.Type.Missing
    Try
        If Not strBtnStdIcon Is Nothing Then
            Dim StandardIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnStdIcon)
            Dim StandardIconImage As System.Drawing.Image = New System.Drawing.Bitmap(StandardIconStream)

            StandardIconIPictureDisp = ImageToPictureConverter.Convert(StandardIconImage)
        End If
    Catch ex As Exception
        MsgBox("Could not create StandardIconIPictureDisp" + ex.Message)
    End Try

    Try
        If Not strBtnLrgIcon Is Nothing Then
            Dim LargeIconStream As System.IO.Stream = Me.GetType().Assembly.GetManifestResourceStream(strBtnLrgIcon)
            Dim LargeIconImage As System.Drawing.Image = New System.Drawing.Bitmap(LargeIconStream)

            LargeIconIPictureDisp = ImageToPictureConverter.Convert(LargeIconImage)
        End If
    Catch ex As Exception
        MsgBox("Could not create LargeIconIPictureDisp" + ex.Message)
    End Try

    CreateButton = g_inventorApplication.CommandManager.ControlDefinitions.AddButtonDefinition(strBtnDisplayName, strBtnInternalName, eBtnType, strBtnClientId, strBtnDescription, strBtnToolTipText, StandardIconIPictureDisp, LargeIconIPictureDisp, eBtnDisplayEnum)

    If CreateButton Is Nothing Then
        MsgBox("Failed to create Button:" & strBtnDisplayName)
    End If

End Function

Maybe this is not the solution but if you get an error message then at least you know where to look.

Jelte de Jong
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature


Blog: hjalte.nl - github.com

0 Likes
Message 3 of 6

etaCAD
Advocate
Advocate
Accepted solution

I didn't run your code and check in detail. I know that icons can be tricky.

Did you ckeck if your icons have to be set as embedded ressouce?

 

I also recommend to go through your code line by line with the debugger and check if you run into an exception. The tooltip in debug mode shows you the value of the variables. So you can always check the content of your icon-variables.

Andreas
etaCAD

Message 4 of 6

sanil_heartbeats
Contributor
Contributor

Thank you so much.... this was the one step I missed... now it works fine. Now I've got a new issue. I need to check if a particular panel exists in the ribbon. If it exists, I need to add the button to that panel. if the panel doesn't exist, I need to create a new panel and add the button to it. I ma not able to get this condition to work properly. I know, it is a different issue but not the one mentioned in the title. so ill create a new query

0 Likes
Message 5 of 6

MaciejWojda
Enthusiast
Enthusiast

@sanil_heartbeats can you please describe what was the problem?

0 Likes
Message 6 of 6

sanil_heartbeats
Contributor
Contributor

I forgot to set the icons as embedded resource in its property detail. Once i did that, the icons loaded properly 

0 Likes