LAB 3: Connect to an Inventor Session

advertisement
Autodesk® Inventor® API Lab for Power Users
Wayne Brill – Autodesk
Brian Ekins - Autodesk - Lab Assistant
Philippe Leefsma - Autodesk - Lab Assistant
Augusto Goncalves - Autodesk - Lab Assistant
CP3505-L
Are you an Autodesk Inventor power user with an interest in becoming even more
productive? Would you like to automate or extend the capabilities of Inventor, but are new to computer
programming? If so, this hands-on lab is designed for you. During the lab, you will create an Inventor
plug-in that will introduce you to the programming world. This lab will provide a learning path for Inventor
power users who know Autodesk Inventor but are absolutely new to programming and are thinking about
taking the plunge. In this lab, we will be working with Autodesk Inventor API in Microsoft® Visual Basic®
Express 2010.
Learning Objectives
At the end of this class, you will be able to:

Describe the basics of using SelectSet in the Inventor API

Describe the basics of using the Inventor API

Create code that runs when a button is clicked so that it accesses selected components in an
assembly

Use Visual Basic Express 2010
About the Speaker
Wayne has been a member of Autodesk Developer Technical Services supporting Autodesk
Developer Network members for 10 years. Wayne provides API support for AutoCAD®,
Autodesk® Inventor®, AutoCAD Mechanical, AutoCAD OEM, and RealDWG®.
wayne.brill@autodesk.com
Autodesk® Inventor® API Lab for Power Users
Note: This handout is the same for two 90 minute LAB sessions. (This session and
session CP2542-L)
Six lessons in this LAB:
LAB 1: The Basic Plug-in
LAB 2: Create a new Visual Basic Express Project
LAB 3: Connect to an Inventor Session
LAB 4: Add a User Interface and logic flow using “If Then” and “For Next”
LAB 5: Add attributes to selected components
LAB 6: Add more UI and call Subs with an argument
LAB 1: The Basic Plug-in
In this lesson, to help you get a quick start, you will begin by writing part of a VB.NET
application that uses the Autodesk Inventor API to hide selected components.
1. Open Visual Basic 2010 Express using the Windows Start menu, selecting All
Programs, and then Microsoft Visual Studio 2010 Express, and then the Microsoft
Visual Basic 2010 Express submenu-item. This launches the Visual Studio 2010
Express development environment.
2. Inside Visual Basic Express, on the File menu, click Open Project. Navigate to the
subfolder of the supporting material you downloaded with this guide called
‘lesson1_VisualExpress2010’ and open the VB.NET project contained within it by
selecting the project file ‘MyFirstInventorPlugin_Lesson1.vbproj’.
3. After you open the project you will see a form with one button (if you don’t see the Form,
click on Form1.vb in the Solution Explorer frame in the upper right hand side). Right click
on Form1 in the Solution Explorer and select View Code or just double click on the
Form.
2
Autodesk® Inventor® API Lab for Power Users
4. In the code window, type the code below into the Sub Button1_Click. (This is what runs
when the button is clicked). You may need to scroll down towards the bottom of the
code to find the place to add the below code. You can just copy and paste the code, but
we highly recommend you take the time to type it in as you’ll start to learn how VB
Express helps you find and enter code using “IntelliSense” (as you start typing, use Tab
to select the code snippets that build up various lines of code). At this stage you
probably won’t understand what most of the code is doing – but this will give you the
feeling of what it’s like to build a VB .NET application.
3
Autodesk® Inventor® API Lab for Power Users
Type this following code:
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
If _invApp.ActiveDocument.DocumentType <> _
DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("Need to have an Assembly document active")
Return
End If
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
If asmDoc.SelectSet.Count = 0 Then
MsgBox("Need to select a Part or Sub Assembly")
Return
End If
4
Autodesk® Inventor® API Lab for Power Users
Dim selSet As SelectSet
selSet = asmDoc.SelectSet
Try
Dim compOcc As ComponentOccurrence
Dim obj As Object
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
compOcc.Visible = False
Next
Catch ex As Exception
MsgBox("Is the selected item a Component?")
MsgBox(ex.ToString())
Return
End Try
5. On the File menu, click Save All.
Don’t worry about the specifics of what this code is actually doing, for now: we’ll cover that
within the next few lessons.
That’s it! You have just written your first plug-in for Inventor. Let’s run the plug-in to see what it
does.
Running the code
1. Start Autodesk Inventor. (Note: When the project is run it will start a new session of
Inventor if one is not already running.)
2. Within Inventor make sure you have an assembly active. There are several types of
document that can be created or worked with inside Inventor. The most commonly used
document types are Part (.ipt), Assembly (.iam) and Drawing (.idw). Open a new
assembly and place some parts using the standard Inventor user-interface.
5
Autodesk® Inventor® API Lab for Power Users
3. To make Visual Basic Express execute the code you have entered, select Start
Debugging on the Debug menu (you can use the F5 key or click on the filled green
arrow – which looks like a “play” button – on the Debugging toolbar). This will cause our
form to be displayed. You may need to minimize VB Express to see both the form and
Inventor.
6
Autodesk® Inventor® API Lab for Power Users
4. Select one or more (by using the Ctrl key) components in the assembly and then click
“Button1” on the form to execute our code and hide the selected components.
7
Autodesk® Inventor® API Lab for Power Users
5. To re-display the invisible components use the Inventor Assembly browser (you can
identify them via their component icons which should now be grayed out). In the
browser, right-click on the invisible components and pick Visibility, making them visible
once again.
8
Autodesk® Inventor® API Lab for Power Users
End of LAB 1. We will be reviewing the code in detail in Lesson 3.
Link to LAB 1 Discussion
LAB 2 - Create a new Visual Basic Express Project
In this section, we will create a blank project similar to the one we were provided with in Lesson
1. This project will be the starting point for Lesson 3.
1.
Close the project from Lesson1, if it is still open in Visual Basic Express, and then on
the File menu, click New Project.
This will open up a new dialog called New Project in which we have the option to select
the template that will be used to create the plugin application.
9
Autodesk® Inventor® API Lab for Power Users
New Project dialog
As we are working with Visual Basic Express, our installed templates are under the
Visual Basic category.
In the center of the dialog, we can see various application templates that are available to
us, the choice of which depends on the type of application we wish to create. As we’re
creating a simple, standalone EXE with a dialog-based user interface, select the
“Windows Forms Application” template.
We now need to select a name for our project. Enter “MyFirstInventorPlug-in” in the box
near the bottom of the New Project dialog and select OK: The basic solution containing
a form should now be created and loaded in the Visual Basic Express editor.
The project contains a blank form named Form1.vb. Forms have Design and Code
views: we can switch between the two views by right-clicking on Form1.vb in the
Solution Explorer and selecting View Code or View Designer. By default, commonly
used .NET components get added as “references” to our project. You can see these by
10
Autodesk® Inventor® API Lab for Power Users
right-clicking the project in the Solution Explorer and selecting Properties. In the
Properties window select References.
References in the Properties Window
2. So far we have created a blank “Windows Forms Application” project using Visual Basic
Express.
In order to create a plug-in for Inventor, we will need to make use of its API. To add the
Inventor API to the components that can be used from our project, we need to add a
reference to the API DLL located in <Inventor Product Installation folder>/Bin/Public
Assemblies>. This folder contains one DLL that we need to add to project:
Autodesk.Inventor.Interop.dll.
In the Solution Explorer, right-click the project and choose Add Reference. Click the
Browse tab in the Add Reference dialog and navigate to a location such as this
beneath the installed location of Inventor on your system: “C:\Program
11
Autodesk® Inventor® API Lab for Power Users
Files\Autodesk\Inventor 2012\Bin\Public Assemblies”. Select
Autodesk.Inventor.Interop.dll and then OK.
Referencing the Inventor API by adding a reference to the Interop.dll
The Inventor API has now been referenced into our project.
Before proceeding further, let’s use the Object Browser in Visual Basic Express to take a
quick look at the contents of this DLL: objects representing Inventor's application,
documents, elements and parameters.
To display the Object Browser, either use the Window menu and select Object
Browser or use the function key F2.
12
Autodesk® Inventor® API Lab for Power Users
Object Browser with the ActiveDocument property of the Inventor.Application selected
3. We’re now ready to use the Inventor API by entering code in Visual Basic Express. In
other words, to provide instructions for Inventor to perform certain tasks.
While developing code, it’s a good idea to build the solution, from time to time, to check
whether errors have been introduced in the code. The code doesn’t necessarily have to
be complete or functional for the build process to provide useful information. This
approach can help avoid potentially lengthy debugging once the code is complete, and
has the side benefit of automatically saving any edited source files before the build
starts.
To build a solution inside Visual Basic Express, select Build <ProjectName> from the
Debug pull-down menu.
13
Autodesk® Inventor® API Lab for Power Users
Build the Application
If the build was successful, you will see Build Succeeded in the status bar at the
bottom-left corner of the Visual Basic Express interface.
4. Save the Project. To do this, on the File Menu select Save All.
End of LAB 2
Link to Lab 2 Discussion
LAB 3: Connect to an Inventor Session
In this lesson, we will take a closer look at the Inventor API. In Lesson 1, we typed code (or
instructions) into a code window associated with a Form and saw how it changed the visibility of
14
Autodesk® Inventor® API Lab for Power Users
components in an assembly. In Lesson 2 we created a Windows Form application and
referenced the Inventor API from it. In this lesson we will continue working on the project we
created in Lesson 2, extending it to use the Inventor API to connect to or start a session of
Inventor while taking a close look at how the code actually works.
Add code to the project we created in lesson 2
In Lesson 2 we created a project and it referenced the Inventor API via
Autodesk.Inventor.Interop.dll. Adding this reference to the Inventor API allows us to start
using it in our project. In the following steps we will access the top level object in the API, the
Inventor.Application object.
1. Open the project you created in Lesson 2 and add the following lines of code to the
Form1.vb code window (above “Public Class Form1”). You can display the code window
by right-clicking on Form1.vb in the Solution Explorer and selecting View Code. To make
room for this place the cursor to the left of “Public Class” and press the Enter key a few
times to add some blank lines at the top of the code window. Add these Imports
statements to the top of the top of the code widow.
Imports System
Imports System.Type
Imports System.Activator
Imports System.Runtime.InteropServices
Imports Inventor
Keywords, such as “Imports” in the above code, are core to the VB.NET language and
are displayed by Visual Basic Express in blue. They are used to help formulate our
instructions for the computer. The “Imports” keyword has a particular role: it brings in the
types from a specified namespace into the current code file’s useable types, which stops
us from having to type complete namespaces in every line of code.
What is a namespace?
When we are working with different components and APIs in our Visual Basic project, it’s
common to find multiple classes with the same name. To avoid this conflict, we use the
concept of namespaces. A namespace is a way to organize classes by grouping them
together in a logical way and to help us identity the class we wish to use.
To give you an example, let’s say there are two boys named John living in the same
neighborhood. One possible way of uniquely identifying one of the Johns might be to use
his last name. But if both Johns have the same last name, such as Smith, this is no
longer enough to uniquely identify them. We now need to use an additional identifier,
such as the school at which they study. If this was put into VB.NET syntax, we might use
SchoolA.Smith.John for one and SchoolB.Smith.John for the other.
15
Autodesk® Inventor® API Lab for Power Users
After adding the Import statements several namespaces are now available including the
Inventor namespace. The Inventor namespace is available for import because we
referenced the Autodesk.Inventor.Interop.dll.
The following code in Form1 defines a class.
Public Class Form1
This is a standard declaration of a class and was added when the project was created by
the Visual Studio Wizard. The public keyword states that this class is to be considered
public and therefore accessible from other classes in this assembly (and even in other
projects using our application as a component). The name Form1 is the name of the
class.
2. Let’s now add a couple of variables after the class declaration. A variable is a named
location where we place some data – usually of a specific type. Variables help us keep
track of what’s going on in our application, as well as providing access to commonly
used objects.
We’ll start by creating a variable named _invApp. We can choose whatever names we
want for our variables, as long as they are not reserved words (such as the “Imports”
keyword) : we might also have chosen a more verbose name such as
“theInventorApplication” for this variable. The underscore prefixing the variable name is
a convention that denotes a class variable: one that can be accessed from all the Sub
routines and Functions in the class.
To declare the variable, we use the Dim keyword, followed by the variable name
(_invApp). We specify the type of this variable after the “As” keyword
(Inventor.Application).
After declaring our _invApp variable – which will be used to provide quick access to the
Inventor Application object – we’ll declare another variable, named _started, as a
Boolean (which means it can either be True or False). Declaring variables reserves an
area of memory to be used to store our data: the amount of memory depends on the
size of the class being used.
Note: Even though we added the Imports directive we still need to use
“Inventor.Application”: using just “Application” would be ambiguous, as the
System.Windows.Forms namespace also contains an Application type.
Public Class Form1
Dim _invApp As Inventor.Application
Dim _started As Boolean = False
16
Autodesk® Inventor® API Lab for Power Users
3. We are now going to create a Sub(-routine). A Sub is a block of code that can be
executed under circumstances we decide: we might want it to be called when a
particular button is clicked in a dialog, for instance.
We will use the keywords “Public” and “Sub” - to denote a publically callable sub-routine
– and then the name of the Sub. At the end of the Sub we use the keywords “End Sub”.
It’s also possible to add a Sub using pull-down menus in VB.NET code windows, instead
of typing the code in. The Subs we can add using the VB.NET dropdowns are special
default Subs associated with the class for which we’re entering code – in our case a
Form class. One of these is the Sub New. We want to implement this Sub because it is
called automatically when our Form is created (i.e. when our application is started).
During this Sub, we will connect to an existing Inventor session or start a new one.
A Sub must be contained within a Class: let’s go ahead and add the “New” Sub to our
Form1 class. We’ll first make the code window associated with Form1 active – by rightclicking on Form1.vb in the Solution Explorer and select “View Code” – and then select
Form1 in the dropdown on the left and then select “New” in the dropdown on the right.
17
Autodesk® Inventor® API Lab for Power Users
Adding the Sub New
The “Sub New” procedure should now have been added to the Form1 class: it’s this Sub
that gets called when the Windows Form Application is started, as the application’s
default behavior is to create an object of type Form1 and display it (this can be controlled
via our project’s properties).
Our application needs a session of Inventor to work: while we could choose to connect
to one at different times (each time it’s needed, for instance), the approach we’re going
to use in this application is to connect to an Inventor session when our application is
started.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
4. Connect to or start an Inventor session in Sub New. Type this code after the
InitializeComponent() call in this Sub. The call to InitializeComponent() was added
automatically in the default implementation of Sub New. InitializeComponent helps set
up the behavior of a Form. If you’re interested in seeing the code it contains, right-click
on the name of the Sub and select “Go To Definition”. Just be sure not to change the
code in the editor window: InitializeComponent’s code will be modified automatically
when we add controls to our form, but you should not have to edit it manually.
' Add any initialization after the InitializeComponent() call.
Try
_invApp = Marshal.GetActiveObject("Inventor.Application")
Catch ex As Exception
Try
Dim invAppType As Type = _
GetTypeFromProgID("Inventor.Application")
_invApp = CreateInstance(invAppType)
_invApp.Visible = True
'Note: if you shut down the Inventor session that was started
'this(way) there is still an Inventor.exe running. We will use
'this Boolean to test whether or not the Inventor App will
'need to be shut down.
_started = True
18
Autodesk® Inventor® API Lab for Power Users
Catch ex2 As Exception
MsgBox(ex2.ToString())
MsgBox("Unable to get or start Inventor")
End Try
End Try
Notice how the equals sign is used to assign an object to the _invApp variable.
_invApp = Marshal.GetActiveObject("Inventor.Application")
After this line has run the variable _invApp contains an object of type
Inventor.Application that we can use. Also notice that the Dim statements we added for
the Inventor Application and the Boolean are outside of the Sub itself, making them
global. This means that we can access these variables from any Sub in the class. We do
this because we want to use the variables in the FormClosed Sub event that we will add
in the next step.
The GetActiveObject function helps us find a running session of Inventor. The string of
characters (known as a ProgID) that we pass into the function, “Inventor.Application”,
tells GetActiveObject the type of object we’re trying to find. We surround the call to
GetActiveObject with a Try-Catch block, which means our code stays on the lookout for
exceptions (a way or returning errors from .NET code). We do this as we know
GetActiveObject will “throw” an exception if it doesn’t find a running Inventor session. If
this happens our Catch statement gets executed, which gives us the chance to try to
launch a new Inventor session.
5. Respond to the FormClosed event. An event is something we get notified about and can
respond to in our application’s code. During our FormClosed event we’re told that Form1
is closing, and that we should clean up after it. If we launched Inventor in our Sub New,
above, we ought to close the session we started. It’s for this reason we set our Boolean
variable – _started – to True if we had to start a new Inventor session: we can check this
variable as the form is closing, and close the Inventor session from there. To add the
FormClosed event Sub select “(Form1 Events)” in the dropdown on the left and then
select “FormClosed” in the dropdown on the right.
19
Autodesk® Inventor® API Lab for Power Users
Adding the Event FormClosed
The “Form1_FormClosed” event handler is added to the Form1 class. This Sub will be
run when the Form is closed.
Private Sub Form1_FormClosed(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
End Sub
20
Autodesk® Inventor® API Lab for Power Users
6. Type this code inside the Form1_FormClosed Sub.
' This will shut down the Inventor session started when the form was started
If _started Then
_invApp.Quit()
End If
_invApp = Nothing
Here we Quit the Inventor session if _started is set to True (i.e. it was our code that
started the session, as one was not already running).
7. Run the Windows Form Application by hitting F5. If you do not have a session of
Inventor running you should see one start.
End of Lesson 3
Here is the complete code from the Code Window for Form1.vb at the end of Lesson 3
(modified slightly using the underscore chatacter (‘_’) to split long lines for readability).
Imports System
Imports System.Type
Imports System.Activator
Imports System.Runtime.InteropServices
Imports Inventor
Public Class Form1
Dim _invApp As Inventor.Application
Dim _started As Boolean = False
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Try
_invApp = Marshal.GetActiveObject("Inventor.Application")
Catch ex As Exception
Try
Dim invAppType As Type = _
GetTypeFromProgID("Inventor.Application")
_invApp = CreateInstance(invAppType)
_invApp.Visible = True
'Note: if you shut down the Inventor session that was started
'this(way) there is still an Inventor.exe running. We will use
21
Autodesk® Inventor® API Lab for Power Users
'this Boolean to test whether or not the Inventor App will
'need to be shut down.
_started = True
Catch ex2 As Exception
MsgBox(ex2.ToString())
MsgBox("Unable to get or start Inventor")
End Try
End Try
End Sub
Private Sub Form1_FormClosed( _
ByVal sender As Object, ByVal e As FormClosedEventArgs) _
Handles Me.FormClosed
If _started Then
_invApp.Quit()
End If
_invApp = Nothing
End Sub
End Class
End of LAB 3
Link to LAB 3 Discussion
LAB 4: Add a Button and logic flow using “If Then” and “For Next”
In previous lessons we learned how to create a basic Windows Forms application and connect it
to a session of Inventor. In this lesson we will add a button to the form and have it hide selected
components, using the code we entered in lesson 1. We will now spend some time to
understand how the code functions.
We talked about how a program is a sequence of instructions telling the computer how to do
something. Many programs will also need some type of User Interface, for the end user to
interact with your new functionality. The Visual Basic Express toolbox makes it very easy to add
user interface elements, such as buttons, to enable this interaction.
1. In the Solution Explorer right click on Form1.vb and select View Designer (or use
Shift+F7).
22
Autodesk® Inventor® API Lab for Power Users
The Designer is where you can create the user Interface. In this example we are just going to add one button.
2. From the View menu select Other Windows and then select Toolbox (or use
Ctrl+Alt+X).
23
Autodesk® Inventor® API Lab for Power Users
3. On the Toolbox, select Button and draw a button on the Form by clicking and dragging
to specify the position and size of the button.
24
Autodesk® Inventor® API Lab for Power Users
4. We now need to assign behavior to our button: code that gets executed when someone
clicks on it. To do this we need to get to the code window for the form and get to the
code that will run when the button is clicked. To do this, right click on Form1.vb and
select View Code (or use F7). In the code window select the drop down on the left and
select Button1.
25
Autodesk® Inventor® API Lab for Power Users
In the right dropdown, select the Click event (the icon used for events is a lightning bolt).
26
Autodesk® Inventor® API Lab for Power Users
This results in the Sub Button1_Click event hander being added to the code window for
the Form and assigned to the button.
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Button1.Click
End Sub
5. Add the following If statement to the Sub Button1_Click.
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
6. Add the following to the Sub Button1_Click. (After the “If Then” statement in step 5).
If _invApp.ActiveDocument.DocumentType <>
DocumentTypeEnum.kAssemblyDocumentObject Then
27
Autodesk® Inventor® API Lab for Power Users
MsgBox("Need to have an Assembly document active")
Return
End If
These two steps make sure a) at least one document is open and b) the active
document is an assembly (our code is going to hide assembly components, after all). If a
different type of document is active then we ask the user to make an assembly active
and then Return from our Sub without executing any more code.
7. Add the following to the Sub Button1_Click after the “If Then” statement in step 6.
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
If asmDoc.SelectSet.Count = 0 Then
MsgBox("Need to select a Part or Sub Assembly")
Return
End If
8. Add the following to the Sub Button1_Click after the “If Then” statement in step 7.
Dim selSet As SelectSet
selSet = asmDoc.SelectSet
Try
Dim compOcc As ComponentOccurrence
Dim obj As Object
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
compOcc.Visible = False
Next
Catch ex As Exception
MsgBox("Is the selected item a Component?")
MsgBox(ex.ToString())
Return
End Try
This completes the code for this lesson. The code now checks to see if an assembly is
active and some entities are selected. It then prints out the name of the component (an
occurrence) and makes it invisible. If the selected entity is not a component then an error
will occur and the catch block will handle it.
28
Autodesk® Inventor® API Lab for Power Users
Running the Code
1. You should now be able to run the project (by selecting Start Debugging from the Debug
menu), which leads to the application starting and the form being displayed. Once you’ve
done this, switch to the Inventor session and select some components in an assembly,
which will take the focus away from our application. Bring the application back in front of
the Inventor session and click the button to run our code. The selected components in
Inventor should now be hidden and – in the browser - display for the components will be
unchecked.
End of LAB 4
Link to LAB 4 Discussion
LAB 5: Add attributes to selected components
In Lesson 4 we created a button on the form to hide selected components in the active Inventor
assembly. Along the way we learned how to use Inventor objects along with how to control code
execution using “If Then” and “For Next” statements. Instead of directly hiding the selected
components, we’ll now modify the code to “tag” our components for later hiding or display.
Attaching attributes provided by the Inventor API will allow us to identify and perform different
operations on our tagged components.
1. Open the project from the previous lesson and open the Code Window for Form1. Or if
the plug-in is already running stop it by selecting Stop Debugging on the Debug Menu in
VB Express. You can also close the application window of the plug-in by clicking the x in
the upper right corner. If the Designer is active, right click on Form1.vb in the Solution
Explorer and select “View Code”.
In the “For Next” loop within the Button1_Click event we are currently hiding each of the
selected components by setting its Visible property to False. Comment out the line of
code that sets the Visible property by inserting an apostrophe/single quote (') at the
beginning of the line.
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
'compOcc.Visible = False
Next
2. There are three Inventor API classes that are used to add an Attribute to entities, one of
which is the AttributeSets collection. Add a line of code which uses the Dim statement to
29
Autodesk® Inventor® API Lab for Power Users
declare a variable named “attbSets” of type AttributSets. We’ll assign this variable
directly to contain the value of our component occurrence’s AttributeSets property.
Dim attbSets As AttributeSets = compOcc.AttributeSets
3. We only want to add our attribute once to each tagged component. We can use the
NameIsUsed Method of the AttributeSets collection to check whether an AttributeSet of
a particular name has already been created. Add the below code below just after the
code we added in step 2.
' Add the attributes to the ComponentOccurrence
If Not attbSets.NameIsUsed("myPartGroup") Then
End If
4. We’ll now create and assign a variable named “attbSet” of type AttributeSet, once again
using the combination of the Dim statement and the equals sign. The string
“myPartGroup” specifies the name of the AttributeSet in the AttributeSets collection .
Add this in the body of the “If Then” statement we created in step 3.
Dim attbSet As AttributeSet = attbSets.Add("myPartGroup")
5. The third class we use to add the attribute is the Attribute itself. We use the Add method
on our AttributeSet to create an Attribute object and add it to the set. We can assign the
results of the Add method directly to a variable named “attb” of type Inventor.Attribute.
You may remember we have to specify the Inventor namespace explicitly to prevent a
name clash with another Attribute class.
Dim attb As Inventor.Attribute = _
attbSet.Add( _
"PartGroup1", ValueTypeEnum.kStringType, "Group1")
6. Build the project using the Build item on the Debug menu. This will let you know if the
project contains any errors: it’s good practice to build regularly both to fix issues as they
get introduced and to save your work.
Use the Watch window
Let’s now take a look at how we can debug our code using Visual Basic Express.
1.
Place a break point on the line that adds the attribute. We can do this by putting the
cursor on the line and then using the F9 key. Another way is to click on the bar to the left
of the code window:
30
Autodesk® Inventor® API Lab for Power Users
2.
Run the project by selecting “Start Debugging” from the Debug menu. (Or use F5)
31
Autodesk® Inventor® API Lab for Power Users
3.
In the Inventor session select a couple of components and then click the button on our
form. Visual Basic Express – and the code window showing this code – should become
active when the line that adds the attribute is about to be executed. The execution will
stop here, waiting for you to perform some action to advance it.
32
Autodesk® Inventor® API Lab for Power Users
4.
When execution has been paused via a breakpoint, we can examine the values of the
variables in our code using the Watch window. We do this by right clicking on the
variable name and selecting “Add Watch”.
33
Autodesk® Inventor® API Lab for Power Users
We can see in the Watch window that the values for the AttributeSet’s properties include the
name we assigned it during the previous line of code.
34
Autodesk® Inventor® API Lab for Power Users
To make the code execution proceed, use the Debug pulldown menu and select Continue (or
Hit F5).
35
Autodesk® Inventor® API Lab for Power Users
5.
Stop debugging by closing the form or select “Stop Debugging” on the Debug menu.
Add another button to the form and use the AttributeManager to get the
components
1. Let’s now add another button to the form that will make use of the attributes we’ve used
to tag our components. Display the Designer by right-clicking on Form1.vb and select
“View Designer” (or use Shift+F7). Display the Toolbox using the View Menu -> Other
Windows then ToolBox (or use Ctrl+Alt+X). Click and drag to place the button.
36
Autodesk® Inventor® API Lab for Power Users
2. By default the text displayed on the buttons are “Button1”, “Button2” and so on. In most
cases we will want to have more descriptive names for them. We can do this by using
the “Properties” Window. We can display the Properties window by right clicking on the
button and selecting “Properties”. Change the Text property of the button to “Hide or
Show Group”: this changes the text shown inside the button but does not change the
internal name of the button.
37
Autodesk® Inventor® API Lab for Power Users
3. Using the same approach, change the text on Button1 to “Add to group”.
4. Make the code window active. Double-click on the button in the Designer to switch to
the code window and create the click event handler. In Lesson 4 we used drop downs
from the code window to add the Sub Button1_Click event handler.
5. When the user clicks on Button2 we want to get the AttributeManager from the active
document after making sure the active document is an assembly. We already have
some code that does this in the Button1_Click Sub. Copy this code into the
Button2_Click Sub.
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
If _invApp.ActiveDocument.DocumentType <> _
DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("Need to have an Assembly document active")
38
Autodesk® Inventor® API Lab for Power Users
Return
End If
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
6. We will now use the AttributeManager to find the various objects tagged with our
attribute. To do so add these lines of code after the code we added in step 5.
Try
Dim attbMan As AttributeManager = asmDoc.AttributeManager
Dim objsCol As ObjectCollection
objsCol = _
attbMan.FindObjects("myPartGroup", "PartGroup1", "Group1")
Catch ex As Exception
MsgBox("Problem hiding component")
End Try
7. The components that were tagged by the code behind Button1 will be contained in the
ObjectCollection after the call to FindObjects. We’ll now go through each of the items in
this collection and “toggle” their visibility (setting the visible ones to be invisible and the
invisible ones to be visible). Do so by adding the below code between the call to
FindObjects and the Catch statement added in step 6.
Dim compOcc As ComponentOccurrence
For Each obj As Object In objsCol
compOcc = obj
' Toggle the visibility of the Component Occurrence
compOcc.Visible = Not compOcc.Visible
Next
8. Build the project and fix any errors that get reported. You can test (and, if necessary,
debug) the project by using the Debug pulldown menu and selecting Start Debugging (or
use F5). Select a couple of components and click Button1 to add the attribute. When
you click Button2 the display of the components should toggle between visible and
invisible.
End of LAB 5
Link to LAB 5 Discussion
39
Autodesk® Inventor® API Lab for Power Users
LAB 6: Add More UI and call Subs with an argument
In lesson 5 we used attributes to tag Inventor components. We then used those attributes to
select the components and hide or display them. In this lesson, instead of toggling the display of
the components, we will add an additional button to provide the user with the direct capability to
either show or hide them. We will also add two more buttons, one to remove our attribute tag
from the selected components and one to remove the attribute from all components. We will
make our code easier to write and to maintain by creating procedures that are called when the
button is clicked. We will pass a Boolean argument to these procedures, allowing the same
procedure to be used in slightly different contexts.
1. Open the project from lesson 5 and display the Designer for Form1. If the code window
is active right-click on Form1.vb in the Solution Explorer and select View Designer. Add
three buttons so that the form looks like the screenshot below. Change the text for the
button (Button2) we added in lesson 4 to Hide group. We will use another button to
show the components in the group. In previous lessons we covered how to add buttons
to the form and change the text for the buttons. (Show the toolbox, drag a button to
place it on the form.) Make the text on the three new buttons:
Show group
Remove from group
Remove all from group
40
Autodesk® Inventor® API Lab for Power Users
2. Type the following in the code window for Form1, before the End Class keyword and
after the last End Sub.
Public Sub HideOrShowGroup(ByVal hide As Boolean)
End Sub
3. Cut the code from the Button2_Click Sub and paste it into the Sub we created in step 2.
Here is the code we need to move into the HideOrShowGroup Sub:
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
41
Autodesk® Inventor® API Lab for Power Users
If _invApp.ActiveDocument.DocumentType <> _
DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("Need to have an Assembly document active")
Return
End If
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
Try
Dim attbMan As AttributeManager = asmDoc.AttributeManager
Dim objsCol As ObjectCollection
objsCol = _
attbMan.FindObjects("myPartGroup", "PartGroup1", "Group1")
Dim compOcc As ComponentOccurrence
For Each obj As Object In objsCol
compOcc = obj
' Toggle the visibility of the Component Occurrence
compOcc.Visible = Not compOcc.Visible
Next
Catch ex As Exception
MsgBox("Problem hiding component")
End Try
4. Change the contents of the For Each loop so that it only makes the Visible property of
the component equal to the Boolean that is passed in. (hide).
For Each obj As Object In objsCol
compOcc = obj
compOcc.Visible = hide
Next
5. Add the following to the now-empty Button2_Click Sub. When this button is clicked it will
run the HideOrShowGroup Sub passing in False.
HideOrShowGroup(False)
6. Add this to the Button3_Click Sub. (The Button with the text “Show group.) When this
button is clicked it will run the HideOrShowGroup Sub passing in True.
HideOrShowGroup(True)
42
Autodesk® Inventor® API Lab for Power Users
7. Type the following into the code window for Form1, before the End Class keyword and
after the last End Sub. This will create another Sub that we can call, passing in a
Boolean variable.
Public Sub AddOrRemoveFromGroup(ByVal add As Boolean)
End Sub
8. Cut and paste this code from the Button1_Click Sub into the AddOrRemoveFromGroup
Sub that we added in Step 7.
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
If _invApp.ActiveDocument.DocumentType <> _
DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("Need to have an Assembly document active")
Return
End If
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
If asmDoc.SelectSet.Count = 0 Then
MsgBox("Need to select a Part or Sub Assembly")
Return
End If
Dim selSet As SelectSet
selSet = asmDoc.SelectSet
Try
Dim compOcc As ComponentOccurrence
Dim obj As Object
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
'compOcc.Visible = False
Dim attbSets As AttributeSets = compOcc.AttributeSets
' Add the attributes to the ComponentOccurrence
If Not attbSets.NameIsUsed("myPartGroup") Then
43
Autodesk® Inventor® API Lab for Power Users
Dim attbSet As AttributeSet = attbSets.Add("myPartGroup")
Dim attb As Inventor.Attribute = _
attbSet.Add( _
"PartGroup1", ValueTypeEnum.kStringType, "Group1")
End If
Next
Catch ex As Exception
MsgBox("Is the selected item a Component?")
MsgBox(ex.ToString())
Return
End Try
9.
Add an If Then Else statement and test the add Boolean variable that is passed into the
Sub. Add the If Then statement right after the code where the attbSets is created.
If add Then
Put the Else statement right after the End If that is used for the If statement that uses
the NameIsUsed property. “If Not attbSets.NameIsUsed…” and right before the Next
keyword. Add an End If after the Else keyword.
' Add the attributes to the ComponentOccurrence
If Not attbSets.NameIsUsed("myPartGroup") Then
Dim attbSet As AttributeSet = attbSets.Add("myPartGroup")
Dim attb As Inventor.Attribute = _
attbSet.Add( _
"PartGroup1", ValueTypeEnum.kStringType, "Group1")
End If
Else
End If
Next
10. Add a nested If Then statement that uses the NameIsUsed property to check if the
name of the attribute myPartGroup is used. (Put it between the Else statement and the
44
Autodesk® Inventor® API Lab for Power Users
End If added in the previous step.). If it has been used, get the AttributeSet by passing
its name (“myPartGroup”) to the Item method of the attbSets object, and then call Delete
on it to delete the AttributeSet from the component.
' Delete the attributes from the ComponentOccurrence
If attbSets.NameIsUsed("myPartGroup") Then
attbSets.Item("myPartGroup").Delete()
End If
11. Call the AddOrRemoveFromGroup Sub from the now-empty Button1_Click passing True
as the argument.
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Button1.Click
AddOrRemoveFromGroup(True)
End Sub
12. Call the AddOrRemoveFromGroup Sub from the Button4_Click Sub, passing False as
the argument. (The button with the text “Remove selected components from group”.) We
can double-click on the button in the Designer view to display the code window and add
the Sub Button4_Click.
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button4.Click
AddOrRemoveFromGroup(False)
End Sub
13. We have one more button that we need to complete. This is the Button with the text
“Remove all components from group”. Double click on this button (Button5) in the
Designer to open the code window and create the Button5_Click Sub. Copy and paste
code from the other functions to do what we need. Here is the completed Button5_Click
Sub. Notice how the code we added for our other button is being reused.
Private Sub Button5_Click( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button5.Click
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
If _invApp.ActiveDocument.DocumentType <> _
DocumentTypeEnum.kAssemblyDocumentObject Then
45
Autodesk® Inventor® API Lab for Power Users
MsgBox("Need to have an Assembly document active")
Return
End If
Dim asmDoc As AssemblyDocument = _invApp.ActiveDocument
' Get the attribute manager for the document
Dim attbMan As AttributeManager = asmDoc.AttributeManager
' Find the objects with the attributes
Dim objCol As ObjectCollection
objCol = _
attbMan.FindObjects("myPartGroup", "PartGroup1", "Group1")
Dim attbSets As AttributeSets
' Delete the attribute from the ComponentOccurrence
For Each obj As Object In objCol
attbSets = obj.AttributeSets
attbSets.Item("myPartGroup").Delete()
' Make the ComponentOccurrence visible
obj.Visible = True
Next
End Sub
End of LAB 6
Link to LAB 6 Discussion
Congratulations! You have now completed this training
More Discussion on the Labs:
Return to LAB 1
LAB 1
Let’s take a step back and review some basics concepts about programming and the benefits it
can bring to your day-to-day work.
Introduction to Programming
More than half of the code that you entered into the project which hides the selected
components is doing error checking. The code that actually does the work can be narrowed
down to these lines of code:
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
46
Autodesk® Inventor® API Lab for Power Users
Dim selSet As SelectSet
selSet = asmDoc.SelectSet
Dim compOcc As ComponentOccurrence
Dim obj As Object
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
compOcc.Visible = False
Next
As we can see a small amount of code can go a long way to simplify working with Inventor.
Software programming allows you to capture the logic of a particular task once and then reap
the benefits over and over again, every time you (or others) want to perform that task.
What is Programming?
A simple answer to this question is: Computer programming is the process of creating a
sequence of instructions to tell the computer to do something. We will look at our program as a
sequence of instructions. During the course of the upcoming lessons, we will look at the various
lines and blocks of code and look at them all in the context of being instructions for a computer.
If we were to explain what computers are to a young child, we might say: a computer is
essentially a tool which follows instructions we provide. Programming is one way of giving
instructions to the computer. Internally, a computer sees these instructions encoded as a series
of numbers (also called machine code). The human-readable instructions we saw at the
beginning of the lesson are called source code and the computer converts these instructions to
machine code which it can then execute. A sequence of such instructions (or code), written to
perform a specific task, is called a program and a collection of such programs and related data
is called a software. Autodesk Inventor is one such software product.
Source code can be written in different languages, just as we humans use different languages
to communicate between ourselves. The development language we will be using in this guide is
called Visual Basic.NET (VB.NET).
What is an API?
API is the acronym for Application Programming Interface: the way a software programmer can
communicate with a software product. For instance, the Inventor API is the way programmers
can work with Inventor, and establishes what functionality a software programmer can use in
Inventor. An API such as Inventor’s allows you to write instructions for Inventor to execute one
after the other.
47
Autodesk® Inventor® API Lab for Power Users
Putting this slightly differently: commercial software companies, such as Autodesk, often
distribute a set of libraries that you can use in your own program to interact with a particular
software product, such as Autodesk Inventor, and extend its functionality. This set of libraries is
known as the software product’s API. In other words, what functionality has been made
available for you to manipulate through programming.
The type of program you write to interact with a software product and extend its functionality will
depend upon how the API has been designed and what has been exposed (through APIs) for
you to work with.
What is a Plug-in?
A software plug-in is a type of program module (or file) that adds functionality to a software
product, usually in the form of a command automating a task or some customization of the
product’s behavior. When we talk about a plug-in for Inventor – and you will also hear the term
AddIn used for this product – we mean a module containing code that makes use of the Inventor
API and connects to Inventor when your plug-in runs that then changes the behavior of Inventor
under certain conditions, such as when a particular command is executed by you. An Inventor
AddIn would also be considered a plug-in. An AddIn is a special kind of Plug-in that
automatically loads when Inventor is started, has high performance and appears to the user to
be part of Inventor.
LAB 2 Discussion
Return to LAB 2
48
Autodesk® Inventor® API Lab for Power Users
A quick recap: in this lesson we took a brief look at what happens when we build a project, as
well as some background information on VB.NET and Visual Basic Express. We then spent
some time creating a brand new Windows Forms Application project in Visual Basic Express,
adding the required project reference for it to be able to use the Inventor API.
In the previous lesson, we saw how you can increase productivity in Inventor by implementing a
plugin built from a small amount of VB.NET code. We then defined some core concepts/terms:
programming, API and plugin.
You will probably have heard the terms COM and .NET with reference to programming with the
Inventor API. Both COM and .NET are technologies that enable communication between
software: we won’t go into details about either, at this stage, but if you are interested in learning
more, you will find information in the Additional Topics section here.
We will now look more closely at what happened when we executed the code in the previous
lesson.
What does it mean to “build” code?
The code that we typed in to Visual Basic Express in the previous lesson was a set of humanreadable instructions (source code) that needed to be converted into code that could be
understood and executed by the computer. The “build” we performed did just that: it packaged
up the resulting executable code inside a standard Windows EXE file. It’s also possible to create
a DLL that can be loaded into Inventor, but that’s a more advanced topic not covered by this
guide. The Additional Topics section also covers this process is a bit more detail.
The following screenshot shows the output EXE along with the associated program debug
database (which provides additional information when debugging the EXE), once we have built
the solution in Lesson 1 using Visual Basic Express. The path to which the EXE is compiled is
specified in the Visual Basic Express project settings and is, by default, set to the bin sub-folder
of the Visual Basic Express project folder.
49
Autodesk® Inventor® API Lab for Power Users
Lesson_2_1_Windows Explorer showing Exe.bmp
Choosing a programming language and development tool
Just as humans use different languages to communicate, we have various language options
available to us when creating an Inventor plugin: for the purposes of this guide we have chosen
Visual Basic .NET (VB.NET), a strong general-purpose programming language that is often
favored by beginners.
There are a number of tools available for developing VB.NET code. They range from open
source tools such as SharpDevelop to Microsoft’s flagship, professional development
environment, Visual Studio. In our case we will be using Visual Basic Express, a free version of
Visual Studio focused on building VB.NET applications.
Visual Basic Express is an Integrated Development Environment (IDE) because it is composed
of various tools, menus and toolbars which ease the creation and management of your code.
The following screenshot shows the initial screen of Visual Basic 2010 Express with the default
settings.
50
Autodesk® Inventor® API Lab for Power Users
Lesson_2_2_VB start page.bmp
The project system in Visual Basic Express comprises Solution and Project files as well as
Project Items, the individual files belonging to projects. A solution is a container for one or more
projects. Each project can in turn be considered a container for project items – such as source
files, icons, etc. – most of which get compiled into the resultant executable file (EXE or DLL).
Visual Basic Express provides a Solution Explorer that organizes and displays the contents of
the loaded solution in a tree-view format:
51
Autodesk® Inventor® API Lab for Power Users
Lesson_2_3_Solution Explorer window.bmp
The Visual Basic Express interface also contains a text editor and interface designers. These
are displayed in the main window depending on the type of file being edited. The text editor is
where you will enter the Visual Basic code for your Inventor plugin. This editor provides
advanced features such as IntelliSense and collapsible code sections along with the more
classic text-editing features such as bookmarks and the display of line numbers.
IntelliSense is an extremely valuable feature of the Visual Studio family that greatly improves
programmer productivity: it automatically provides suggestions for the code being written based
on the objects available and the letters that are being typed.
52
Autodesk® Inventor® API Lab for Power Users
Lesson_2_4_Intellisense.bmp
IntelliSense showing the methods and properties for a ComponentOccurrence
Clearly one of the key features of Visual Basic Express is its ability to build VB.NET code into an
executable file. During the build process, the language compiler performs various checks and
analyses on the code. One such check is to ensure the code conforms to the syntactical rules of
the Visual Basic language. The compiler also performs various other checks, such as whether a
variable has been appropriately defined or not. Detected errors are reported via the Error List
Window, typically found at the bottom of the main window. The Error List can be displayed by
selecting Error List from the View Menu > Other Windows.
53
Autodesk® Inventor® API Lab for Power Users
The Visual in Visual Basic Express
One of the main strengths of Visual Basic Express is the set of tools it has for creating a User
Interface. When we create a new project we can select a “Windows Forms Application”. When
this template is used the main window for the application is automatically created. This window
is called a form and we can place user interface elements (called controls), such as a command
buttons, on it. We add an element by simply selecting it in the Toolbox and then clicking and
dragging it onto the Form. The Toolbox can be displayed using the View menu > Other
Windows > Toolbox. The code that is needed, behind the scenes, to make these elements work
correctly is added automatically to the project. Because of this, it greatly simplifies the code we
need to add ourselves to get our application up and running.
54
Autodesk® Inventor® API Lab for Power Users
Additional Topics
Visual Basic Express vs. Visual Studio Professional
In this guide, as you will have noticed, we are using Visual Basic Express. This is a free version
of Visual Studio, a great tool to start writing and managing Visual Basic code for our Inventor
plugin without investing in a more expensive tool. Microsoft has targeted the Express editions of
Visual Studio at students, hobbyists and other part-time programmers. While it provides most of
the features of Visual Studio Professional, such as IntelliSense, it does have certain limitations.
For instance, it contains fewer project templates and has limited options for debugging. For
users who are serious about plugin development beyond this introductory project, we
recommend investing in one of the more fully-featured members of the Visual Studio product
family.
What is COM?
“Microsoft COM (Component Object Model) technology in the Microsoft Windows-family of
Operating Systems enables software components to communicate. COM is used by developers
to create re-usable software components, link components together to build applications, and
take advantage of Windows services. COM objects can be created with a variety of
programming languages. Object-oriented languages, such as C++, provide programming
mechanisms that simplify the implementation of COM objects.”
Source: MSDN Library
What is .NET?
“The .NET Framework is an integral Windows component that supports building and running the
next generation of applications and XML Web services.”
Source: MSDN Library
The .NET Framework is a software framework that sits on top of the Microsoft® Windows®
operating system* and provides the underlying platform, libraries and services for all .NET
applications. The services generally include memory management, garbage collection, common
type system, class libraries, etc.
* Subsets of .NET are also available on other operating systems, whether via the open source
Mono project or via Microsoft® Silverlight®, but these are not topics for this guide: we will focus
solely on the use of .NET in the context of Microsoft Windows.
What does the .NET Framework contain?
The framework contains two main components:
1. Common Language Runtime (CLR) – This is the agent (or execution engine) in the
.NET Framework responsible for managing the execution of code. Which is why code
written to target this runtime is also known as managed code. All managed code runs
under the supervision of the CLR, but what does this mean? The CLR manages code by
55
Autodesk® Inventor® API Lab for Power Users
providing core services such as memory management (which includes automatically
releasing the computer’s memory for reuse on other tasks when it is no longer needed),
error (or exception) handling, managing the use of multiple threads of execution and
ensuring rules around the use of different types of object are adhered to. The CLR is
really the foundation of the .NET Framework.
2. .NET Framework Class Library – As the name suggests, this is a library or collection of
object types that can be used from your own code when developing .NET applications.
These .NET applications can target Windows (whether command-prompt based or with
a graphical user interface), the web or mobile devices. This library is available to all
languages using the .NET Framework.
As mentioned above, the CLR improves code robustness by making sure the executing code
conforms to a common type system (CTS). The CTS ensures that all .NET (or managed) code –
irrespective of the language – uses a similar set of object types and can work together in the
same environment. It is this feature that makes it possible for you to write applications in the
development language of your choice and yet make use of components/code written by
programmers using other .NET languages.
Accessing COM from .NET
Inventor’s API is COM-based: internally the Inventor product is implemented using C++ and its
API is exposed through COM, enabling the use of various development environments and
programming languages. Thankfully, the interoperability features of .NET make it really easy to
work with COM APIs: any complexity of passing data between .NET and Inventor is hidden
away, so we can focus on using the API rather than dealing with communication issues.
Building Executables
When we built our code into an EXE, it was compiled into Common Intermediate Language (CIL
–also known as MSIL) code using the language-specific compiler. CIL is CPU-independent set
of instruction that can be executed by the CLR on Windows operating systems. CIL is typically
portable across 32- and 64-bit systems and even – to some extent – to non-Windows operating
systems. The CIL code generated from our VB source code was then packaged into a .NET
assembly. Such an assembly is a library of CIL code stored in Portable Executable (PE) format
(which contains both the CIL its associated metadata). Assemblies can either be process
assemblies (EXEs) or library assemblies (DLLs).
During the course of this guide, we focus on developing a particular type of Inventor plugin: a
process assembly (EXE) which communicates with Inventor. Because of the overhead
associated with developing them, we will not spend time looking at Inventor AddIns, which are
usually library assemblies (DLLs) that get loaded into and executed within Inventor’s memory
space. One reason that implementing an EXE to work with Inventor is simpler that developing
an AddIn is related to its user interface: Executables do not need to integrate seamlessly with
the Inventor user interface by adding ribbon buttons (for instance).
56
Autodesk® Inventor® API Lab for Power Users
Running Executables
During execution of a .NET assembly, CIL (residing in the
assembly) is passed through the CLR’s just-in-time (JIT) compiler
to generate native (or machine) code. JIT compilation of the CIL to
native code occurs when the application is executed. As not all of
the code is required during execution, the JIT compiler only
converts the CIL when it is needed, thus saving time and memory.
It also stores any generated code in memory, making it available
for subsequent use without the need to recompile.
In the last step of this process, the native code gets executed by
the computer’s processor.
If you would like more details on the process of building .NET
applications, please refer to the MSDN Library.
LAB 3 Discussion
Link to return to LAB 3
In this lesson, we will take a closer look at the Inventor API. In Lesson 1, we typed code (or
instructions) into a code window associated with a Form and saw how it changed the visibility of
components in an assembly. In Lesson 2 we created a Windows Form application and
referenced the Inventor API from it. In this lesson we will continue working on the project we
created in Lesson 2, extending it to use the Inventor API to connect to or start a session of
Inventor while taking a close look at how the code actually works.
Object Oriented Programming
In the previous lesson, we talked about how a program is a sequence of instructions which tells
the computer how to perform one or more tasks. Simple programs tend to consist of a sequence
or list of instructions operating on variables – data representing what’s happening in the
program as it executes. But, with increasing complexity, such linear sequences of instructions
(an approach also often referred to as procedural programming) can be difficult to manage and
ends up not being well-suited for the task for which the code was written.
57
Autodesk® Inventor® API Lab for Power Users
To help address the complexity problem, Object-Oriented Programming (OOP) was developed
to allow source code to be structured differently, enabling componentization and reuse. OOP
encourages us to develop discrete, reusable units of programming logic which are aimed at
modeling objects from the problem domain and the relationships between them. A good
example of this is a map. A map of a city can be considered as a model or a simplified
representation of the city itself, providing a useful abstraction of the information we need to get
around it.
The key to good object-oriented design is to model the elements of the problem domain as
individual objects displaying the relevant behavior of the originals and the relationships between
them.
A class can be thought of as a type which can be used to describe a representation of a thing.
A class can be considered the template that describes the details of an object and is used to
create individual objects. In this way classes can help define the common characteristics of
objects of their type: the objects’ attributes (properties) and behaviors (methods). In the
context of VB.NET, methods are either Functions or Subs (more on this later).
An object is an instance of a class. These are the building blocks of Object-Oriented
Programming and can be thought of as variables - often quite complex ones – which
encapsulate both data and behavior.
To provide an example, the relationship between a class and an object has parallels with
Inventor iFeatures. An iFeature could be considered as a class. When we create an instance of
this iFeature, that instance can be thought of as an object. The iFeature is the blueprint or
template: each instance of the iFeature has the set of parameters defined in the iFeature but
has different parameter values. They might have a different length or width, for instance.
Use the Object Model Chart to discover the Inventor API classes
Looking at the Inventor API object model, you will see that many of the classes in the Inventor
API are organized to follow the main document types in Inventor – Parts, Assemblies and
Drawings. Other parts of the API are used to create user interfaces and other objects not related
to a specific document type. You can download a PDF containing a diagram of the Inventor API
Object Model from the Inventor Developer Center - http://www.autodesk.com/developinventor
(you will find other resources available for the Inventor API here, as well).
The Object Model chart allows us to see graphically how the classes in the Inventor API relate
to one another. The top level class is the Application. One of the classes accessible from the
Application class is the Documents class. Under Documents we find PartDocument,
AssemblyDocument and DrawingDocument. Here is a screenshot of part of the Object Model
chart that shows the relationship between the Application, Documents and DrawingDocument
classes. Notice it is a hierarchy showing how classes are referenced by – and accessible from –
other classes.
58
Autodesk® Inventor® API Lab for Power Users
Lesson_3_1_Object_Model_Chart.bmp
ObjectModel screenshot of DrawingDocument object
We could think of the Object Model chart as we would a business organization chart. At the top
we have the president and under the president we may have several vice presidents. Then each
vice president would have directors and they would have employees under them and so on. So
if this business was like the Inventor API, you would need to go through the president
(Application), then the vice president (Documents) and down the hierarchy to get to the
employee (DrawingDocument) to get something done related to this part of the business (such
as saving the DrawingDocument). Another way to look at the Object Model is to see it as a type
of containment such as a building. The Application object would be the entire building and it
contains floors. One floor would be Documents collection and that floor contains rooms such as
various Document objects. You would need to go the building front door (Application) then go to
the right floor (Documents) and then into the Document room to do something with the
document.
In the Object Model Chart we see that some of the boxes around the classes are rectangular
and some have rounded corners. Boxes with rounded corners are used to denote collections of
59
Autodesk® Inventor® API Lab for Power Users
objects – notice their names typically end in an “s”, as they are intended to contain multiple
objects of a particular class. The Documents collection, for example, will contain one or more
Document objects. A collection will have methods such as an Add method that will create a
new object of that class. (The Documents.Add method will create a new document).
The Object Model PDF is also provided with the Inventor SDK (Software Development Kit). The
SDK will be in a directory on your local system such as this:
C:\Program Files\Autodesk\Inventor 2011\SDK\DeveloperTools\Docs
The SDK ships with Inventor however separate msi files need to be run to install it. These are
DeveloperTools.msi and UserTools.msi. DeveloperTools.msi installs samples and tools
intended to help developers write applications. User Tools.msi will install applications that
automate tasks for Inventor users that are not available in the Inventor product. The location of
the installer is different for Windows XP and Windows Vista or Windows 7.
Windows XP: C:\Program Files\Autodesk\Inventor 2011\SDK\DeveloperTools.msi
Windows Vista or 7: C:\Users\Public\Documents\Autodesk\Inventor
2011\SDK\DeveloperTools.msi
For more information on the SDK see this file:
C:\Program Files\Autodesk\Inventor 2011\SDK\SDK_Readme.htm
LAB 4 Discussion
Link to LAB 4
A Closer Look at the Code
In previous lessons we learned that a class can have methods and properties. Classes also
generate events when things happen for your code to respond to: we want to respond to our
button’s click event, for instance, and it’s in our handler for this event (which is a special kind of
method) that we’ve added the rest of the code in this lesson.
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles
Button1.Click
End Sub
When the button is clicked we want to get the components in the assembly that the user has
already selected. To do this we need to use the SelectSet property of the document.
60
Autodesk® Inventor® API Lab for Power Users
To make sure the rest of our code can function, we first need to check Inventor has a document
open. We do this by checking the number of items in the Documents collection from Inventor’s
Application object via the collection’s Count property. Notice how we’re using the dot notation to
“walk the hierarchy”, going from one object to another via properties.
If _invApp.Documents.Count = 0 Then
MsgBox("Need to open an Assembly document")
Return
End If
An “If Then” statement lets you execute code conditionally: if the condition between the “If” and
the “Then” evaluates to true, then the code between the “Then” and the “End If” gets executed.
In this example, when the Count property is zero, we know that no documents are open in
Inventor. At this point we tell the user to open an assembly and we then Return from the Sub –
jumping to the end of the Sub without executing any further code. It’s much better to check for
problematic situations in this way than to let the code fail and generate a confusing error
message. The Return keyword does not cause our application to exit completely – it only
Returns from the Sub – so the user can simply open an assembly and click the button again.
The next piece of code is another “If Then” statement: this time to make sure the document
that’s active in Inventor is an assembly, as our code only works with assembly components. In
this case we use a slightly different comparison: we use the inequality operator (<>) rather than
the equality operator (=). So if the active document is not an assembly we present a different
message to the user and Return from the Sub.
If _invApp.ActiveDocument.DocumentType <>
DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("Need to have an Assembly document active")
Return
If our code gets past the two “If Then” statements then we know an assembly is active and we
can proceed to get the SelectSet from it.
Dim asmDoc As AssemblyDocument
asmDoc = _invApp.ActiveDocument
If asmDoc.SelectSet.Count = 0 Then
MsgBox("Need to select a Part or Sub Assembly")
Return
End If
We use the Dim statement to declare a variable named “asmDoc” of type “AssemblyDocument”
and directly assign the contents of the Inventor Application’s ActiveDocument property to it
61
Autodesk® Inventor® API Lab for Power Users
using the equals sign (which is also the assignment operator in VB.NET). If we make changes
to asmDoc using one of its properties, the change will take effect on the active document. Here
we are just using one of the properties, “SelectSet” in an “If Then” statement – we’re not
modifying the document at all. Once again we’re checking the Count property, to see whether
the SelectSet contains any items: if the user did not select anything then we ask them to do so
before Returning from the Sub.
At this point in our code, we know that something is selected in the active Inventor assembly.
Now we will go ahead and do something to each of the selected components.
Dim selSet As SelectSet
selSet = asmDoc.SelectSet
Try
Dim compOcc As ComponentOccurrence
Dim obj As Object
For Each obj In selSet
compOcc = obj
Debug.Print(compOcc.Name)
compOcc.Visible = False
Next
Catch ex As Exception
MsgBox("Is the selected item a Component?")
MsgBox(ex.ToString())
Return
End Try
Here we assign the SelectSet containing the selected entities from the active
AssemblyDocument to the “selSet” variable. A Try Catch block is used for error checking: if a
problem occurs while executing the code inside the Try block, the code in the Catch block gets
executed, allowing us to provide further information to the user about the problem (in this case
we ask them to make sure they have selected one or more components).
Within the Try block we use a “For Next” loop to step through each of the entities in the
SelectSet. If only one entity is selected then the code between the “For Each” and “Next”
statements will only be processed once. If there are more entities selected, the code will be
processed once for each entity. We know that the code will be executed at least once, as we
would already have Returned from the Sub if there were no entities in the SelectSet. The
SelectSet could contain any type of entity that is selectable in Inventor: it’s for this reason we
access its contents the generic “Object” type (a type that can contain any kind of object). If the
user has selected something other than a Component an error will be generated when we
attempt to assign it to our “compOcc” variable of type ComponentOccurrence. Assuming this
assignment doesn’t cause an error, the next line will execute, which uses Debug.Print to send
62
Autodesk® Inventor® API Lab for Power Users
the name of the ComponentOccurrence to the Immediate window in Visual Basic Express. This
window can be displayed in Visual Basic Express from the Debug Menu>Windows (or Ctrl+G).
Using Debug.Print and the immediate window is a useful tool if a problem occurs and you need
to work out what is wrong. Notice that the Immediate window is accessed from a different
location then the Error List which is accessed from View>Other Windows. After the Debug.Print
statement we reach the goal of this lesson’s code, to hide the selected components by setting
their Visible property to False.
LAB 5 Discussion
Link to LAB 5
A Closer Look at the Code for Button1
As we now know, using the Inventor API we can use custom attribute values to tag entities such
as components. We can then use this attribute to find the tagged entities and do something with
them. In this example we use a custom attribute value to locate the components and then hide
or display them. There are three Inventor API classes that are used to add an Attribute to
entities: AttributeSets, AttributeSet and Attribute. Many types of Inventor entity – including
ComponentOccurrence – have an AttributesSets property. Notice in this example that the name
of the variable we use to store the contents of the AttributeSets property is attbSets, a
shorthand version of AttributeSets. Any naming convention can be used; however it is helpful if
the chosen names are descriptive and consistent with either the type or the purpose of the
variable.
Dim attbSets As AttributeSets = compOcc.AttributeSets
As mentioned, the second class we use when adding attributes is AttributeSet. From the name
of this class we can guess that the AttributeSets object is a collection of AttributeSet objects.
Each AttributeSet associated with an object needs to have a unique name. If an AttributeSet
with the name we want to use has already been added to the component, we should not try to
add another with that name. We can use the NameIsUsed method of the AttributeSets class to
check if an AttributeSet with a particular name has already been added to that object. The
name of the AttributeSet we are going to create in this example, myPartGroup, is passed into
the NameIsUsed property. The If Not Then statement will cause the code between the If and
End If to be processed if the name myPartGroup has not already been given to an AttributeSet
in the AttributesSets of the component.
' Add the attributes to the ComponentOccurrence
If Not attbSets.NameIsUsed("myPartGroup") Then
End If
63
Autodesk® Inventor® API Lab for Power Users
We use the Add method of the AttributeSets object to create an AttributeSet. (Remember that
we got the AttributeSets from the component). The AttributeSets.Add method takes a String that
will be the name of the AttributeSet. Here we are using the name myPartGroup, which needs to
be passed in as a string of characters. To create a String, we simply need to enclose the text –
the contents of the string – in double quotes. It is a good idea to use a descriptive value in this
string, which will essentially be the name of our AttributeSet. We will also use this text to test for
the existence of our AttributeSet via the “NameIsUsed” property.
Dim attbSet As AttributeSet = attbSets.Add("myPartGroup")
The third object we need to add the attribute is the Attribute itself. We use the Add method of
the AttributeSet to create the Attribute.
Dim attb As Inventor.Attribute = _
attbSet.Add( _
"PartGroup1", ValueTypeEnum.kStringType, "Group1")
The AttributeSet.Add method takes three arguments. Notice how IntelliSense is very helpful for
knowing the types of the various arguments:
64
Autodesk® Inventor® API Lab for Power Users
The first argument is a String and will be the name of the Attribute. The second argument is a
ValueType and is one of the value types in the Inventor.ValueTypeEnum. The third argument is
the Value which needs to be the type specified by the second argument.
A Closer Look at the Code for Button2
The code in Button2 searches for entities tagged with the attributes added by the code behind
Button1: it uses the FindObjects method of the AttributeManager, which we access via the
assembly document (asmDoc) and assign to a variable (attbMan). We want to catch any errors
so we enclose these operations in a Try Catch block.
Try
Dim attbMan As AttributeManager = asmDoc.AttributeManager
Dim objsCol As ObjectCollection
objsCol = _
attbMan.FindObjects("myPartGroup", "PartGroup1", "Group1")
Catch ex As Exception
MsgBox("Problem hiding component")
65
Autodesk® Inventor® API Lab for Power Users
End Try
The FindObjects method populates an ObjectCollection with each of the objects it finds with our
custom attribute attached. FindObjects takes three arguments to locate objects (Inventor
entities) with attributes. Although we use all three arguments in our project – to look for
attributes with a specific AttributeSetName, AtributeName and AttributeValue – they are all not
required: in other situations we might choose to look only for attributes belonging to a set with a
particular name, for instance. In this example we passed in “myPartGroup” (as the
AttributeSetName), “PartGroup1” (as the AttributeName) and “Group1” (as the AttributeValue).
IntelliSense, as we see below, helps us understand the meaning of the arguments to the
FindObjects method. Notice the square brackets, which indicate that each of the arguments is
optional.
We should now have the tagged components in the ObjectCollection returned by the call to
FindObjects. To hide or show the components we need to loop through each object in the
collection and change its Visible property. The natural way to loop through a collection is using a
“For Each Next” loop: other types of loop would also work, but would require us to maintain a
66
Autodesk® Inventor® API Lab for Power Users
counter which acts as an index into the collection and to select items manually from it. “For
Each Next” loops provide us with the current object in the collection at each pass through the
code.
The next line is very simple: we are simply toggling the Visible property of each
ComponentOccurrence object: if the value is True it gets set to False and if it’s False it gets set
to True. The Not operator lets us do this very succinctly, without the need for an “If Then Else”
conditional statement.
Dim compOcc As ComponentOccurrence
For Each obj As Object In objsCol
compOcc = obj
' Toggle the visibility of the Component Occurrence
compOcc.Visible = Not compOcc.Visible
Next
LAB 6 Discussion
Link to LAB 6
A Closer Look at the Code
In this lesson we created two different Sub-routines that we can call when a button is clicked
instead of having the code directly in our Sub. The advantage of using a separate Sub is that
similar code will not be duplicated in our project and our code will be easier to update in the
future. In lesson 5 we created a button that, when clicked, hid or displayed components after
determining which to modify by searching for an attribute tag.. We now have a Sub that can hide
or show these components.
Public Sub HideOrShowGroup(ByVal hide As Boolean)
End Sub
We also have a Sub that can add components to or remove them from the group.
Public Sub AddOrRemoveFromGroup(ByVal add As Boolean)
End Sub
These Sub-routines can run from anywhere in our project. We can pass in True or False to
control the behavior. We were therefore able to reuse code that we created previously by
making a few simple changes. We changed the code we pasted into the
HideOrShowComponentsInGroup Sub to either hide or show the components based on the
67
Autodesk® Inventor® API Lab for Power Users
Boolean value passed in. We did this by changing the For Each loop simply to make the Visible
property of the component equal to the argument passed into the Sub. (hide).
For Each obj As Object In objsCol
compOcc = obj
compOcc.Visible = hide
Next
The changes we made to the code added to the AddOrRemoveFromGroup Sub were to
change its behavior based on the value of the Boolean variable, add, that was passed into the
Sub. For the case where add is True, we used the code we already had. For the case where
add is False, we added code to delete the AttributeSet. We used If Then Else End If
statements to do this. Similar to adding an AttributeSet, we do not want to try to delete an
AttributeSet that does not exist, so we checked the NameIsUsed property to test this. In the
case the AttributeSet exists, we then used the Item property of the AttributeSets with our
chosen name (“myPartGroup”), calling the Delete method on the resultant AttributeSet to
remove it from the component.
If add Then
' Add the attributes to the ComponentOccurrence
If Not attbSets.NameIsUsed("myPartGroup") Then
Dim attbSet As AttributeSet = attbSets.Add("myPartGroup")
Dim attb As Inventor.Attribute = _
attbSet.Add( _
"PartGroup1", ValueTypeEnum.kStringType, "Group1")
End If
Else
' Delete the attributes to the ComponentOccurrence
If attbSets.NameIsUsed("myPartGroup") Then
attbSets.Item("myPartGroup").Delete()
End If
End If
Next
The code for Button 5 (Remove all components from group) that we copied from another Sub
gets all the components with our AttributeSet and deletes the AttributeSet from each one (rather
than deleting it only from the selected components). In this Sub, after we have an
ObjectCollection with all of the components in the Assembly with our AttributeSet, we can use a
“For Next” loop to delete the AttributeSet from each component. We also need to make each
68
Autodesk® Inventor® API Lab for Power Users
component visible: after the Sub has finished its work, these components will no longer have
our AttributeSet attached, and so will no longer be made visible by the “Show Group” button.
69
Download