Add button to ribbon panel for Add-In

Add button to ribbon panel for Add-In

ccoomes
Advocate Advocate
1,918 Views
2 Replies
Message 1 of 3

Add button to ribbon panel for Add-In

ccoomes
Advocate
Advocate

I have created an Inventor Add-In using the Nifty Add-In Template and I have hit a problem when adding more than 1 button to a custom Ribbon panel.

 

When I try to add a second button to an existing panel, I get the error:

 

error HREULTSs: 0x80004005(E_FAIL)

 

The code I am using is as follows:

 

Private Sub AddToUserInterface()
' This sample code illustrates creating a button on a new panel of the Tools tab of
' the Part ribbon. You'll need to change this to create the UI that your add-in needs.

 

'Add button to Part Ribbon, 3D Model Tab
AddPaneltoRibbon("Part", "id_TabModel", "MyPanel", "Part3DModPanelID", m_PartiPropButton)
AddPaneltoRibbon("Part", "id_TabModel", "MyPanel", "Part3DModPanelID", m_SaveSEFileButton)

 

The AddPaneltoRibbon is a sub created from the code in the Nifty Template to allow multiple buttons to be added as is a follows:

 

Sub AddPaneltoRibbon(RibnName As String, RibnTabName As String, RibPnlName As String, RibPnlID As String, BtnName As ButtonDefinition)

'Get the Ribbon
Dim Ribn As Ribbon = g_inventorApplication.UserInterfaceManager.Ribbons.Item(RibnName)

'Get the ribbon Tab
Dim RibnTab As RibbonTab = Ribn.RibbonTabs.Item(RibnTabName)

' Check to see if the panel already exists and create it if it doesn't.
Dim Pnl As RibbonPanel = Nothing

Try
Pnl = RibnTab.RibbonPanels.Item(RibPnlName)
Catch ex As Exception
Pnl = RibnTab.RibbonPanels.Add(RibPnlName, RibPnlID, g_addInClientID)
End Try

' Add a button.
If Not BtnName Is Nothing Then
Pnl.CommandControls.AddButton(BtnName, True)
End If

End Sub

 

I can get a single button to create a new panel, and then add the button, but it will not allow me to add a second button to the panel.  If I create a different panel by a different unique ID, it adds a second panel to the ribbon tab, as per the code below:

 

'Add button to Part Ribbon, 3D Model Tab
AddPaneltoRibbon("Part", "id_TabModel", "MyPanel", "Part3DModPanelID", m_PartiPropButton)
AddPaneltoRibbon("Part", "id_TabModel", "MyPanel", "Part3DModPanelID2", m_SaveSEFileButton)

 

I have been through the previous posts on similar subjects, tried all of the suggestions and solutions, but I just cannot get it to add the second button on the Panel.

 

Could someone please let me know what I have done wrong so I can get it to add a second button to an existing Ribbon panel?

 

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

NachoShaw
Advisor
Advisor
Accepted solution

Hey

 

you might be best adding the buttons independently rather than trying to rely on a function to create them. Here is the code i use-

 

AddinGlobal Class

Imports System
Imports System.Collections.Generic
Imports System.Runtime.InteropServices

Imports Inventor

Public Class AddinGlobal
    Public Shared InventorApp As Inventor.Application

    Public Shared RibbonPanelId As String
    Public Shared RibbonPanel As RibbonPanel
    Public Shared ButtonList As List(Of InventorButton) = New List(Of InventorButton)()

    Private Shared mClassId As String
    Public Shared Property ClassId As String
        Get
            If (Not String.IsNullOrEmpty(mClassId)) Then
                Return AddinGlobal.mClassId
            Else
                Throw New System.Exception("The addin server cannot be found!")
            End If
        End Get
        Set
            AddinGlobal.mClassId = Value
        End Set
    End Property

    Public Shared Sub GetAddinClassId(ByVal t As Type)
        Dim guidAtt As GuidAttribute = GuidAttribute.GetCustomAttribute(t, GetType(GuidAttribute))
        mClassId = "{" + guidAtt.Value + "}"
    End Sub
End Class

 

InventorAddinServer Class

populate the private variables at the top (RibbonName, AddTab, MyTabName etc)

add your application GUID. i have added 2 buttons to this class with an icon for each. you will need to edit the button descriptions

Imports System
Imports System.Reflection
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports Inventor

    <Guid("add your GUID here")>
    Public Class InventorAddinServer
        Implements ApplicationAddInServer

        Private RibbonName As String = "Part"
        Private AddTab As Boolean = False
        Private MyTabName As String = "id_TabModel"
        Private MyTabID As String = "id_Tabid_" & MyTabName
        Private MyPanel As String = "My Panel"

	Private Button1Title As String = "My Button 1"
	Private Button1Description As String = "My Button 1 Description"
	Private Button1ToolTip As String = "My Button 1 Tooltip"

	Private Button2Title As Stringg = "My Button 2"
	Private Button2Description As String = "My Button 2 Description"
	Private Button2ToolTip As String = "My Button 2 Tooltip"

        Sub New()
        End Sub

        ''' <summary>
        ''' Do initializations in it such as caching the application object, registering event handlers, and adding ribbon buttons.
        ''' </summary>
        ''' <param name="siteObj">The entry object for the addin.</param>
        ''' <param name="loaded1stTime">Indicating whether the addin is loaded for the 1st time.</param>
        Sub Activate(ByVal siteObj As ApplicationAddInSite, ByVal loaded1stTime As Boolean) Implements ApplicationAddInServer.Activate
            AddinGlobal.InventorApp = siteObj.Application

            Try
                AddinGlobal.GetAddinClassId(Me.GetType())

                'create your icons, make sure they are embedded and added to the resources
                Dim icon1 As Icon = New Icon(Me.GetType(), "MyIcon1.ico")
                Dim icon2 As Icon = New Icon(Me.GetType(), "MyIcon2.ico")

                Dim button1 As InventorButton = New InventorButton(Button1Title, "InventorAddinServer.Button_" + Guid.NewGuid().ToString(), Button1Description, Button1Tooltip, icon1, icon1, CommandTypesEnum.kShapeEditCmdType, ButtonDisplayEnum.kDisplayTextInLearningMode)
                button1.SetBehavior(True, True, True)
                button1.Execute = AddressOf ButtonActions.Button1_Execute

                Dim button2 As InventorButton = New InventorButton(Button2Title, "InventorAddinServer.Button_" + Guid.NewGuid().ToString(), Button1Description, Button1Tooltip, icon2, icon2, CommandTypesEnum.kShapeEditCmdType, ButtonDisplayEnum.kDisplayTextInLearningMode)
                button2.SetBehavior(True, True, True)
                button2.Execute = AddressOf ButtonActions.Button2_Execute

                If (loaded1stTime = True) Then
                    Dim uiMan As UserInterfaceManager = AddinGlobal.InventorApp.UserInterfaceManager
                    'kClassicInterface support can be added if necessary.
                    If (uiMan.InterfaceStyle = InterfaceStyleEnum.kRibbonInterface) Then
                        Dim ribbon As Inventor.Ribbon = uiMan.Ribbons(RibbonName)
                        Dim tab As RibbonTab = Nothing

                        Select Case AddTab
                            Case True
                                Try
                                    'Change it if necessary.
                                    tab = ribbon.RibbonTabs(MyTabName)
                                Catch
                                    tab = ribbon.RibbonTabs.Add(MyTabName, MyTabID, Guid.NewGuid().ToString())
                                End Try
                            Case False
                                tab = ribbon.RibbonTabs(MyTabName)
                        End Select

                        AddinGlobal.RibbonPanelId = "{ae9863ba-cf99-4cdd-93ce-6ebfa99ac23b}"
                        AddinGlobal.RibbonPanel = tab.RibbonPanels.Add(MyPanel, "InventorAddinServer.RibbonPanel_" + Guid.NewGuid().ToString(), AddinGlobal.RibbonPanelId, String.Empty, True)

                        Dim cmdCtrls As CommandControls = AddinGlobal.RibbonPanel.CommandControls

                        cmdCtrls.AddButton(button1.ButtonDef, button1.DisplayBigIcon, button1.DisplayText, "", button1.InsertBeforeTarget)
                        cmdCtrls.AddButton(button2.ButtonDef, button2.DisplayBigIcon, button2.DisplayText, "", button2.InsertBeforeTarget)
                    End If
                End If
            Catch e As Exception
                MessageBox.Show(e.ToString())
            End Try

            Try
                AddinGlobal.GetAddinClassId(Me.GetType())

                'Change it if necessary but make sure it's embedded.

            Catch e As Exception
                MessageBox.Show(e.ToString())
            End Try

            ' TODO: Add more initialization code below.

            mTransactionEvents1 = New TransactionEvents1(AddinGlobal.InventorApp.TransactionManager.TransactionEvents)
            mTransactionEvents1.Register()
        End Sub

        ''' <summary>
        ''' Do cleanups in it such as forcing GC Collection and closing log files.
        ''' </summary>
        Sub Deactivate() Implements ApplicationAddInServer.Deactivate
            mTransactionEvents1.UnRegister()

        End Sub

        ''' <summary>
        ''' Deprecated. Use the ControlDefinition instead to execute commands.
        ''' </summary>
        ''' <param name="commandID"></param>
        Sub ExecuteCommand(ByVal commandID As Integer) Implements ApplicationAddInServer.ExecuteCommand

        End Sub

        ''' <summary>
        ''' Implement it if wanting to expose your own automation interface.
        ''' </summary>
        ReadOnly Property Automation As Object Implements ApplicationAddInServer.Automation
            Get
                Return Nothing
            End Get
        End Property

        Dim mTransactionEvents1 As TransactionEvents1
    End Class

 

InventorButton Class

Imports System
Imports System.Windows.Forms
Imports System.Drawing

Imports Inventor

'Namespace ViewLabels
''' <summary>
''' The class wrapps up Inventor Button creation stuffs and is easy to use.
''' No need to derive. Create an instance using either constructor and assign the Action.
''' </summary>
Public Class InventorButton
#Region "Fields And  Properties"

    Private mButtonDef As ButtonDefinition
    Public Property ButtonDef As ButtonDefinition
        Get
            Return mButtonDef
        End Get
        Set
            mButtonDef = Value
        End Set
    End Property

#End Region

#Region "Constructors"

    ''' <summary>
    ''' The most comprehensive signature.
    ''' </summary>
    Sub New(ByVal displayName As String, ByVal internalName As String, ByVal description As String, ByVal tooltip As String, ByVal standardIcon As Icon, ByVal largeIcon As Icon, ByVal commandType As CommandTypesEnum, ByVal buttonDisplayType As ButtonDisplayEnum)
        Create(displayName, internalName, description, tooltip, AddinGlobal.ClassId, standardIcon, largeIcon, commandType, buttonDisplayType)
    End Sub

    ''' <summary>
    ''' The signature does not care about Command Type (always editing) and Button Display (always with text).
    ''' </summary>
    Sub New(ByVal displayName As String, ByVal internalName As String, ByVal description As String, ByVal tooltip As String, ByVal standardIcon As Icon, ByVal largeIcon As Icon)
        Create(displayName, internalName, description, tooltip, AddinGlobal.ClassId, Nothing, Nothing, CommandTypesEnum.kEditMaskCmdType, ButtonDisplayEnum.kAlwaysDisplayText)
    End Sub

    ''' <summary>
    ''' The signature does not care about icons.
    ''' </summary>
    Sub New(ByVal displayName As String, ByVal internalName As String, ByVal description As String, ByVal tooltip As String, ByVal commandType As CommandTypesEnum, ByVal buttonDisplayType As ButtonDisplayEnum)
        Create(displayName, internalName, description, tooltip, AddinGlobal.ClassId, Nothing, Nothing, commandType, buttonDisplayType)
    End Sub

    ''' <summary>
    ''' This signature only cares about display name and icons.
    ''' </summary>
    ''' <param name="displayName"></param>
    ''' <param name="standardIcon"></param>
    ''' <param name="largeIcon"></param>
    Sub New(ByVal displayName As String, ByVal standardIcon As Icon, ByVal largeIcon As Icon)
        Create(displayName, displayName, displayName, displayName, AddinGlobal.ClassId, standardIcon, largeIcon, CommandTypesEnum.kEditMaskCmdType, ButtonDisplayEnum.kAlwaysDisplayText)
    End Sub

    ''' <summary>
    ''' The simplest signature, which can be good for prototyping.
    ''' </summary>
    Sub New(ByVal displayName As String)
        Create(displayName, displayName, displayName, displayName, AddinGlobal.ClassId, Nothing, Nothing, CommandTypesEnum.kEditMaskCmdType, ButtonDisplayEnum.kAlwaysDisplayText)
    End Sub

    ''' <summary>
    ''' The helper method for constructors to call to avoid duplicate code.
    ''' </summary>
    Public Sub Create(ByVal displayName As String, ByVal internalName As String, ByVal description As String, ByVal tooltip As String, ByVal clientId As String, ByVal standardIcon As Icon, ByVal largeIcon As Icon, ByVal commandType As CommandTypesEnum, ByVal buttonDisplayType As ButtonDisplayEnum)
        If (String.IsNullOrEmpty(clientId)) Then
            clientId = AddinGlobal.ClassId
        End If

        Dim standardIconIPictureDisp As stdole.IPictureDisp = Nothing
        Dim largeIconIPictureDisp As stdole.IPictureDisp = Nothing
        If (standardIcon IsNot Nothing) Then
            standardIconIPictureDisp = IconToPicture(standardIcon)
            largeIconIPictureDisp = IconToPicture(largeIcon)
        End If

        mButtonDef = AddinGlobal.InventorApp.CommandManager.ControlDefinitions.AddButtonDefinition(displayName, internalName, commandType, clientId, description, tooltip, standardIconIPictureDisp, largeIconIPictureDisp, buttonDisplayType)

        mButtonDef.Enabled = True
        AddHandler mButtonDef.OnExecute, AddressOf ButtonDefinition_OnExecute

        DisplayText = True

        AddinGlobal.ButtonList.Add(Me)
    End Sub

#End Region

#Region "Behavior"

    Public Property DisplayBigIcon As Boolean
    Public Property DisplayText As Boolean
    Public Property InsertBeforeTarget As Boolean

    Public Sub SetBehavior(ByVal useBigIcon As Boolean, ByVal showText As Boolean, ByVal beforeTarget As Boolean)
        DisplayBigIcon = useBigIcon
        DisplayText = showText
        InsertBeforeTarget = beforeTarget
    End Sub

    Public Sub CopyBehaviorFrom(ByVal button As InventorButton)
        DisplayBigIcon = button.DisplayBigIcon
        DisplayText = button.DisplayText
        InsertBeforeTarget = InsertBeforeTarget
    End Sub

#End Region

#Region "Actions"

    ''' <summary>
    ''' The button callback method.
    ''' </summary>
    ''' <param name="context"></param>
    Private Sub ButtonDefinition_OnExecute(ByVal context As NameValueMap)
        If (Execute IsNot Nothing) Then
            Execute()
        Else
            MessageBox.Show("Nothing to execute.")
        End If
    End Sub

    ''' <summary>
    ''' The button action to be assigned from anywhere outside.
    ''' </summary>
    Public Execute As Action

#End Region

#Region "Image Converters"

    Public Shared Function ImageToPicture(ByVal image As Image) As stdole.IPictureDisp
        Return ImageConverter.ImageToPicture(image)
    End Function

    Public Shared Function IconToPicture(ByVal icon As Icon) As stdole.IPictureDisp
        Return ImageConverter.ImageToPicture(icon.ToBitmap())
    End Function

    Public Shared Function PictureToImage(ByVal picture As stdole.IPictureDisp) As Image
        Return ImageConverter.PictureToImage(picture)
    End Function

    Public Shared Function PictureToIcon(ByVal picture As stdole.IPictureDisp) As Icon
        Return ImageConverter.PictureToIcon(picture)
    End Function

    Private Class ImageConverter
        Inherits AxHost
        Sub New()
            MyBase.New(String.Empty)
        End Sub

        Public Shared Function ImageToPicture(ByVal image As Image) As stdole.IPictureDisp
            Return GetIPictureDispFromPicture(image)
        End Function

        Public Shared Function IconToPicture(ByVal icon As Icon) As stdole.IPictureDisp
            Return ImageToPicture(icon.ToBitmap())
        End Function

        Public Shared Function PictureToImage(ByVal picture As stdole.IPictureDisp) As Image
            Return GetPictureFromIPicture(picture)
        End Function

        Public Shared Function PictureToIcon(ByVal picture As stdole.IPictureDisp) As Icon
            Dim bitmap As Bitmap = New Bitmap(PictureToImage(picture))
            Return System.Drawing.Icon.FromHandle(bitmap.GetHicon())
        End Function
    End Class

#End Region
End Class

''' <summary>
''' This class is used to set the InventorWin as the owner of any WinForms.
''' Usage:
'''         winform.Show(New InventorWin())
''' </summary>
Public Class InventorWin
    Implements IWin32Window
    Public ReadOnly Property Handle As IntPtr Implements IWin32Window.Handle
        Get
            Return AddinGlobal.InventorApp.MainFrameHWND
        End Get
    End Property
End Class
'End Namespace

 

ButtonActions Class

#Region "Namespaces"
Imports System
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports Inventor
#End Region

Public Class ButtonActions
    Public Shared Sub Button1_Execute()
       Msgbox("Button 1 pressed")
    End Sub

    Public Shared Sub Button2_Execute()
       Msgbox("Button 2 pressed")
    End Sub
End Class

 

 

Nacho
Automation & Design Engineer

Inventor automation Programmer (C#, VB.Net / iLogic)
Furniture, Sheet Metal, Structural, Metal fab, Tradeshow, Fabrication, CNC

EESignature


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.


0 Likes
Message 3 of 3

ccoomes
Advocate
Advocate

Sorry for the delay in reply, I have been away from week.

 

After reading everyone's posts and help, the function I was using would not add buttons if the tab already exists.  Not sure why but I once you add them at the same time it works correctly.

 

To get round this, I modified my function add up to 10 buttons at the same time.  It may not be the best solution or correct method to do it, but it works for me.

 

Below is the code to the sub that adds the buttons to a new ribbon:

 

Sub AddPaneltoRibbon(RibnName As String, RibnTabName As String, RibPnlName As String, RibPnlID As String, AddStandardButtons As Boolean, BtnName1 As ButtonDefinition, Optional ByVal BtnName2 As ButtonDefinition = Nothing, Optional ByVal BtnName3 As ButtonDefinition = Nothing,
                             Optional ByVal BtnName4 As ButtonDefinition = Nothing, Optional ByVal BtnName5 As ButtonDefinition = Nothing, Optional ByVal BtnName6 As ButtonDefinition = Nothing, Optional ByVal BtnName7 As ButtonDefinition = Nothing,
                             Optional ByVal BtnName8 As ButtonDefinition = Nothing, Optional ByVal BtnName9 As ButtonDefinition = Nothing, Optional ByVal BtnName10 As ButtonDefinition = Nothing)

            'Get the controll Definitions for Built-In Buttons
            Dim oControlDef1 As Inventor.ControlDefinitions = g_inventorApplication.CommandManager.ControlDefinitions

            'Get the Ribbon
            Dim Ribn As Ribbon = g_inventorApplication.UserInterfaceManager.Ribbons.Item(RibnName)

            'Get the ribbon Tab
            Dim RibnTab As RibbonTab = Ribn.RibbonTabs.Item(RibnTabName)

            ' Check to see if the panel already exists and create it if it doesn't.
            Dim Pnl As RibbonPanel = Nothing

            'Set the Standard Buttons
            Dim BtnSaveAsDef1 As ButtonDefinition = oControlDef1.Item("AppFileSaveAsCmd")
            Dim BtnSaveCopyAsDef1 As ButtonDefinition = oControlDef1.Item("AppFileSaveCopyAsCmd")
            Dim BtnCloseActiveDef1 As ButtonDefinition = oControlDef1.Item("AppFileCloseCmd")

            Try
                Pnl = RibnTab.RibbonPanels.Item(RibPnlName)
            Catch ex As Exception
                Pnl = RibnTab.RibbonPanels.Add(RibPnlName, RibPnlID, g_addInClientID)
            End Try

            If AddStandardButtons = True Then
                Pnl.CommandControls.AddButton(BtnSaveAsDef1, False, False)
                Pnl.CommandControls.AddButton(BtnSaveCopyAsDef1, False, False)
                '.CommandControls.AddButton(BtnCloseActiveDef1, False, False)
            End If

            ' Add a button.
            Pnl.CommandControls.AddButton(BtnName1, True)
            If Not IsNothing(BtnName2) Then Pnl.CommandControls.AddButton(BtnName2, True)
            If Not IsNothing(BtnName3) Then Pnl.CommandControls.AddButton(BtnName3, True)
            If Not IsNothing(BtnName4) Then Pnl.CommandControls.AddButton(BtnName4, True)
            If Not IsNothing(BtnName5) Then Pnl.CommandControls.AddButton(BtnName5, True)
            If Not IsNothing(BtnName6) Then Pnl.CommandControls.AddButton(BtnName6, True)
            If Not IsNothing(BtnName7) Then Pnl.CommandControls.AddButton(BtnName7, True)
            If Not IsNothing(BtnName8) Then Pnl.CommandControls.AddButton(BtnName8, True)
            If Not IsNothing(BtnName9) Then Pnl.CommandControls.AddButton(BtnName9, True)
            If Not IsNothing(BtnName10) Then Pnl.CommandControls.AddButton(BtnName10, True)

        End Sub

 

It is not the prettiest, and when I have more time I will try to add the button by using the examples provided.

 

Thanks again for everyone's help.

0 Likes