Inventor API: Custom add-in #1 – Introduction & modifying the ribbon

Hi!
Long time no see I might say… But there is a reason for that. As I mentioned in my previous post I turned my focus onto add-ins for Inventor and I have spent some time on that. Now, the plan is for short series of three post about writing add-in for Inventor. It will consist of three episodes: one – introduction and modifying the ribbon; two – description what the add-in we’re going to write in this series will do and its user interface in WPF; three – everything that resided under the hood and presentation how it works with Inventor.

TOOLS

In terms of tools there is nothing special needed. Obviously, Inventor needs to be installed and it’s SDK that comes along with the package. I do not own a licence for Inventor, but Autodesk allows for free 30-day trial to test their packages. The trial is for full package with no feature-limitations, however it is not allowed to use it for “commercial or for-profit purposes” [see here][1]. Writing these posts does not and will not violate either of those conditions, nonetheless if you are willing to write an add-in that will be used commercially you cannot do that with the trial. That having said we can move forward.
Once you have it installed it is necessary to install the SDK. It is an .MSI package you need to extract. It can be found in your Public Documents folder, then /Autodesk/Inventor2018/SDK. The package we’re interested in is developertools.msi. It will deliver some samples and – most important – project templates for Visual Studio. Unfortunately, the templates are for VS2015 so if you’re using VS2017 you will need to install older version as the templates will be installed only if Visual Studio is installed. If you still prefer to use VS2017 you can create project ins VS2015 and then open it newer IDE. I have not encountered any issues.

To sum things up, you will need:

  • Microsoft Visual Studio 2015 and optionally  Visual Studio 2017
  • Autodesk Inventor package which you can download with trial licence if you are not using it for commercial or profit purposes
  • Autodesk Inventor SDK developer tools installed that comes together with the software package

KNOWLEDGE BASE

Before I move on to the project I’d like to recommend two sources of knowledge about Inventor API. I already mentioned them in my previous post but to keep things organised I will do it again here.

  • Object Model Diagram – it is a PDF file that comes with the SDK developer tools and can be found in PublicDocuments/Autodesk/Inventor/SDK/DeveloperTools/Docs
  • this[2] repository on Git Hub. It contains thematically organised lessons on Inventor API with examples in C#

STARTING THE PROJECT

As mentioned before the templates are available for VS2015, so creating the project must be done in VS2015. All code written this series will be available on Git Hub. You will find a link at the end of this post.
Another thing that is important is to use correct version of .NET framework. I will be using Inventor2018 and it uses version 4.5. As I am aware most recent editions of Inventor uses 4.5 but if you want to be absolutely sure you can check that. To do that you need to go to your Inventor installation folder, then /Bin and open Inventor.exe.config file  in any text editor, then find <startup> tag section:

In the section above, the sku attribute defines version of the framework and in this case it is 4.5.
Having the project created you can save it, close and re-open in VS2017 if you prefer. Otherwise, you can continue in VS2015.
The last step would be to edit some values in AssemblyInfo.cs.

The project template is set up in a way that one the project is built all necessary files will be copied to appropriate location so the add-in will be visible in Inventor.
Having this done we almost can move on to modifying the application’s ribbon.

PROJECT REFERENCES

But before we start playing around with Inventor we need to add some references to the project. Right after project creation we only have references to autodesk.inventor.interop and System. We need bit more:

  • PresentationFramework – our UI will be build using WPF. You could use WinForms and I think that’s the preferred library, however I like WPF more. And that is the only reason for my decision.
  • System.Xaml – needed for WPF
  • stdole – that provides IPictureDisp interface that is going to be used for converting embedded icons to those usable with Inventor ribbons
  • System.Drawing – that provides Image abstract class and Icon class, needed for the same reason as above
  • System.Windows.Forms – that may seem suprising as I’ve already writtten that we’re going to use WPF. The reason behind the need of that reference is that AxHost base class to build our converter from Image objects to IPictureDisp usable with Inventor ribbons.

MODIFYING THE RIBBON

The application has several different ribbons. Which is used depends on what type of document is active and what environment is being used. To divide this series into episodes which are more or less equal length-wise I will just say now that the add-in will operate in drawing environment and will have two buttons: one to setup its preferences and the other one to run actions to be performed by the add-in.

First I will prepare two icon for our buttons. I downloaded some free icons from here. (I am absolutely talent-less if it comes to drawing). We need two size of each icon: 128×128@32bit and 16×16@32bit and they must be set as embedded resource. They will be stored in img folder in our project. So, to summarise: 4 files = 2 different icons x 2 different sizes.
Unfortunately, those icons cannot be used as they are. First, they must be converted to be of type IPictureDisp. To achieve that I’m going to use this[3] implementation (as proposed by Andrew Whitechapel at MSDN) of such converter:

As you can see our AxHostConverter class is an internal sub-class within our project main class StandardAddInServer. It won’t be used anywhere else so this approach is absolutely safe.
A method that creates instances of button definition as icons takes argument of type object, therefore they will be declared in StandardAddInServer class body as objects:

They will be in fact of type IPictureDisp in stdole namespace, but because of the fact that Inventor namespace also contains IPictureDisp type and avoid that confusion I will keep them as of type object. The process of retrieval from embedded resources and proper conversion will be performed by a private method getIcons() inside StandardAddInServer class:

So, that was the most confusing part. Now, it’s time start messing with the API. Adding our buttons to the application’s UI we need to start with defining some members in the class’ body:

The above fields will be initialised in another private method modifyRibbon(). The separate method is not needed however I like to have it separated just for a bit of clarity.
addInGuid string is copied value of Guid attribute from class signature. It will be later used to simplify a bit invocations of methods defining new buttons.

First two steps are easy, we just need to get some objects from currently running instance of Inventor, and that’s it.
Next step is to create command category for our add-in. It is done as in the code above, where arguments are as follow: strings for display name and internal name, and guid. Internal name is built as follows: “Autodesk:CmdCategory:our_custom_name“. This will add our category of commands that will be visible in UI customisation dialog:

Next, we need to access intended ribbon and one of its tabs. The ribbon we’re interested in is Drawing ribbon, the tab is Place Views.

As you can see they are accessible by their unique names and you must know them. They all can be found in mentioned earlier Git Hub repository here[4].

Next step – defining buttons:

It is achieved with use of ControlDefinitions and its AddButtonDefinition method. It takes several arguments (in respective order):

  • display name (string)
  • internal name (string) following scheme “Autodesk:command_category_name:button_name”
  • CommandTypesEnum – type of command, for UI elements it should be kQueryOnlyCmdType
  • add-in guid
  • description (string)
  • tool-tip (string)
  • standard icon (of type object, but it needs to be IPictureDisp)
  • large icon (of type object, but it needs to be IPictureDisp)
  • ButtonDisplayEnum – a way a button is displayed, in our case it is kAlwaysDisplayText

Once the button is defined we need to add action that will be performed when the button is clicked.

It the example above customAction method must return void and take one argument of NameValueMap which is set of name and value pair. It will be explained in one of later posts. For the time being, this method will only display a message box to demonstrate the buttons actually work.

The last step of defining a button is to add it to command category:

Now, we need to add panel to Place Views tab.

It is acheived using Add method in RibbonPanels collection in one of the ribbon tabs. It accepts arguments as follow:

  • display name (string)
  • internal name (string): “Autodesk:command_category_name:button_name
  • add-in guid

Now, we need to add our buttons to the created panel:

In the example above AddButton takes three arguments:

  • button definition
  • boolean – use large icon
  • boolean – display text

So, that’s it. The ribbon is modified. After changes described above it looks like that:

Nothing more to add today. Check the links below and stay tuned for the next part!
Cheers, Michal

GitHub repo: https://github.com/mickaj/AutoBreaker-Inventor

Sources:
[1] – https://www.autodesk.com/licensing/trial-license
[2] – https://github.com/ADN-DevTech/Inventor-Training-Material
[3] – https://blogs.msdn.microsoft.com/andreww/2007/07/30/converting-between-ipicturedisp-and-system-drawing-image/
[4] – https://github.com/ADN-DevTech/Inventor-Training-Material/blob/master/Module%2009%20-%20User%20Interface/RibbonNames.txt

Inventor API – Custom add-in Part #2
Inventor API – Custom add-in Part #3