How to add a WPF window to an Add-In

How to add a WPF window to an Add-In

piotrekdoro94
Advocate Advocate
545 Views
3 Replies
Message 1 of 4

How to add a WPF window to an Add-In

piotrekdoro94
Advocate
Advocate

Hi, I'm trying to convert my plugins to proper add-ins with limited success. I have problems trying to add a WPF window as a UI and attaching some code to it.

 

For example: I have a simple code snippet that creates a work point in the center of mass. It works while the code is executed by a click event of a button I've added to my ribbon, which is fine for a simple feature like this.

For more complex add-ins I want the click event of a button on the ribbon to open a WPF window which contains its own set of buttons and controls which will execute my code.

 

Here is a code snippet that shows what happens when a MyButton (that's the button added to the ribbon) is clicked. This implementation works

 

 

 

 

Private Sub MyButton_OnExecute(Context As NameValueMap)
    Try
       Dim oPartDoc As PartDocument
       Dim oPartCompDef As PartComponentDefinition

       oPartDoc = _inventor.ActiveDocument
       oPartCompDef = oPartDoc.ComponentDefinition

       Dim oCenterOfMass As Point
       Dim oWorkPoint As WorkPoint

       oCenterOfMass = oPartCompDef.MassProperties.CenterOfMass
       oWorkPoint = oPartCompDef.WorkPoints.AddFixed(oCenterOfMass)

       Catch ex As Exception
       MsgBox("Center of mass property could not be found")
       End Try
End Sub

 

 

 

 

Now I've changed MyButton so that clicking it shows a WPF window called Window1:

 

 

 

 Private Sub MyButton_OnExecute(Context As NameValueMap)
     Dim window As New Window1
     window.Show()
 End Sub

 

 

 

 

That window contains just one button which should put a work point in the center of mass. The Window1 code looks like this:

 

 

 

Imports System.Runtime.InteropServices
Imports Inventor

Public Class Window1
    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Try
            Dim _inventor As Inventor.Application
            Dim oPartDoc As PartDocument
            Dim oPartCompDef As PartComponentDefinition

            oPartDoc = _inventor.ActiveDocument
            oPartCompDef = oPartDoc.ComponentDefinition

            Dim oCenterOfMass As Point
            Dim oWorkPoint As WorkPoint

            oCenterOfMass = oPartCompDef.MassProperties.CenterOfMass
            oWorkPoint = oPartCompDef.WorkPoints.AddFixed(oCenterOfMass)

        Catch ex As Exception
            MsgBox("Center of mass property could not be found")
        End Try
    End Sub
End Class

 

 

 

 

Now there is some bug on line 11. I can't get a reference to active document but I don't know how to fix it. I'm no developer and I already find add-in creation pretty arcane.

 

 I've created my add-in following a tutorial at: Jelte de Jong (hjalte.nl).

The entire visual studio project in its broken state is in the attachments ("CenterOfMass - project files.zip")

I've also added a compiled, working version that doesn't use a WPF window. It should appear in Part environment in 3d model tab in work features panel ("CenterOfMass - compiled and working.zip"). 

 

The project contains:

- a CenterOfMass

0 Likes
546 Views
3 Replies
Replies (3)
Message 2 of 4

JelteDeJong
Mentor
Mentor

in your file Window1.xaml.vb I'm missing the constructor. I guess that you need to add this:

Private ReadOnly _inventor As Inventor.Application

Public Sub New(inventor As Inventor.Application)

    ' This call is required by the designer.
    InitializeComponent()

    _inventor = inventor

End Sub

That will break your button class. You have to change the sub "MyButton_OnExecute(Context As NameValueMap)" (in file MyButton.vb) to this:

Private Sub MyButton_OnExecute(Context As NameValueMap)

    Dim window As New Window1(_inventor)
    window.ShowDialog()

End Sub

 

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 4

piotrekdoro94
Advocate
Advocate

Thank you for help, your tutorials were very useful.

 

Unfortunately, I can't get CenterOfMass add-in to work. It keeps throwing in the same place. After suggested modifications MyButton.vb looks like this:

 

Imports System.Runtime.InteropServices
Imports Inventor
Public Class MyButton
    Private _inventor As Inventor.Application
    Private _settingsButton As ButtonDefinition
    Public Sub New(inventor As Inventor.Application)
        _inventor = inventor

        SetupButtonDefinition()
        AddButtonDefinitionToRibbon()
    End Sub

    Private Sub SetupButtonDefinition()

        Dim conDefs As ControlDefinitions = _inventor.CommandManager.ControlDefinitions
        _settingsButton = conDefs.AddButtonDefinition(
            "Center of Mass",
            "Center of Mass",
            CommandTypesEnum.kEditMaskCmdType,
            Guid.NewGuid().ToString(),
            "Command creates a work point in the center of mass coordinates. Works in Part environment and is part of CenterOfMass add-in",
            "Create point in center of mass")
        AddHandler _settingsButton.OnExecute, AddressOf MyButton_OnExecute

    End Sub

    Private Sub AddButtonDefinitionToRibbon()

        Dim ribbon As Ribbon = _inventor.UserInterfaceManager.Ribbons.Item("Part")
        Dim ribbonTab As RibbonTab = ribbon.RibbonTabs.Item("id_TabModel")
        Dim ribbonPanel As RibbonPanel = ribbonTab.RibbonPanels.Item("id_PanelA_ModelWorkFeatures")
        ribbonPanel.CommandControls.AddButton(_settingsButton)

    End Sub

    Private Sub MyButton_OnExecute(Context As NameValueMap) 
        Dim window As New Window1(_inventor)
        window.ShowDialog()
    End Sub
End Class

 

And the Window1.xaml.vb looks like this:

 

Imports System.Runtime.InteropServices
Imports Inventor

Public Class Window1

    Private ReadOnly _inventor As Inventor.Application

    Public Sub New(inventor As Inventor.Application)

        ' This call is required by the designer.
        InitializeComponent()

        _inventor = inventor

    End Sub

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)

        Try
            Dim _inventor As Inventor.Application
            Dim oPartDoc As PartDocument
            Dim oPartCompDef As PartComponentDefinition

            oPartDoc = _inventor.ActiveDocument
            oPartCompDef = oPartDoc.ComponentDefinition

            Dim oCenterOfMass As Point
            Dim oWorkPoint As WorkPoint

            oCenterOfMass = oPartCompDef.MassProperties.CenterOfMass
            oWorkPoint = oPartCompDef.WorkPoints.AddFixed(oCenterOfMass)


        Catch ex As Exception

            MsgBox("Center of mass property could not be found")

        End Try
    End Sub
End Class

 

I don't think I understand what the code snippets you've provided do. As I understand it:

- in MyButton.vb

Private Sub MyButton_OnExecute(Context As NameValueMap)

    Dim window As New Window1(_inventor) 'Here I'm passing a field of a MyButton instace to the Window1 constructor. _inventor=inventor means that _inventor is an Inventor application object 
    window.ShowDialog() 'Here I'm switching from modal Show() to non-modal Showdialog(). I'm not sure if it means something

End Sub

 In Window1.xlam.vb:

Private ReadOnly _inventor As Inventor.Application 'I'm declaring a field _inventor which is an Inventor application object

Public Sub New(inventor As Inventor.Application) 'This is a constructor for Window one which is called from MyButton.vb 

    ' This call is required by the designer.
    InitializeComponent() 'I'm not sure why this is necessary. From quick googling it seems that Visual Studio adds this to a Sub New automatically

    _inventor = inventor

End Sub

 

0 Likes
Message 4 of 4

piotrekdoro94
Advocate
Advocate

I've managed to cobble together something resembling a solution but it's pretty ugly and I would gladly use something else.

 

I've deleted my WPF window (Window1) from my project folder. Then I've rewritten the "CenterOfMass" as a separate winforms app and compiled it. The winform has a button with an onClick event that looks like this:

 

 

 

Imports Inventor
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Imports System.Windows.Forms
Imports System.IO
Imports System.Xml.Serialization
Imports System.Security.Cryptography
Imports System.Diagnostics.Contracts

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click


        Dim InventorApp As Inventor.Application
        Dim oPartDoc As PartDocument
        Dim oPartCompDef As PartComponentDefinition

        InventorApp = Marshal.GetActiveObject("Inventor.Application")
        oPartDoc = InventorApp.ActiveDocument
        oPartCompDef = oPartDoc.ComponentDefinition
        oPartDoc.Activate()

        Try
            InventorApp = Marshal.GetActiveObject("Inventor.Application")
            MessageBox.Show("Connected To Inventor session")

        Catch ex As Exception
            MessageBox.Show("Failed to connect to inventor session")
        End Try


        Dim oCenterOfMass As Point
        Dim oWorkPoint As WorkPoint

        Try
            oCenterOfMass = oPartCompDef.MassProperties.CenterOfMass
            oWorkPoint = oPartCompDef.WorkPoints.AddFixed(oCenterOfMass)
        Catch
            MsgBox("No center of mass detected")
        End Try

    End Sub
End Class

 

 

 

Now I use the ribbon button to run a compiled version of the winforms app shown above. The ribbbon button executes the following code when clicked:

 

 

 

 Private Sub MyButton_OnExecute(Context As NameValueMap)
     Process.Start("C:\Users\Piotrekdoro\Desktop\InventorVBA\Center of mass 1\bin\Debug\WindowsApp1.exe")
 End Sub

 

 

 

There are two big downsides with this approach that might emerge as far as I can predict:

 

  • Problems with debugging - if there is a bug in the separate executable then debugger will not find it
  • Add-in as a process is lumped with the main Inventor process. When I use it to launch a separate executable I create a separate process, which means that the add-in can't directly talk with UI. It also means that the code in the separate program won't be able to use Inventor specific events. I don't need this functionality at the moment, but I think that both of these issues could be solved by handling events within the add-in and creating intermediary "input.txt" and "output.txt" files which would be used for the addin and UI to communicate with each other
0 Likes