├── _config.yml ├── Fütemire.ico ├── Resources ├── Thumbs.db ├── Settings.png └── Settings_32x32.png ├── Converters ├── ReadoutPrecisionToCustomPropertyPrecision.vb ├── EmptyControlVisibilityConverter.vb ├── InventorValueConverter.vb └── RelayCommand.vb ├── README.md ├── My Project ├── Settings.settings ├── AssemblyInfo.vb ├── Settings.Designer.vb ├── Resources.resx └── MyExtensions │ └── MyWpfExtension.vb ├── Config Files ├── Fütemire.AddinName.Inventor.addin └── AddinName.manifest ├── Windows ├── MainWindow.xaml └── MainWindow.xaml.vb ├── InventorWPFAddin.sln ├── License ├── app.config ├── Extensions ├── FileSystemExtensions.vb ├── InventorAttributeSetExtensions.vb └── InventorDocumentExtensions.vb ├── .gitattributes ├── .gitignore ├── MyTemplate.vstemplate ├── AutodeskInventorWPFAddin.vbproj └── Core Classes ├── MainWindowControlDef.vb ├── AddinBaseClass.vb ├── ErrorLogging.vb └── ControlDefBaseClass.vb /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /Fütemire.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futemire/Autodesk-Inventor-WPF-Add-in-Template/HEAD/Fütemire.ico -------------------------------------------------------------------------------- /Resources/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futemire/Autodesk-Inventor-WPF-Add-in-Template/HEAD/Resources/Thumbs.db -------------------------------------------------------------------------------- /Resources/Settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futemire/Autodesk-Inventor-WPF-Add-in-Template/HEAD/Resources/Settings.png -------------------------------------------------------------------------------- /Resources/Settings_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futemire/Autodesk-Inventor-WPF-Add-in-Template/HEAD/Resources/Settings_32x32.png -------------------------------------------------------------------------------- /Converters/ReadoutPrecisionToCustomPropertyPrecision.vb: -------------------------------------------------------------------------------- 1 | Imports Inventor 2 | 3 | Public Module ReadoutPrecisionToCustomPropertyPrecision 4 | 5 | End Module -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Autodesk-Inventor-WPF-Add-in-Template 2 | An Autodesk Inventor WPF based add-in template with wizard interface. 3 | 4 | A WPF add-in template for Autodesk Inventor. The template should be available as a downloadable Visual Studio package including the main template and other reusable Item templates. The initial project creation will include a template wizard that the user will fill out to aid rapid creation of an out-of-the-box working add-in. The goal is to provide a solution in which any developer can get up and running quickly without having to focus on the initial setup of an add-in. 5 | -------------------------------------------------------------------------------- /My Project/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0, 0 10 | 11 | 12 | -------------------------------------------------------------------------------- /Config Files/Fütemire.AddinName.Inventor.addin: -------------------------------------------------------------------------------- 1 | 2 | {$guid1$} 3 | {$guid1$} 4 | Build Stock Number 5 | $addindescription$ 6 | C:\ProgramData\Autodesk\Inventor Addins\$companyname$\$safeprojectname$.dll 7 | 1 8 | 0 9 | 0 10 | 15.. 11 | 1 12 | 1 13 | 0 14 | -------------------------------------------------------------------------------- /Windows/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /InventorWPFAddin.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "AutodeskInventorWPFAddin", "AutodeskInventorWPFAddin.vbproj", "{67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /Converters/EmptyControlVisibilityConverter.vb: -------------------------------------------------------------------------------- 1 | Imports System.Globalization 2 | 3 | Public Class EmptyControlVisibilityConverter : Implements IValueConverter 4 | 5 | Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.Convert 6 | If Not TypeOf (value) Is Integer Then Return Binding.DoNothing 7 | Select Case True 8 | Case value > 0 9 | Return Visibility.Visible 10 | Case Else 11 | Return Visibility.Collapsed 12 | End Select 13 | End Function 14 | 15 | Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IValueConverter.ConvertBack 16 | If Not TypeOf (value) Is Visibility Then Return Binding.DoNothing 17 | Select Case True 18 | Case Visibility.Collapsed 19 | Return 0 20 | Case Visibility.Hidden 21 | Return 0 22 | Case Else 23 | Return 1 24 | End Select 25 | End Function 26 | End Class -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Fütemire 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Converters/InventorValueConverter.vb: -------------------------------------------------------------------------------- 1 | Imports System.Globalization 2 | Imports Inventor 3 | Public Class InventorValueConverter : Implements IMultiValueConverter 4 | 5 | ''' 6 | ''' Converts Inventor internal parameter value to correct units in lists. 7 | ''' values(0) must be the Inventor Parameter. 8 | ''' values(1) is the internal value. 9 | ''' 10 | ''' [Array] Inventor Parameter and Parameter Internal Value to be converted. 11 | ''' [String] 12 | Public Function Convert(values() As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object Implements IMultiValueConverter.Convert 13 | Try 14 | Dim InvDoc As Document = values(0) 15 | Dim UOM As UnitsOfMeasure = InvDoc.UnitsOfMeasure 16 | Dim ConvertedValue As String = UOM.GetStringFromValue(values(1), UOM.LengthUnits) 17 | Return ConvertedValue 18 | Catch ex As Exception 19 | Return Binding.DoNothing 20 | End Try 21 | End Function 22 | 23 | ''' 24 | ''' ConvertBack not implemented. 25 | ''' 26 | Public Function ConvertBack(value As Object, targetTypes() As Type, parameter As Object, culture As CultureInfo) As Object() Implements IMultiValueConverter.ConvertBack 27 | Return Binding.DoNothing 28 | End Function 29 | End Class -------------------------------------------------------------------------------- /Config Files/AddinName.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | <$safeprojectname$.MySettings> 32 | 33 | 34 | 35 | 36 | 0, 0 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Extensions/FileSystemExtensions.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.CompilerServices 2 | 3 | Module FileSystemExtensions 4 | 5 | ''' 6 | ''' Checks the specified path and returns the last write time of the file. 7 | ''' 8 | ''' [String] Full file path. 9 | 10 | Public Function GetLastWriteTime(FilePath As String) As Date 11 | Return My.Computer.FileSystem.GetFileInfo(FilePath).LastWriteTime 12 | End Function 13 | 14 | ''' 15 | ''' Checks the path of files or directories and returns [TRUE] if it exists. 16 | ''' 17 | ''' [Sting] Path of file or directory to check. 18 | ''' [Boolean] 19 | 20 | Public Function IsValidPath(ByVal Path As String) As Boolean 21 | 'First check to see if the path exists as a file. 22 | If My.Computer.FileSystem.FileExists(Path) Then Return True 23 | 'Then check to see if the path exists as a directory. 24 | If My.Computer.FileSystem.DirectoryExists(Path) Then Return True 25 | 'If we made it here then the path does not exist at all... 26 | Return False 27 | End Function 28 | 29 | ''' 30 | ''' Ensures that a directory path exists, if not then tries to create it. 31 | ''' This method works on File and Directory paths. 32 | ''' Returns [True] if the path exists or was created, [False] is failed to create. 33 | ''' 34 | ''' [String] A file or Directory path to check. 35 | ''' [True] or [False] 36 | 37 | Public Function EnsureDirectory(Path As String) As Boolean 38 | Try 39 | Dim DirPath = IO.Path.GetDirectoryName(Path) 40 | If Not My.Computer.FileSystem.DirectoryExists(DirPath) Then 41 | My.Computer.FileSystem.CreateDirectory(DirPath) 42 | End If 43 | Return True 44 | Catch ex As Exception 45 | Return False 46 | End Try 47 | End Function 48 | 49 | End Module -------------------------------------------------------------------------------- /Windows/MainWindow.xaml.vb: -------------------------------------------------------------------------------- 1 | Imports System.ComponentModel 2 | Imports System.Runtime.CompilerServices 3 | Imports System.Windows.Threading 4 | 5 | Class MainWindow 6 | 7 | ''' 8 | ''' AddinBaseClass object to be used referenced by this window. 9 | ''' 10 | Private _Addin As AddinBaseClass 11 | 12 | ''' 13 | ''' Just a sample event to show how to hook back into the MainWindowControlDef. 14 | ''' This can be modified to fit your needs, or deleted. 15 | ''' 16 | Public Event MyEvent() 17 | 18 | ''' 19 | ''' Creates a new instance of the window and moves it to the last saved location. 20 | ''' 21 | ''' [AddinBaseClass] AddinBaseClass object to be used referenced by this window. 22 | Sub New(ByVal Addin As AddinBaseClass) 23 | 24 | ' This call is required by the designer. 25 | InitializeComponent() 26 | 27 | 'Link the Add-in Object 28 | _Addin = Addin 29 | 30 | 'Set Inventor as the parent of this window. 31 | 'This will allow your window to be minimized with Inventor. 32 | Call _Addin.SetInventorAsOwnerWindow(Me) 33 | 34 | 'Set the saved window location. 35 | Me.Top = My.Settings.WindowLocation.X 36 | Me.Left = My.Settings.WindowLocation.Y 37 | 38 | 39 | End Sub 40 | 41 | ''' 42 | ''' Closes the window and saves its last location on screen to the app settings. 43 | ''' 44 | Private Sub OnCloseWindow(target As Object, e As ExecutedRoutedEventArgs) 45 | My.Settings.WindowLocation = New System.Drawing.Point(Me.Top, Me.Left) 46 | My.Settings.Save() 47 | SystemCommands.CloseWindow(Me) 48 | End Sub 49 | 50 | ''' 51 | ''' Empty delegate so we can force a window update on the UI thread from other threads. 52 | ''' 53 | Public EmptyDelegate As Action = Sub() 54 | End Sub 55 | 56 | Public Sub Refresh() 57 | Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate) 58 | End Sub 59 | 60 | End Class 61 | -------------------------------------------------------------------------------- /Converters/RelayCommand.vb: -------------------------------------------------------------------------------- 1 | ''' 2 | ''' A command whose sole purpose is to 3 | ''' relay its functionality to other 4 | ''' objects by invoking delegates. The 5 | ''' default return value for the CanExecute 6 | ''' method is 'true'. 7 | ''' 8 | ''' Code converted from the example on the following link. 9 | ''' http://stackoverflow.com/questions/3531772/binding-button-click-to-a-method 10 | ''' 11 | Public Class RelayCommand : Implements ICommand 12 | #Region "Fields" 13 | ReadOnly _execute As Action(Of Object) 14 | ReadOnly _canExecute As Predicate(Of Object) 15 | Private Event ICommand_CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged 16 | #End Region 17 | 18 | #Region "Constructors" 19 | ''' 20 | ''' Creates a new command that can always execute. 21 | ''' 22 | ''' The execution logic. 23 | Public Sub New(execute As Action(Of Object)) 24 | Me.New(execute, Nothing) 25 | End Sub 26 | 27 | ''' 28 | ''' Creates a new command. 29 | ''' 30 | ''' The execution logic. 31 | ''' The execution status logic. 32 | Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object)) 33 | If execute Is Nothing Then 34 | Throw New ArgumentNullException("execute") 35 | End If 36 | _execute = execute 37 | _canExecute = canExecute 38 | End Sub 39 | #End Region 40 | 41 | #Region "ICommand Members" 42 | 43 | Public Function CanExecute(parameters As Object) As Boolean Implements ICommand.CanExecute 44 | Return If(_canExecute Is Nothing, True, _canExecute(parameters)) 45 | End Function 46 | 47 | Public Custom Event CanExecuteChanged As EventHandler 48 | AddHandler(ByVal value As EventHandler) 49 | AddHandler CommandManager.RequerySuggested, value 50 | End AddHandler 51 | RemoveHandler(ByVal value As EventHandler) 52 | RemoveHandler CommandManager.RequerySuggested, value 53 | End RemoveHandler 54 | RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) 55 | If (_canExecute IsNot Nothing) Then 56 | _canExecute.Invoke(sender) 57 | End If 58 | End RaiseEvent 59 | End Event 60 | 61 | Public Sub Execute(parameters As Object) Implements ICommand.Execute 62 | _execute(parameters) 63 | End Sub 64 | #End Region 65 | End Class -------------------------------------------------------------------------------- /My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Globalization 3 | Imports System.Reflection 4 | Imports System.Resources 5 | Imports System.Runtime.InteropServices 6 | Imports System.Windows 7 | 8 | ' General Information about an assembly is controlled through the following 9 | ' set of attributes. Change these attribute values to modify the information 10 | ' associated with an assembly. 11 | 12 | ' Review the values of the assembly attributes 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 'In order to begin building localizable applications, set 23 | 'CultureYouAreCodingWith in your .vbproj file 24 | 'inside a . For example, if you are using US English 25 | 'in your source files, set the to "en-US". Then uncomment the 26 | 'NeutralResourceLanguage attribute below. Update the "en-US" in the line 27 | 'below to match the UICulture setting in the project file. 28 | 29 | ' 30 | 31 | 'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found. 32 | '1st parameter: where theme specific resource dictionaries are located 33 | '(used if a resource is not found in the page, 34 | ' or application resource dictionaries) 35 | 36 | '2nd parameter: where the generic resource dictionary is located 37 | '(used if a resource is not found in the page, 38 | 'app, and any theme specific resource dictionaries) 39 | 40 | 41 | 'The following GUID is for the ID of the typelib if this project is exposed to COM 42 | 43 | 44 | ' Version information for an assembly consists of the following four values: 45 | ' 46 | ' Major Version 47 | ' Minor Version 48 | ' Build Number 49 | ' Revision 50 | ' 51 | ' You can specify all the values or you can default the Build and Revision Numbers 52 | ' by using the '*' as shown below: 53 | ' 54 | 55 | 56 | 57 | ' I prefer versioning with the year, month, day, build number format like below, but i left the default intact for the template. -Addam 58 | ' 59 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | 16 | _ 19 | Partial Friend NotInheritable Class MySettings 20 | Inherits Global.System.Configuration.ApplicationSettingsBase 21 | 22 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) 23 | 24 | #Region "My.Settings Auto-Save Functionality" 25 | #If _MyType = "WindowsForms" Then 26 | Private Shared addedHandler As Boolean 27 | 28 | Private Shared addedHandlerLockObject As New Object 29 | 30 | _ 31 | Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) 32 | If My.Application.SaveMySettingsOnExit Then 33 | My.Settings.Save() 34 | End If 35 | End Sub 36 | #End If 37 | #End Region 38 | 39 | Public Shared ReadOnly Property [Default]() As MySettings 40 | Get 41 | 42 | #If _MyType = "WindowsForms" Then 43 | If Not addedHandler Then 44 | SyncLock addedHandlerLockObject 45 | If Not addedHandler Then 46 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 47 | addedHandler = True 48 | End If 49 | End SyncLock 50 | End If 51 | #End If 52 | Return defaultInstance 53 | End Get 54 | End Property 55 | 56 | _ 59 | Public Property ErrorLogDirectory() As String 60 | Get 61 | Return CType(Me("ErrorLogDirectory"),String) 62 | End Get 63 | Set 64 | Me("ErrorLogDirectory") = value 65 | End Set 66 | End Property 67 | 68 | _ 71 | Public Property WindowLocation() As Global.System.Drawing.Point 72 | Get 73 | Return CType(Me("WindowLocation"),Global.System.Drawing.Point) 74 | End Get 75 | Set 76 | Me("WindowLocation") = value 77 | End Set 78 | End Property 79 | End Class 80 | 81 | Namespace My 82 | 83 | _ 86 | Friend Module MySettingsProperty 87 | 88 | _ 89 | Friend ReadOnly Property Settings() As Global.MySettings 90 | Get 91 | Return Global.MySettings.Default 92 | End Get 93 | End Property 94 | End Module 95 | End Namespace 96 | -------------------------------------------------------------------------------- /Extensions/InventorAttributeSetExtensions.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.CompilerServices 2 | Imports System.Text 3 | Imports Inventor 4 | 5 | Module InventorAttributeSetExtensions 6 | 7 | ''' 8 | ''' Returns a string tree of all attributes and their values in the specified attribute set. 9 | ''' 10 | ''' [Inventor.AttributeSet] 11 | ''' [String] 12 | 13 | Public Function ToValueString(ByVal AttSet As AttributeSet) As String 14 | Dim FullTreeString As StringBuilder 15 | FullTreeString.AppendLine("Attribute Set: " & AttSet.Name) 16 | For Each Att As Attribute In AttSet 17 | FullTreeString.AppendLine("Attribute Name: " & Att.Name & " Value: " & Att.Value.ToString) 18 | Next 19 | Return Trim(FullTreeString.ToString) 20 | End Function 21 | 22 | ''' 23 | ''' Searches an Inventor attribute for specified XML attribute with option to also specify the XML element if more than one. 24 | ''' Returns the [String] value of first occurrence found or [Nothing]. 25 | ''' 26 | ''' [Inventor.Attribute] 27 | ''' [String] If Inventor attribute contains multiple XML Elements then specify the Element name that contains the correct attribute. 28 | ''' [String] Name of XML attribute to search for. 29 | ''' [String] or [Nothing] 30 | 31 | Public Function GetXMLAttributeByName(InvAttribute As Attribute, XMLElementName As String, XMLAttributeName As String) As String 32 | Try 33 | Dim RootEle As XElement = InvAttribute.Value 34 | Dim ReturnedAttributes As IEnumerable(Of XElement) = From RA As XElement 35 | In RootEle.Descendants 36 | Where XMLElementName = RA.Name 37 | 38 | Select Case ReturnedAttributes.Count 39 | Case >= 0 40 | 'No Items found. 41 | Return Nothing 42 | Case 1 43 | 'Item found, only return first instance. 44 | Return ReturnedAttributes(0).Value 45 | End Select 46 | Catch ex As Exception 47 | Throw New Exception("GetXMLAttributeByName()" & vbNewLine & ex.ToString) 48 | End Try 49 | 'If we made it this far then return nothing. 50 | Return Nothing 51 | End Function 52 | 53 | ''' 54 | ''' Save the specified XML element to an Inventor Attribute. 55 | ''' Returns [True] on success and [False] on fail. 56 | ''' 57 | ''' [Inventor.AttributeSet] 58 | ''' [String] Name of Inventor Attribute to update or create. 59 | ''' [String] XML element to save to the Inventor attribute. 60 | ''' [Boolean] 61 | 62 | Public Function SaveXMLAsAttribute(InvAttributeSet As AttributeSet, InvAttributeName As String, XMLElement As XElement) As Boolean 63 | If InvAttributeSet.NameIsUsed(InvAttributeName) Then 64 | Dim InvAtt As Attribute = InvAttributeSet(InvAttributeName) 65 | 'If the Inventor Attribute is a string type update it. 66 | If InvAtt.ValueType = ValueTypeEnum.kStringType Then 67 | InvAtt.Value = XMLElement.ToString 68 | Return True 69 | Else 70 | 'Was not correct type. 71 | Throw New Exception("SaveXMLAsAttribute()" & vbNewLine & "The Inventor Attribute value type was not String.") 72 | End If 73 | Else 74 | 'The attribute does not exist so create it. 75 | InvAttributeSet.Add(InvAttributeName, ValueTypeEnum.kStringType, XMLElement.ToString) 76 | Return True 77 | End If 78 | 'If we made it this far then return nothing. 79 | Return False 80 | End Function 81 | 82 | End Module -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /Extensions/InventorDocumentExtensions.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.CompilerServices 2 | Imports Inventor 3 | 4 | Module InventorDocumentExtensions 5 | Public Enum PropertySetEnum 6 | All 7 | SummaryInfo 8 | DesignTracking 9 | Custom 10 | End Enum 11 | 12 | ''' 13 | ''' Inventor Document InventorDocumentSubType 14 | ''' 15 | 16 | Public Enum InventorDocumentSubType 17 | UnKnown 18 | SolidPart 19 | SheetMetal 20 | GenericProxy 21 | CompatabilityProxy 22 | CatalogProxy 23 | Assembly 24 | Drawing 25 | DesignElement 26 | Presentation 27 | End Enum 28 | 29 | ''' 30 | ''' Gets the Document SubType of Inventor Document. 31 | ''' 32 | ''' [Inventor.Document] Document to return the SubType on. 33 | ''' [InventorDocumentSubType] Document SubType Enum 34 | ''' 35 | 36 | Public Function GetDocumentSubType(ByRef InvDoc As Inventor.Document) As InventorDocumentSubType 37 | Select Case InvDoc.DocumentSubType.DocumentSubTypeID 38 | Case "{4D29B490-49B2-11D0-93C3-7E0706000000}" 39 | Return InventorDocumentSubType.SolidPart 40 | Case "{9C464203-9BAE-11D3-8BAD-0060B0CE6BB4}" 41 | Return InventorDocumentSubType.SheetMetal 42 | Case "{92055419-B3FA-11D3-A479-00C04F6B9531}" 43 | Return InventorDocumentSubType.GenericProxy 44 | Case "{9C464204-9BAE-11D3-8BAD-0060B0CE6BB4}" 45 | Return InventorDocumentSubType.CompatabilityProxy 46 | Case "{9C88D3AF-C3EB-11D3-B79E-0060B0F159EF}" 47 | Return InventorDocumentSubType.CatalogProxy 48 | Case "{E60F81E1-49B3-11D0-93C3-7E0706000000}" 49 | Return InventorDocumentSubType.Assembly 50 | Case "{BBF9FDF1-52DC-11D0-8C04-0800090BE8EC}" 51 | Return InventorDocumentSubType.Drawing 52 | Case "{62FBB030-24C7-11D3-B78D-0060B0F159EF}" 53 | Return InventorDocumentSubType.DesignElement 54 | Case "{76283A80-50DD-11D3-A7E3-00C04F79D7BC}" 55 | Return InventorDocumentSubType.Presentation 56 | End Select 57 | Return InventorDocumentSubType.UnKnown 58 | End Function 59 | 60 | ''' 61 | ''' Function returns [Parameter] with specified name Or [Nothing]. 62 | ''' 63 | ''' [String] Name of parameter to return. 64 | ''' [Inventor.Parameter] Or [Nothing] 65 | 66 | Public Function GetParameter(InvDoc As Inventor.PartDocument, ParameterName As String) As Inventor.Parameter 67 | Try 68 | Return InvDoc.ComponentDefinition.Parameters.Item(ParameterName) 69 | Catch ex As Exception 70 | Return Nothing 71 | End Try 72 | End Function 73 | 74 | ''' 75 | ''' Function returns [Parameter] with specified name Or [Nothing]. 76 | ''' 77 | ''' [String] Name of parameter to return. 78 | ''' [Inventor.Parameter] Or [Nothing] 79 | 80 | Public Function GetParameter(InvDoc As Inventor.AssemblyDocument, ParameterName As String) As Inventor.Parameter 81 | Try 82 | Return InvDoc.ComponentDefinition.Parameters.Item(ParameterName) 83 | Catch ex As Exception 84 | Return Nothing 85 | End Try 86 | End Function 87 | 88 | ''' 89 | ''' Returns the specified iProperty from the specified PropertySet or Nothing. 90 | ''' 91 | ''' [Inventor.Document] 92 | ''' [String] Name of property to search for. 93 | ''' [PropertySetEnum] PropertySet to search. Default=All 94 | ''' [Boolean] If TRUE then create non existing property. 95 | ''' 96 | 97 | Public Function GetIpropertyFromPropertySet(InventorDocument As Document, PropertyName As String, 98 | Optional PropertySet As PropertySetEnum = PropertySetEnum.All, 99 | Optional CreateProperty As Boolean = False, 100 | Optional PropertyValue As String = "") As [Property] 101 | If PropertySet = PropertySetEnum.All Then 102 | 'Search all properties. 103 | For Each PropSet As PropertySet In InventorDocument.PropertySets 104 | For Each Prop As [Property] In PropSet 105 | If Prop.Name = PropertyName Then Return Prop 106 | Next 107 | Next 108 | Else 109 | 'Search a specific PropertySet. 110 | Dim SetName As String = Nothing 111 | Select Case PropertySet 112 | Case PropertySetEnum.SummaryInfo 113 | SetName = "Inventor Summary Information" 114 | Case PropertySetEnum.DesignTracking 115 | SetName = "Design Tracking Properties" 116 | Case PropertySetEnum.Custom 117 | SetName = "Inventor User Defined Properties" 118 | End Select 119 | 'Try to return a value. 120 | Try 121 | Return InventorDocument.PropertySets(SetName)(PropertyName) 122 | Catch ex As Exception 123 | 124 | If CreateProperty Then 125 | 'Create the non-existing property as a custom iProperty. 126 | Return InventorDocument.PropertySets("Inventor User Defined Properties").Add(PropertyValue, PropertyName) 127 | End If 128 | End Try 129 | End If 130 | 'Was not found and was not created. 131 | Return Nothing 132 | End Function 133 | 134 | End Module -------------------------------------------------------------------------------- /MyTemplate.vstemplate: -------------------------------------------------------------------------------- 1 | 2 | 3 | Autodesk Inventor WPF Add-in 4 | Autodesk Inventor Add-in project template using Windows Presentation Foundation (WPF). 5 | VisualBasic 6 | Autodesk 7 | 1 8 | true 9 | Autodesk Inventor WPF Add-in 10 | true 11 | Enabled 12 | true 13 | Fütemire.ico 14 | 15 | 16 | 17 | app.config 18 | 19 | Fütemire.AddinName.Inventor.addin 20 | BuildStockNumber.manifest 21 | 22 | 23 | EmptyControlVisibilityConverter.vb 24 | InventorValueConverter.vb 25 | ReadoutPrecisionToCustomPropertyPrecision.vb 26 | RelayCommand.vb 27 | 28 | 29 | AddinBaseClass.vb 30 | AddinConfigClass.vb 31 | AdministrationClass.vb 32 | ControlDefBaseClass.vb 33 | ErrorLogging.vb 34 | MainWindowControlDef.vb 35 | ManagedParameter.vb 36 | StockTypeBaseClass.vb 37 | 38 | 39 | AssemblyExtensions.vb 40 | ComboBoxExtensions.vb 41 | EnumExtensions.vb 42 | FileSystemExtensions.vb 43 | InventorAttributeSetExtensions.vb 44 | InventorDocumentExtensions.vb 45 | MathExtensions.vb 46 | UIElementExtensions.vb 47 | XMLExtensions.vb 48 | 49 | 50 | vstg0001.vb 51 | 52 | 53 | AssemblyInfo.vb 54 | 55 | MyWpfExtension.vb 56 | 57 | Resources.resx 58 | Resources.Designer.vb 59 | Settings.settings 60 | Settings.Designer.vb 61 | 62 | 63 | BuildStockNumber.Config 64 | CarbonFiber.png 65 | function_32.png 66 | pencil.png 67 | StockTag.pdn 68 | StockTag.png 69 | StockTag16.png 70 | tag--pencil.png 71 | 72 | 73 | Default Control Styles.xaml 74 | ModifiedDefaultControls.xaml 75 | WindowStyles.xaml 76 | 77 | 78 | MainWindow.xaml 79 | MainWindow.xaml.vb 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /My Project/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\$safeprojectname$.Config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 123 | 124 | 125 | ..\Resources\StockTag.pdn;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 126 | 127 | 128 | ..\Resources\Settings.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\Settings_32x32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | -------------------------------------------------------------------------------- /My Project/MyExtensions/MyWpfExtension.vb: -------------------------------------------------------------------------------- 1 | #If _MyType <> "Empty" Then 2 | 3 | Namespace My 4 | ''' 5 | ''' Module used to define the properties that are available in the My Namespace for WPF 6 | ''' 7 | ''' 8 | 9 | Module MyWpfExtension 10 | Private s_Computer As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.Devices.Computer) 11 | Private s_User As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.ApplicationServices.User) 12 | Private s_Windows As New ThreadSafeObjectProvider(Of MyWindows) 13 | Private s_Log As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.Logging.Log) 14 | ''' 15 | ''' Returns the application object for the running application 16 | ''' 17 | 18 | Friend ReadOnly Property Application() As Application 19 | Get 20 | Return CType(Global.System.Windows.Application.Current, Application) 21 | End Get 22 | End Property 23 | ''' 24 | ''' Returns information about the host computer. 25 | ''' 26 | 27 | Friend ReadOnly Property Computer() As Global.Microsoft.VisualBasic.Devices.Computer 28 | Get 29 | Return s_Computer.GetInstance() 30 | End Get 31 | End Property 32 | ''' 33 | ''' Returns information for the current user. If you wish to run the application with the current 34 | ''' Windows user credentials, call My.User.InitializeWithWindowsUser(). 35 | ''' 36 | 37 | Friend ReadOnly Property User() As Global.Microsoft.VisualBasic.ApplicationServices.User 38 | Get 39 | Return s_User.GetInstance() 40 | End Get 41 | End Property 42 | ''' 43 | ''' Returns the application log. The listeners can be configured by the application's configuration file. 44 | ''' 45 | 46 | Friend ReadOnly Property Log() As Global.Microsoft.VisualBasic.Logging.Log 47 | Get 48 | Return s_Log.GetInstance() 49 | End Get 50 | End Property 51 | 52 | ''' 53 | ''' Returns the collection of Windows defined in the project. 54 | ''' 55 | 56 | Friend ReadOnly Property Windows() As MyWindows 57 | 58 | Get 59 | Return s_Windows.GetInstance() 60 | End Get 61 | End Property 62 | 63 | 64 | Friend NotInheritable Class MyWindows 65 | 66 | Private Shared Function Create__Instance__(Of T As {New, Global.System.Windows.Window})(ByVal Instance As T) As T 67 | If Instance Is Nothing Then 68 | If s_WindowBeingCreated IsNot Nothing Then 69 | If s_WindowBeingCreated.ContainsKey(GetType(T)) = True Then 70 | Throw New Global.System.InvalidOperationException("The window cannot be accessed via My.Windows from the Window constructor.") 71 | End If 72 | Else 73 | s_WindowBeingCreated = New Global.System.Collections.Hashtable() 74 | End If 75 | s_WindowBeingCreated.Add(GetType(T), Nothing) 76 | Return New T() 77 | s_WindowBeingCreated.Remove(GetType(T)) 78 | Else 79 | Return Instance 80 | End If 81 | End Function 82 | 83 | 84 | Private Sub Dispose__Instance__(Of T As Global.System.Windows.Window)(ByRef instance As T) 85 | instance = Nothing 86 | End Sub 87 | 88 | 89 | Public Sub New() 90 | MyBase.New() 91 | End Sub 92 | Private Shared s_WindowBeingCreated As Global.System.Collections.Hashtable 93 | Public Overrides Function Equals(ByVal o As Object) As Boolean 94 | Return MyBase.Equals(o) 95 | End Function 96 | Public Overrides Function GetHashCode() As Integer 97 | Return MyBase.GetHashCode 98 | End Function 99 | 100 | 101 | Friend Overloads Function [GetType]() As Global.System.Type 102 | Return GetType(MyWindows) 103 | End Function 104 | Public Overrides Function ToString() As String 105 | Return MyBase.ToString 106 | End Function 107 | End Class 108 | End Module 109 | End Namespace 110 | Partial Class Application 111 | Inherits Global.System.Windows.Application 112 | 113 | 114 | Friend ReadOnly Property Info() As Global.Microsoft.VisualBasic.ApplicationServices.AssemblyInfo 115 | 116 | Get 117 | Return New Global.Microsoft.VisualBasic.ApplicationServices.AssemblyInfo(Global.System.Reflection.Assembly.GetExecutingAssembly()) 118 | End Get 119 | End Property 120 | End Class 121 | #End If -------------------------------------------------------------------------------- /AutodeskInventorWPFAddin.vbproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {67E0ED77-8AC6-4F97-84AB-ECA8B6D6116B} 8 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{F184B08F-C81C-45F6-A57F-5ABD9991F28F} 9 | Library 10 | $safeprojectname$ 11 | $safeprojectname$ 12 | v4.5.2 13 | Custom 14 | true 15 | SAK 16 | SAK 17 | SAK 18 | SAK 19 | 2017.3.13.1 20 | 21 | 22 | AnyCPU 23 | true 24 | full 25 | true 26 | true 27 | true 28 | bin\Debug\ 29 | $safeprojectname$.xml 30 | 41999,42016,42017,42018,42019,42020,42021,42022,42030,42032,42036,42104,42108,42109 31 | false 32 | 33 | 34 | AnyCPU 35 | pdbonly 36 | false 37 | false 38 | true 39 | false 40 | true 41 | bin\Release\ 42 | $safeprojectname$.xml 43 | 41999,42016,42017,42018,42019,42020,42021,42022,42030,42032,42036,42104,42108,42109 44 | false 45 | 46 | 47 | On 48 | 49 | 50 | Binary 51 | 52 | 53 | Off 54 | 55 | 56 | On 57 | 58 | 59 | 60 | 61 | 62 | false 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | True 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 4.0 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | MSBuild:Compile 97 | Designer 98 | 99 | 100 | 101 | 102 | 103 | Component 104 | 105 | 106 | Component 107 | 108 | 109 | 110 | 111 | 112 | MainWindow.xaml 113 | Code 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | Code 138 | 139 | 140 | Microsoft.VisualBasic.WPF.MyExtension 141 | 1.0.0.0 142 | 143 | 144 | True 145 | Settings.settings 146 | True 147 | 148 | 149 | VbMyResourcesResXFileCodeGenerator 150 | My.Resources 151 | 152 | 153 | 154 | 155 | SettingsSingleFileGenerator 156 | Settings.Designer.vb 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | {D98A091D-3A0F-4C3E-B36E-61F62068D488} 169 | 1 170 | 0 171 | 0 172 | primary 173 | False 174 | True 175 | 176 | 177 | {00020430-0000-0000-C000-000000000046} 178 | 2 179 | 0 180 | 0 181 | primary 182 | False 183 | True 184 | 185 | 186 | 187 | 188 | xcopy /y "$(ProjectDir)Config Files\$companyname.$(TargetName).Inventor.addin" "C:\ProgramData\Autodesk\Inventor Addins\" 189 | xcopy /y "$(TargetPath)" "C:\ProgramData\Autodesk\Inventor Addins\$companyname$ Add-ins\" 190 | 191 | -------------------------------------------------------------------------------- /Core Classes/MainWindowControlDef.vb: -------------------------------------------------------------------------------- 1 | Imports System.Reflection 2 | Imports System.Security.Principal 3 | Imports System.Text 4 | Imports System.Text.RegularExpressions 5 | Imports $safeprojectname$.My 6 | Imports Inventor 7 | 8 | ''' 9 | ''' This is a sample class that demonstrates creating a Control Definition by inheriting from the ControlDefBaseClass. 10 | ''' The ControlDefBaseClass handles the repetitive work of creating/accessing Tabs and Panels as well as adding Control Definitions to specified Panels. 11 | ''' You can modify this to fit your needs, or delete it. 12 | ''' 13 | Public Class MainWindowControlDef : Inherits ControlDefBaseClass 14 | 15 | 'Inventor's button definition for this ControlDef. 16 | Public WithEvents ButtonDef As ButtonDefinition 17 | 18 | 'The window that this control definition will display/interact with. 19 | Public WithEvents MainWin As MainWindow 20 | 21 | 'Use Inventor's Transaction manager to set undo checkpoints. 22 | Public TransMan As TransactionManager 23 | Public AddinTransAction As Transaction 24 | 25 | 'Events to be used in the current ControlDef. 26 | Public WithEvents AppEvents As ApplicationEvents 27 | 28 | ''' 29 | ''' [Private] Active Inventor Document reference object. 30 | ''' 31 | Private _ActDoc As Document 32 | 33 | ''' 34 | ''' [Private] Document sub type such as "SolidPart" or "Sheetmetal". 35 | ''' 36 | Private _ComponentType As InventorDocumentSubType 37 | 38 | ''' 39 | ''' [Private] AddinBaseClass reference object. 40 | ''' 41 | Private _Addin As AddinBaseClass 42 | 43 | 44 | ''' 45 | ''' Creates the ComponentDefinition. 46 | ''' 47 | ''' 48 | Public Sub New(ByVal Addin As AddinBaseClass) 49 | 50 | 'Initialize the base class. 51 | 'This MUST be called before anything else. 52 | MyBase.New(Addin) 53 | 54 | 'Populate to the private object. 55 | _Addin = Addin 56 | 57 | 'Create the balloon tips that will be displayed to the user. 58 | 'This is less intrusive than constantly displaying message boxes. 59 | _Addin.InvApp.UserInterfaceManager.BalloonTips.Add("$companysafename$_$addinsafename$_HeyNowBalloonTip", '<---- Company Name, Addin Name, Balloon Tip Name, No Spaces 60 | "Hey Now", '<---- Balloon Tip Display Name, Spaces OK 61 | "Hey Now, This is a balloon tip!" 62 | ) 63 | 64 | 65 | 'Hookup the event objects needed for this control. 66 | AppEvents = _Addin.InvApp.ApplicationEvents 67 | 68 | 'Define the button name & internal name. The Button Name can be anything but the Internal Name must be unique and cannot contain spaces. 69 | 'Because there are nearly 2000 button definition already in Inventor I typically create Internal Names by using this format... 70 | 'MyCompanyName_MyAddinSafeName_MyButtonName 71 | 72 | ButtonName = "$addinname$ Button 1" 73 | LargeIcon = My.Resources.Settings 74 | SmallIcon = My.Resources.Settings_32x32 75 | 76 | ButtonInternalName = "$companysafename$_$addinsafename$_MainWindow" 77 | ShowButtonText = True 78 | 79 | 80 | 'General hover text to be displayed when user hovers over the button. 81 | 'Note that this text will ignored if you decide to use the progressive tool tip. 82 | ToolTip = "Launch $addinname$." 83 | 84 | 'This feature is optional. If set to True then your button will display a more elaborate tool tip with a 85 | 'title, space for a longer button description, and the option to add an image or video string. 86 | Progressive = False 87 | ProgressiveTitle = Nothing 88 | ProgressiveDesc = Nothing 89 | ProgressiveImage = Nothing 90 | ProgressiveVideo = Nothing 91 | 92 | 'Create a new list of the ribbons you want to add the button to. 93 | IncludeInRibbons = New List(Of RibbonType)({RibbonType.Part, RibbonType.Assembly}) 94 | 95 | 'Specify the Internal Name of the Ribbon Tab that the button should be included in. 96 | 'If Left blank then a control definition will be created but NOT added to UI. 97 | 'If a Ribbon Tab with the specified InternalName is found then the existing object is used. 98 | 'If a Ribbon Tab with the specified InternalName is not fount then it is created. 99 | 'Use the same nomenclature as explained for the ButtonInternalName above. 100 | ' 101 | TabInternalName = "$companysafename$_$addinsafename$_Tab" 102 | 103 | 'Friendly Name of Tab to create if InteranlName is not found. This name can contain spaces. 104 | TabName = "$companyname$" 105 | 106 | 'Specify the Internal Name of the Ribbon Panel that the button should be included in. 107 | 'If Left blank then a control definition will be created but NOT added to UI. 108 | 'If a Ribbon Panel with the specified InternalName is found then the existing object is used. 109 | 'If a Ribbon Panel with the specified InternalName is not fount then it is created. 110 | 'Use the same nomenclature as explained for the ButtonInternalName above. 111 | ' 112 | PanelInternalName = "$companysafename$_$addinsafename$_Panel1" 113 | 114 | 'Friendly Name of Tab to create if InteranlName is not found. This name can contain spaces. 115 | PanelName = "$addinname$" 116 | 117 | 'Create the control button definition and link it to your Global Private WithEvents button def above. 118 | ButtonDef = CreateControlDefButton() 119 | 120 | 'Make the call to add the button to the User Interface. 121 | Call AddButtonToUI() 122 | 123 | End Sub 124 | 125 | ''' 126 | ''' Launch the main window for the $addinname$ add-in. 127 | ''' 128 | Private Sub ButtonDefinition_OnExecute(Context As NameValueMap) Handles ButtonDef.OnExecute 129 | Try 130 | 131 | 'Don't allow multiple instances of the window. 132 | If Not MainWin Is Nothing Then Exit Sub 133 | 134 | 'Set the Active Document & Active RangeBox 135 | _ActDoc = _Addin.InvApp.ActiveDocument 136 | 137 | 'Get the active document type. 138 | _ComponentType = _Addin.InvApp.ActiveDocument.GetDocumentSubType 139 | 140 | 'Get the Active Document. 141 | Select Case True 142 | Case _ComponentType = InventorDocumentSubType.Assembly 143 | _ActDoc = DirectCast(_ActDoc, AssemblyDocument) 144 | Case _ComponentType = InventorDocumentSubType.SolidPart 145 | _ActDoc = DirectCast(_ActDoc, PartDocument) 146 | Case _ComponentType = InventorDocumentSubType.SheetMetal 147 | _ActDoc = DirectCast(_ActDoc, PartDocument) 148 | Case Else 149 | 'We don't have a valid document type. 150 | Exit Sub 151 | End Select 152 | 153 | 'Create the transaction manager and start a transaction. 154 | TransMan = _Addin.InvApp.TransactionManager 155 | AddinTransAction = TransMan.StartTransaction(_ActDoc, "$addinname$") 156 | 157 | 'Create the window object. 158 | MainWin = New MainWindow(_Addin) 159 | 160 | 'You could create events in your MainWindow and add handlers here to handle user interactions. 161 | 'It would look something like this... 162 | AddHandler MainWin.MyEvent, AddressOf SomeMethodInThisClass 163 | 164 | 'Now show the window. 165 | MainWin.ShowDialog() 166 | 167 | 'End the transaction so it is committed. 168 | 'We won't get here until the MainWin is closed. 169 | If Not AddinTransAction Is Nothing Then 170 | AddinTransAction.End() 171 | AddinTransAction = Nothing 172 | End If 173 | 174 | Catch ex As Exception 175 | 'On error we need to abort the transaction if it is uncommitted. 176 | If Not AddinTransAction Is Nothing Then 177 | AddinTransAction.Abort() 178 | AddinTransAction = Nothing 179 | End If 180 | 181 | 'Log the error. 182 | _Addin.Logging.WriteToErrorLog("There was an error opening the form!", _Addin, ex) 183 | End Try 184 | End Sub 185 | 186 | 187 | #Region "Inventor Events" 188 | 'An example of where you can handle events that this control def has hooked into. 189 | Private Sub AppEvents_OnActivateDocument(DocumentObject As _Document, BeforeOrAfter As EventTimingEnum, 190 | Context As NameValueMap, ByRef HandlingCode As HandlingCodeEnum) Handles AppEvents.OnActivateDocument 191 | Select Case BeforeOrAfter 192 | Case EventTimingEnum.kBefore 193 | 194 | Case EventTimingEnum.kAfter 195 | 196 | Case EventTimingEnum.kAbort 197 | End Select 198 | 199 | End Sub 200 | 201 | Private Sub AppEvents_OnSaveDocument(DocumentObject As _Document, BeforeOrAfter As EventTimingEnum, 202 | Context As NameValueMap, ByRef HandlingCode As HandlingCodeEnum) Handles AppEvents.OnSaveDocument 203 | Select Case BeforeOrAfter 204 | Case EventTimingEnum.kBefore 205 | 206 | Case EventTimingEnum.kAfter 207 | 208 | Case EventTimingEnum.kAbort 209 | 210 | End Select 211 | End Sub 212 | #End Region 213 | 214 | #Region "Sample Event Handler" 215 | ''' 216 | ''' Just a sample event handler to show how to handle events from your MainWindow. 217 | ''' You can modify this to fit your needs, or delete it. 218 | ''' 219 | Public Sub SomeMethodInThisClass() 220 | MsgBox("My Main Window Fired An Event!") 221 | End Sub 222 | #End Region 223 | End Class -------------------------------------------------------------------------------- /Core Classes/AddinBaseClass.vb: -------------------------------------------------------------------------------- 1 | Imports System.Reflection 2 | Imports System.Runtime.InteropServices 3 | Imports System.Windows.Forms 4 | Imports Inventor 5 | 6 | ''' 7 | ''' For global add-in variables and methods only that rarely change. 8 | ''' Best practice is to wrap variables and properties in classes, so add here sparingly and only if it doesn't need to be managed. 9 | ''' 10 | Public Module AddinInfo 11 | 12 | ''' 13 | ''' Returns the Name attribute of the calling assembly. 14 | ''' 15 | ''' [String] 16 | Public ReadOnly Property AddinName As String 17 | Get 18 | Dim ProductName As AssemblyProductAttribute = Assembly.GetCallingAssembly.GetCustomAttribute(GetType(AssemblyProductAttribute)) 19 | Return ProductName.Product 20 | End Get 21 | End Property 22 | 23 | ''' 24 | ''' Safe name of the add-in containing no spaces and beginning with an underscore or letter. 25 | ''' 26 | ''' [String] 27 | Public ReadOnly Property SafeName As String 28 | Get 29 | 'Replace Spaces with underscore. 30 | Dim Name = AddinName.Replace(" ", "_") 31 | 'Add underscore if first character is a number. 32 | If IsNumeric(Name.Chars(0)) Then Name = "_" & Name 33 | Return Name 34 | End Get 35 | End Property 36 | 37 | ''' 38 | ''' Returns the Description attribute of the calling assembly. 39 | ''' 40 | ''' [String] 41 | Public ReadOnly Property AddinDescription As String 42 | Get 43 | Dim ProductDescription As AssemblyDescriptionAttribute = Assembly.GetCallingAssembly.GetCustomAttribute(GetType(AssemblyDescriptionAttribute)) 44 | Return ProductDescription.Description 45 | End Get 46 | End Property 47 | 48 | ''' 49 | ''' Returns the Version attribute of the calling assembly. 50 | ''' 51 | ''' [String] 52 | Public ReadOnly Property AddinVersion As String 53 | Get 54 | Dim AssemblyVersion As AssemblyFileVersionAttribute = Assembly.GetCallingAssembly.GetCustomAttribute(GetType(AssemblyFileVersionAttribute)) 55 | Return AssemblyVersion.Version 56 | End Get 57 | End Property 58 | 59 | ''' 60 | ''' Client ID of the add-in. 61 | ''' 62 | ''' [String] 63 | Public ReadOnly Property CLID As String 64 | Get 65 | Return "$guid1$" 66 | End Get 67 | End Property 68 | 69 | ''' 70 | ''' Gets or creates the AppData path for the current add-in. 71 | ''' 72 | ''' [String] Subdirectory to append to AppData path. 73 | ''' [String] 74 | Public ReadOnly Property AddinAppDataPath(Optional SubDirectoryName As String = Nothing) As String 75 | Get 76 | Dim AppDataDirectory As String 77 | Select Case True 78 | Case SubDirectoryName Is Nothing 79 | AppDataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData) & "\Autodesk\Inventor Addins\" 80 | Case SubDirectoryName = "" 81 | AppDataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData) & "\Autodesk\Inventor Addins\" 82 | Case Else 83 | SubDirectoryName.Replace("\", "") 84 | AppDataDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData) & "\Autodesk\Inventor Addins\" & SubDirectoryName & "\" 85 | End Select 86 | 'Create the AppData directory if it did not exist. 87 | If Not My.Computer.FileSystem.DirectoryExists(AppDataDirectory) Then 88 | My.Computer.FileSystem.CreateDirectory(AppDataDirectory) 89 | End If 90 | Return AppDataDirectory 91 | End Get 92 | End Property 93 | 94 | End Module 95 | 96 | 97 | Public Class AddinBaseClass 98 | Implements ApplicationAddInServer 99 | 100 | ''' 101 | ''' The Inventor Application object referenced by this add-in. 102 | ''' 103 | ''' 104 | Public ReadOnly Property InvApp As Inventor.Application 105 | Get 106 | Return _InvApp 107 | End Get 108 | End Property 109 | Private _InvApp As Inventor.Application 110 | 111 | ''' 112 | ''' The error logging class for the add-in. 113 | ''' 114 | Friend WithEvents Logging As ErrorLogging 115 | 116 | ''' 117 | ''' Enables or Disables this add-in for watching for log changes via the FileSystemWatcher. 118 | ''' 119 | Friend EnableLogWatching As Boolean = False 120 | 121 | ''' 122 | ''' Location of Application Data folder on current machine. 123 | ''' Windows best practice is to use the AppData folders to save application data from you app. 124 | ''' Saving in ProgramData or other locations you can start to run into issues with having to have elevated permissions. 125 | ''' Appdata Roaming is usefull to save app settings or config info for your app that can be used across multiple machines 126 | ''' that a user logs into with the same Active Directlry account. This is great in an enterprise environment. 127 | ''' 128 | Public AppDataDirectory As String 129 | 130 | ''' 131 | ''' An example Button Control Definition. 132 | ''' You dont need to use WithEvents if your ControlDef does not raise events. 133 | ''' See Setting Up Control Definitions in this project. 134 | ''' 135 | Public WithEvents MainWindowCDef As MainWindowControlDef 136 | 137 | ''' 138 | ''' Inventor Application Events 139 | ''' 140 | Public WithEvents AppEvents As ApplicationEvents 141 | 142 | ''' 143 | ''' Method required by Autodesk Inventor API Interface. 144 | ''' This property is provided to allow the Add-in to expose an API. 145 | ''' 146 | Public ReadOnly Property Automation As Object Implements ApplicationAddInServer.Automation 147 | Get 148 | Return Me 149 | End Get 150 | End Property 151 | 152 | ''' 153 | ''' This method is called by Inventor when it loads the Add-in. 154 | ''' 155 | ''' [Inventor.AddInSiteObject] Provides access to the Inventor Application object. 156 | ''' [Boolean] Indicates if the Add-in is loaded for the first time in the current Inventor session. 157 | Public Sub Activate(AddInSiteObject As ApplicationAddInSite, FirstTime As Boolean) Implements ApplicationAddInServer.Activate 158 | Try 159 | If FirstTime Then 160 | 'Setup the Unhandled Exception Handler. 161 | Dim curDomain = AppDomain.CurrentDomain : AddHandler curDomain.UnhandledException, AddressOf AddinUnhandledExceptionHandler 162 | 163 | 'Load the private variables... 164 | _InvApp = AddInSiteObject.Application 165 | 166 | 'Hook into events... 167 | AppEvents = _InvApp.ApplicationEvents 168 | 169 | 'Instantiate the error logging class. 170 | Logging = New ErrorLogging(My.Settings.ErrorLogDirectory) 171 | ' ▲ 172 | ' └─── This is not the best solution and should be changed. 173 | ' For the sake of simplicity in this template I removed my custom configuration 174 | ' file that can be administered without modifying or rebuilding code. 175 | ' Consider implementing your own to avoid hard coded paths or at lease 176 | ' revalidate the saved path on each startup and give the user the ability 177 | ' to update at will.. 178 | 179 | 180 | 'The control definitions are defined above so that they can be accessed anywhere the AddinBaseClass is passed. 181 | 'Create an instance of the control definitions. 182 | 'The MainWindowCDef creates a button that opens the MainWindow in this project when clicked. 183 | MainWindowCDef = New MainWindowControlDef(Me) 184 | 185 | End If 186 | 187 | Catch ex As Exception 188 | 'Write the error to the XML Error Log. 189 | Logging.WriteToErrorLog("The $addinname$ Add-in was not loaded!", ex) 190 | End Try 191 | End Sub 192 | 193 | ''' 194 | ''' Method required by Autodesk Inventor API Interface. 195 | ''' 196 | Public Sub Deactivate() Implements ApplicationAddInServer.Deactivate 197 | 'Only release if we have an application object. 198 | If Not _InvApp Is Nothing Then Marshal.ReleaseComObject(_InvApp) 199 | 200 | 'Call Garbage Collection 201 | GC.WaitForPendingFinalizers() 202 | GC.Collect() 203 | End Sub 204 | 205 | ''' 206 | ''' Method required by Autodesk Inventor API Interface. 207 | ''' 208 | ''' Depreciated. This method is required to be included for legacy purposes but needs to remain empty. 209 | ''' 210 | Public Sub ExecuteCommand(CommandID As Integer) Implements ApplicationAddInServer.ExecuteCommand 211 | 'Do Nothing 212 | End Sub 213 | 214 | ''' 215 | ''' Sets the Inventor window as the parent/owner of the specified form/window. 216 | ''' 217 | ''' [Window] The window to set as the child of the Inventor Window. 218 | ''' [Boolean] Returns TRUE on Success. 219 | ''' Setting an add-in window/dialog/form as a child will make sure it is hidden when the main Inventor window is minimized. 220 | 221 | Public Function SetInventorAsOwnerWindow(CurrWind As Window) As Boolean 222 | 223 | Try 224 | 'Find the Inventor Window Handle. 225 | Dim InvWndHnd As IntPtr = IntPtr.Zero 226 | 227 | 'Search the process list for the matching Inventor application. 228 | For Each pList As Process In Process.GetProcesses() 229 | If pList.MainWindowTitle.Contains(InvApp.Caption) Then 230 | InvWndHnd = pList.MainWindowHandle 231 | Exit For 232 | End If 233 | Next 234 | 235 | Dim InvWndIrp = New Interop.WindowInteropHelper(CurrWind) 236 | InvWndIrp.EnsureHandle() 237 | InvWndIrp.Owner = InvWndHnd 238 | Return True 239 | Catch ex As Exception 240 | Return False 241 | End Try 242 | End Function 243 | 244 | ''' 245 | ''' Handles all "Unhandled" exceptions caught in the add-in. 246 | ''' 247 | Sub AddinUnhandledExceptionHandler(sender As Object, args As UnhandledExceptionEventArgs) 248 | MsgBox("Unhandled Exception was caught!" & vbNewLine & DirectCast(args.ExceptionObject, Exception).ToString) 249 | End Sub 250 | 251 | ''' 252 | ''' Allows user to select a config file for the add-in. 253 | ''' 254 | ''' Returns TRUE on success, FALSE if canceled or failed. 255 | ''' 256 | ''' [Boolean] 257 | Private Function SetConfigFile() As Boolean 258 | 'Create the file open dialog. 259 | Dim FOD As New OpenFileDialog 260 | With FOD 261 | .AddExtension = True 262 | .CheckFileExists = True 263 | .CheckPathExists = True 264 | .Filter = "Config File (*.Config) | * .Config" 265 | .Multiselect = False 266 | .Title = "Select the Build StockNumber configuration file..." 267 | End With 268 | 269 | RETRY_LOAD_CONFIG: 270 | 'If a file was selected then check the path and set it. 271 | Select Case FOD.ShowDialog 272 | Case DialogResult.OK 273 | 'First make sure the path exists. 274 | If Not IsValidPath(FOD.FileName) Then GoTo RETRY_LOAD_CONFIG 275 | 'Next make sure it is a valid config file for the add-in. 276 | Dim ConfigText = IO.File.ReadAllText(FOD.FileName) 277 | If Not ConfigText.Contains("addin_name=""$safeprojectname$""") Then 278 | MsgBox("The selected file is not a valid config file for the Build StockNumber add-in!" & vbNewLine & "Please make another selection...") 279 | GoTo RETRY_LOAD_CONFIG 280 | End If 281 | My.Settings.ConfigDocPath = FOD.FileName 282 | My.Settings.Save() 283 | Return True 284 | End Select 285 | 286 | 'Either a path couldn't be found or the user canceled. 287 | Return False 288 | End Function 289 | 290 | Protected Function ValidateConfigFile() 291 | REVALIDATE: 292 | 'First check to see if the saved config file is valid, if not return false. 293 | If Not CheckPath(My.Settings.ConfigDocPath) Then 294 | MsgBox("The config file for the Build StockNumber add-in could not be loaded!" & vbNewLine & "Please select a valid config file...") 295 | If Not SetConfigFile() Then Return False Else GoTo REVALIDATE 296 | End If 297 | 298 | Dim ConfigText = IO.File.ReadAllText(My.Settings.ConfigDocPath) 299 | If Not ConfigText.Contains("addin_name=""$safeprojectname$""") Then 300 | MsgBox("The selected file is not a valid config file for the Build StockNumber add-in!" & vbNewLine & "Please select a valid config file...") 301 | If Not SetConfigFile() Then Return False Else GoTo REVALIDATE 302 | End If 303 | 304 | 'Next see if the config file has an updated path element. 305 | Dim Config As XDocument = XDocument.Load(My.Settings.ConfigDocPath) 306 | Dim xUpdatedPath As XElement = Config.Root.Descendants("UpdatedConfigPath")(0) 307 | 308 | If Not xUpdatedPath Is Nothing Then 309 | 'We found an UpdatedConfigPath element so lets check to make sure it is valid. 310 | Dim NewPath As XAttribute = xUpdatedPath.Attribute("path") 311 | If Not NewPath Is Nothing Then 312 | 313 | 'Check the NewPath. 314 | If IsValidPath(NewPath.Value) Then 315 | 'The new path exists so next make sure it is a valid config file for the add-in. 316 | Dim NewConfigText = IO.File.ReadAllText(NewPath.Value) 317 | If Not NewConfigText.Contains("addin_name=""$safeprojectname$""") Then 318 | MsgBox("The Updated Config file path listed in the current config file for the Build StockNumber add-in is invalid!" & vbNewLine & "Please make another selection...") 319 | If Not SetConfigFile() Then Return False Else GoTo REVALIDATE 320 | End If 321 | My.Settings.ConfigDocPath = NewPath.Value 322 | My.Settings.Save() 323 | End If 324 | End If 325 | End If 326 | 327 | Return True 328 | End Function 329 | 330 | End Class -------------------------------------------------------------------------------- /Core Classes/ErrorLogging.vb: -------------------------------------------------------------------------------- 1 | Imports System.DirectoryServices.AccountManagement 2 | Imports System.Reflection 3 | Imports System.Runtime.CompilerServices 4 | 5 | ''' 6 | ''' Notes about the ErrorLogging class. 7 | ''' This class will allow your application to write its errors to a specific XML document for each user. 8 | ''' The file name will be [WindowsAccountUserName].xml in the directory specified when creating the class. 9 | ''' If a directory is not supplied when creating the class then the default directory will be the user's AppData directory for the add-in. 10 | ''' 11 | Public Class ErrorLogging 12 | 13 | ''' 14 | ''' Gets/Sets a validated path for the Error Log Directory from the application settings. 15 | ''' 16 | ''' [String] A valid directory to store error logs. 17 | Public Property CurrentErrorLogDirectory() As String 18 | Set(value As String) 19 | If value.EnsureDirectory Then 20 | My.Settings.ErrorLogDirectory = value 21 | My.Settings.Save() 22 | Else 23 | Throw New System.IO.FileNotFoundException("The specified error log could not be found or created!", value) 24 | End If 25 | End Set 26 | Get 27 | Return My.Settings.ErrorLogDirectory 28 | End Get 29 | End Property 30 | 31 | ''' 32 | ''' 33 | ''' 34 | ''' [String](Optional | Default = Nothing) The path where the error log should be created. 35 | ''' Be sure it is in a location that the current application user can write to! 36 | ''' 37 | Public Sub New(Optional ErrorLogDirectory As String = Nothing) 38 | 39 | Try 40 | 'Pass the optional parameter to the CurrentErrorLogDirectory property, even if it is nothing. 41 | CurrentErrorLogDirectory = ErrorLogDirectory 42 | 43 | Catch ex As Exception 44 | 'If we made it here then either the optional ErrorLogDirectory parameter was nothing or invalid. 45 | 'So create an Error Logs folder under the current user's AppData directory for the add-in. 46 | CurrentErrorLogDirectory = AddinAppDataPath & "Error Logs\" 47 | End Try 48 | 49 | End Sub 50 | 51 | ''' 52 | ''' Creates an XML Style sheet for the error log. 53 | ''' 54 | Public Sub CreateErrorStyleSheet() 55 | Dim ErrorStyles As XDocument = Nothing 56 | ErrorStyles = 57 | 58 | 59 | 60 | 61 | 62 | 63 | 80 | 81 | 82 |
83 |

Error Summary |

84 |
85 | Name: 86 | 87 | 88 |
89 | Login: 90 | 91 | 92 |
93 | Error Count: 94 | 95 | 96 |
97 | Last Project: 98 | 99 | 100 |
101 | Last Error: 102 | 103 | 104 |
105 |
106 | 107 | 108 |

109 | Error No. | 110 |

111 |

112 | Time: 113 | 114 | 115 | | Inventor Version: 116 | 117 | 118 | | Project: 119 | 120 | 121 | | Addin Version: 122 | 123 | 124 |
125 | Addin Config: 126 | 127 | 128 |
129 |
130 | 131 | Error Message: 132 |
133 | 134 |
135 |
136 | Exception Message: 137 |
138 | 139 |
140 |
141 | Stack Trace: 142 |
143 | 144 |
145 |

146 |
147 |
148 | 149 | 150 |
151 |
152 | 153 | 'Save the style sheet. 154 | ErrorStyles.Save(CurrentErrorLogDirectory & "ErrorStyles.xsl") 155 | End Sub 156 | 157 | ''' 158 | ''' Writes the error to a log specific to the current user. 159 | ''' 160 | ''' [String] User friendly message. 161 | ''' [Exception] Exception to be included in log. 162 | Public Sub WriteToErrorLog(ByVal Message As String, 163 | Optional Ex As Exception = Nothing, 164 | Optional AdditionalElements As List(Of XElement) = Nothing) 165 | 166 | On Error Resume Next 167 | 'Exit if the file path is invalid or can not be created. 168 | If Not CurrentErrorLogDirectory.EnsureDirectory Then Exit Sub 169 | 170 | Dim LogDirectoryPath = CurrentErrorLogDirectory & Environment.UserName & ".xml" 171 | 172 | Dim xErrorLog As New XDocument 173 | 174 | 'Write to the log. 175 | If Not LogDirectoryPath.IsValidPath Then 176 | 'The file did not exist so create the file and header with the first entry. 177 | 178 | xErrorLog = 179 | 180 | 181 | 182 | 183 | 185 | user_name=<%= Environment.UserName %> 186 | email=<%= UserPrincipal.Current.EmailAddress %> 187 | error_count="1" 188 | last_error_occurred=<%= Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString %> 189 | /> 190 | 191 | > 192 | version=<%= AddinVersion %>/> 193 | /> 194 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 195 | <%= New XCData(Message) %> 196 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 197 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.Message) %>) %> 198 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.StackTrace) %>) %> 199 | 200 | 201 | 202 | 203 | Else 204 | 'Load the existing error log. 205 | xErrorLog = XDocument.Load(LogDirectoryPath) 206 | 207 | 'Get current error number. 208 | Dim CurrCount As Integer = CInt(xErrorLog.Root.Element("ErrorLogSummary").Attribute("error_count").Value) + 1 209 | 210 | 'Create a new Error element. 211 | Dim xError = 212 | time=<%= Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString %>> 213 | version=<%= AddinVersion %>/> 214 | /> 215 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 216 | <%= New XCData(Message) %> 217 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 218 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.Message) %>) %> 219 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.StackTrace) %>) %> 220 | 221 | 222 | 'Add the error element to the document. 223 | xErrorLog.Root.Element("Errors").Add(xError) 224 | 225 | 'Update the ErrorLogSummary 226 | 'Error Count 227 | xErrorLog.Root.Element("ErrorLogSummary").Attribute("error_count").Value = CurrCount 228 | 'Last Error Time 229 | xErrorLog.Root.Element("ErrorLogSummary").Attribute("last_error_occurred").Value = Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString 230 | 231 | End If 232 | 233 | 'Save the error log. 234 | xErrorLog.Save(LogDirectoryPath) 235 | xErrorLog = Nothing 236 | 237 | 'Lets make sure that an ErrorStyles sheet exists in the saved path. 238 | If Not CurrentErrorLogDirectory & "ErrorStyles.xsl".IsValidPath Then 239 | 'One did not exist so lets create it. 240 | Call CreateErrorStyleSheet() 241 | End If 242 | 243 | End Sub 244 | 245 | ''' 246 | ''' Writes the error to a log specific to the current user. 247 | ''' 248 | ''' [String] User friendly message. 249 | ''' [AddinBaseClass] Base class for the add-in. 250 | ''' [Exception] Exception to be included in log. 251 | Public Sub WriteToErrorLog(ByVal Message As String, 252 | ByVal Addin As AddinBaseClass, 253 | Optional Ex As Exception = Nothing, 254 | Optional AdditionalElements As List(Of XElement) = Nothing) 255 | 256 | On Error Resume Next 257 | 'Exit if the file path is invalid or can not be created. 258 | 'If My.Computer.FileSystem.EnsureDirectory(ErrorLogDirectory) Is Nothing Then Exit Sub 259 | 260 | Dim LogDirectoryPath = CurrentErrorLogDirectory & Environment.UserName & ".xml" 261 | 262 | Dim InventorProject As String = Addin.InvApp.DesignProjectManager.ActiveDesignProject.Name 263 | Dim InventorVersion As String = Addin.InvApp.SoftwareVersion.DisplayVersion 264 | Dim xErrorLog As New XDocument 265 | 266 | 'Write to the log. 267 | If Not LogDirectoryPath.IsValidPath Then 268 | 'The file did not exist so create the file and header with the first entry. 269 | 270 | xErrorLog = 271 | 272 | 273 | 274 | 275 | 277 | user_name=<%= Environment.UserName %> 278 | email=<%= UserPrincipal.Current.EmailAddress %> 279 | error_count="1" 280 | last_project=<%= InventorProject %> 281 | last_error_occurred=<%= Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString %> 282 | /> 283 | 284 | > 285 | version=<%= AddinVersion %>/> 286 | /> 287 | version=<%= InventorVersion %>/> 288 | <%= New XCData(Message) %> 289 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 290 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.Message) %>) %> 291 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.StackTrace) %>) %> 292 | 293 | 294 | 295 | 296 | Else 297 | 'Load the existing error log. 298 | xErrorLog = XDocument.Load(LogDirectoryPath) 299 | 300 | 'Get current error number. 301 | Dim CurrCount As Integer = CInt(xErrorLog.Root.Element("ErrorLogSummary").Attribute("error_count").Value) + 1 302 | 303 | 'Create a new Error element. 304 | Dim xError = 305 | time=<%= Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString %>> 306 | version=<%= AddinVersion %>/> 307 | /> 308 | version=<%= InventorVersion %>/> 309 | <%= New XCData(Message) %> 310 | <%= If(IsNothing(AdditionalElements), Nothing, From ele In AdditionalElements) %> 311 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.Message) %>) %> 312 | <%= If(IsNothing(Ex), Nothing, <%= New XCData(Ex.StackTrace) %>) %> 313 | 314 | 315 | 'Add the error element to the document. 316 | xErrorLog.Root.Element("Errors").Add(xError) 317 | 318 | 'Update the ErrorLogSummary 319 | 'Error Count 320 | xErrorLog.Root.Element("ErrorLogSummary").Attribute("error_count").Value = CurrCount 321 | 'Last Error Time 322 | xErrorLog.Root.Element("ErrorLogSummary").Attribute("last_error_occurred").Value = Date.Now.ToShortDateString & " @ " & Date.Now.ToShortTimeString 323 | 'Last Project 324 | xErrorLog.Root.Element("ErrorLogSummary").Attribute("last_project").Value = InventorProject 325 | 326 | End If 327 | 328 | 'Save the error log. 329 | xErrorLog.Save(LogDirectoryPath) 330 | xErrorLog = Nothing 331 | 332 | 'Lets make sure that an ErrorStyles sheet exists in the saved path. 333 | If Not CurrentErrorLogDirectory & "ErrorStyles.xsl".IsValidPath Then 334 | 'One did not exist so lets create it. 335 | Call CreateErrorStyleSheet() 336 | End If 337 | End Sub 338 | 339 | End Class 340 | -------------------------------------------------------------------------------- /Core Classes/ControlDefBaseClass.vb: -------------------------------------------------------------------------------- 1 | Imports Inventor 2 | Imports System.Drawing 3 | Imports System.Windows.Forms 4 | 5 | ''' 6 | ''' The ControlDefBaseClass handles the repetitive work of creating/accessing Tabs and Panels as well as adding Control Definitions to specified Panels. 7 | ''' This class must be inherited. 8 | ''' 9 | Public MustInherit Class ControlDefBaseClass : Inherits AxHost 10 | 11 | ''' 12 | ''' Inventor Tool Ribbon Types. 13 | ''' RibbonType: All • Assembly • Drawing • Part • ZeroDoc 14 | ''' 15 | Public Enum RibbonType 16 | ''' 17 | ''' Adds the control to all Tool Ribbons. 18 | ''' 19 | All 20 | ''' 21 | ''' Add the control to the Assembly Tool Ribbon. 22 | ''' 23 | Assembly 24 | ''' 25 | ''' Add the control to the Drawing Tool Ribbon. 26 | ''' 27 | Drawing 28 | ''' 29 | ''' Add the control to the Solid Part and Sheet Metal Part Tool Ribbons. 30 | ''' 31 | Part 32 | ''' 33 | ''' Add the control to the No Documents Open Tool Ribbon. 34 | ''' 35 | ZeroDoc 36 | End Enum 37 | 38 | ''' 39 | ''' AddinBaseClass object to be used referenced by this class. 40 | ''' 41 | Private _Addin As AddinBaseClass 42 | 43 | ''' 44 | ''' Returns a collection of Inventor ControlDefinitions. 45 | ''' 46 | ''' [Inventor.ControlDefinitions] 47 | Public ReadOnly Property ControlDefs() As ControlDefinitions 48 | Get 49 | Return _Addin.InvApp.CommandManager.ControlDefinitions 50 | End Get 51 | End Property 52 | 53 | ''' 54 | ''' Returns the active CommandControl object from the current panel of the active environment. 55 | ''' 56 | ''' [CommandControl] 57 | Public ReadOnly Property ButtonControl As CommandControl 58 | Get 59 | Return _Addin.InvApp.UserInterfaceManager.ActiveEnvironment.Ribbon.RibbonTabs.Item(TabInternalName) _ 60 | .RibbonPanels.Item(PanelInternalName).CommandControls.Item(ButtonInternalName) 61 | End Get 62 | End Property 63 | 64 | ''' 65 | ''' [Required] The display name of the Button. 66 | ''' 67 | Public Property ButtonName As String 68 | ''' 69 | ''' [Required] A unique identification name for the button. 70 | ''' 71 | ''' Best Practice: Use legible name with no spaces. 72 | ''' Format example: MyCompany_MyAddin_ButtonName 73 | ''' 74 | Public ButtonInternalName As String 75 | ''' 76 | ''' [Optional] Text to be displayed in tool tip when hovering over the button. 77 | ''' 78 | Public ToolTip As String 79 | ''' 80 | ''' [Optional] Small icon to be displayed on button. Size 16px X 16px 81 | ''' 82 | ''' Accepted Image Types: BMP • JPG • PNG 83 | ''' 84 | ''' Note: ButtonName is always displayed if an icon is not set. 85 | ''' 86 | Public SmallIcon As Bitmap 87 | ''' 88 | ''' [Optional] Large icon to be displayed on button. Size 32px X 32px 89 | ''' 90 | ''' Accepted Image Types: BMP • JPG • PNG 91 | ''' 92 | ''' Note: ButtonName is always displayed if an icon is not set. 93 | ''' 94 | Public LargeIcon As Bitmap 95 | ''' 96 | ''' [True] Shows the button name and icon. (Default) 97 | ''' 98 | ''' [False] Hides the button name and only displays the icon. 99 | ''' 100 | ''' Note: ButtonName is always displayed if an icon is not set. 101 | ''' 102 | Public ShowButtonText As Boolean = True 103 | ''' 104 | ''' [True](Default) Displays button using the LargeIcon. 105 | ''' 106 | ''' [False] Displays button using the SmallIcon. 107 | ''' 108 | ''' Note: If LargeIcon is not set then the SmallIcon is scaled. 109 | ''' 110 | Public LargeButtonFormat As Boolean = True 111 | ''' 112 | ''' [Required] The display name of the ribbon panel that the button will be added to. 113 | ''' 114 | ''' This name is used only if the ribbon panel needs to be created. 115 | ''' 116 | Public PanelName As String 117 | ''' 118 | ''' [Required] The unique identification name of the panel that the button will be added to. 119 | ''' 120 | ''' This will be used as the internal name of the ribbon panel if it is to be created. 121 | ''' 122 | ''' Best Practice: Use legible name with no spaces. 123 | ''' Format example: MyCompany_MyAddin_PanelName 124 | ''' 125 | Public PanelInternalName As String 126 | ''' 127 | ''' [Required] The display name of the ribbon tab that includes the panel that holds the button. 128 | ''' 129 | ''' This name is used if the ribbon tab needs to be created. 130 | ''' 131 | Public TabName As String 132 | ''' 133 | ''' [Required] The unique identification name of the ribbon tab that includes the panel that holds the button. 134 | ''' 135 | ''' This will be used as the internal name of the ribbon tab if it is to be created. 136 | ''' 137 | ''' Best Practice: Use legible name with no spaces. 138 | ''' Format example: MyCompany_MyAddin_TabName 139 | ''' 140 | Public TabInternalName As String 141 | ''' 142 | ''' [True] Displays an expanding tool-tip that can hold a short summary of the command and an image or video. 143 | ''' 144 | ''' [False](Default) Displays the standard tool-tip and does not load the progressive tool-tip objects. 145 | ''' 146 | Public Progressive As Boolean 147 | ''' 148 | ''' [Optional] Title displayed at the top of the progressive tool-tip. 149 | ''' 150 | ''' Ignored if Progressive is set to [False]. 151 | ''' 152 | Public ProgressiveTitle As String 153 | ''' 154 | ''' Summary or Description text presented in the progressive tool-tip window. 155 | ''' 156 | ''' Ignored if Progressive is set to [False]. 157 | ''' 158 | Public ProgressiveDesc As String 159 | ''' 160 | ''' An Image presented in the progressive tool-tip window. 161 | ''' 162 | ''' Accepted Image Types: BMP • JPG • PNG 163 | ''' 164 | ''' Ignored if Progressive is set to [False]. 165 | ''' 166 | Public ProgressiveImage As Image 167 | ''' 168 | ''' An Video presented in the progressive tool-tip window. 169 | ''' 170 | ''' [String] Video stream path or URL. 171 | ''' 172 | ''' Ignored if Progressive is set to [False]. 173 | ''' 174 | Public ProgressiveVideo As String 175 | ''' 176 | ''' [Optional] Holds a list of RibbonType that define which Tool Ribbons the control will be added too. 177 | ''' 178 | ''' Note: If no RibbonTypes are added to the list then the ControlDefinition will be created but not added to the UI. 179 | ''' 180 | Public IncludeInRibbons As List(Of RibbonType) 181 | ''' 182 | ''' The [ButtonDefinition] object for the current [ControlDefinition]. 183 | ''' 184 | Public ButtonDefinition As ButtonDefinition 185 | ''' 186 | ''' The [CommandControl] object for the current [ControlDefinition]. 187 | ''' 188 | Public ButtonCommand As CommandControl 189 | 190 | ''' 191 | ''' Creates a new instance of the AddinControlDefinitionBaseClass. 192 | ''' 193 | ''' [AddinBaseClass] AddinBaseClass object to be used referenced by this class. 194 | Sub New(ByVal Addin As AddinBaseClass) 195 | 'Needed to Initialize the AxHost... 196 | MyBase.New(CLID) 197 | 198 | 'Pass the Addin Object. 199 | _Addin = Addin 200 | End Sub 201 | 202 | ''' 203 | ''' Creates a [ButtonDefinitionObject] for Autodesk Inventor command buttons. 204 | ''' 205 | ''' [ButtonDefinitionObject] 206 | Public Function CreateControlDefButton() As ButtonDefinitionObject 207 | 208 | 'Convert the bitmaps to IPictureDisp 209 | Dim ICO16 As IPictureDisp = Nothing, ICO32 As IPictureDisp = Nothing 210 | 211 | If Not SmallIcon Is Nothing Then ICO16 = DirectCast(GetIPictureDispFromPicture(SmallIcon), IPictureDisp) 212 | If Not LargeIcon Is Nothing Then ICO32 = DirectCast(GetIPictureDispFromPicture(LargeIcon), IPictureDisp) 213 | 214 | 'Create The Button Definition. 215 | ButtonDefinition = ControlDefs.AddButtonDefinition(ButtonName, ButtonInternalName, CommandTypesEnum.kQueryOnlyCmdType, CLID, ToolTip, ToolTip, ICO16, ICO32) 216 | 217 | 'If we have not set the control to have a progressive tool tip then go ahead and return the ButtonDefinition. 218 | If Not Progressive Then Return ButtonDefinition 219 | 220 | 'Enable the progressive tool tip. 221 | ButtonDefinition.ProgressiveToolTip.IsProgressive = True 222 | 223 | 'If a title was defined then add it. 224 | If Not ProgressiveTitle Is Nothing Then ButtonDefinition.ProgressiveToolTip.Title = ProgressiveTitle 225 | 226 | 'If there is an extended description then add it. 227 | If Not ProgressiveDesc Is Nothing Then ButtonDefinition.ProgressiveToolTip.ExpandedDescription = ProgressiveDesc 228 | 229 | On Error Resume Next 230 | 'If an image was passed then include it. 231 | If Not ProgressiveImage Is Nothing Then ButtonDefinition.ProgressiveToolTip.Image = DirectCast(GetIPictureDispFromPicture(ProgressiveImage), IPictureDisp) 232 | 233 | 'If an image was passed then include it as well. 234 | If Not ProgressiveVideo Is Nothing Then ButtonDefinition.ProgressiveToolTip.Video = ProgressiveVideo 235 | 236 | 'Return the definition. 237 | Return ButtonDefinition 238 | End Function 239 | 240 | ''' 241 | ''' Adds the Button to the Inventor UI based on specified Panel, Tab, and Ribbon. 242 | ''' 243 | Public Function AddButtonToUI() As CommandControl 244 | 'If no tool ribbons were specified then we need to log the error and exit. 245 | If IncludeInRibbons.Count = 0 Then 246 | _Addin.Logging.WriteToErrorLog("Could not add " & ButtonName & " to the Inventor UI because no Tool Ribbons were specified.", _Addin) 247 | Return Nothing 248 | End If 249 | 250 | Dim ASY_RIB, DWG_RIB, PRT_RIB, NODOC_RIB As Ribbon 251 | Try 252 | 'Add the Button to all Tool Ribbons. 253 | If IncludeInRibbons.Contains(RibbonType.All) Then 254 | ASY_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Assembly") 255 | DWG_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Drawing") 256 | PRT_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Part") 257 | NODOC_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("ZeroDoc") 258 | AddButtonDefinitionToPanel(ASY_RIB) 259 | AddButtonDefinitionToPanel(DWG_RIB) 260 | AddButtonDefinitionToPanel(PRT_RIB) 261 | AddButtonDefinitionToPanel(NODOC_RIB) 262 | Else 263 | 'Add the Button to only the specified Tool Ribbons. 264 | For Each SelectedRibbon In IncludeInRibbons 265 | Select Case SelectedRibbon 266 | Case RibbonType.Assembly 267 | 'Assembly Ribbon 268 | ASY_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Assembly") : AddButtonDefinitionToPanel(ASY_RIB) 269 | Case RibbonType.Drawing 270 | 'Drawing Ribbon 271 | DWG_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Drawing") : AddButtonDefinitionToPanel(DWG_RIB) 272 | Case RibbonType.Part 273 | 'Part Ribbon 274 | PRT_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("Part") : AddButtonDefinitionToPanel(PRT_RIB) 275 | Case RibbonType.ZeroDoc 276 | 'Zero Doc Ribbon 277 | NODOC_RIB = _Addin.InvApp.UserInterfaceManager.Ribbons.Item("ZeroDoc") : AddButtonDefinitionToPanel(NODOC_RIB) 278 | Case Else 279 | 'Do Nothing 280 | End Select 281 | Next 282 | End If 283 | Catch ex As Exception 284 | _Addin.Logging.WriteToErrorLog("Could not add " & ButtonName & " to the Inventor UI because no Tool Ribbons were specified.", _Addin) 285 | Return Nothing 286 | Finally 287 | ASY_RIB = Nothing 288 | DWG_RIB = Nothing 289 | PRT_RIB = Nothing 290 | NODOC_RIB = Nothing 291 | End Try 292 | Return ButtonCommand 293 | End Function 294 | 295 | ''' 296 | ''' Find a Ribbon Tab using the TabInteranlName specified in the ControlDefinition. 297 | ''' Returns the RibbonTab or Nothing if it is not found. 298 | ''' 299 | ''' [Inventor.Ribbon] Ribbon to search. 300 | ''' [Boolean](Optional | Default = True) Creates a new Ribbon Tab if not found. 301 | ''' [Inventor.RibbonTab] or Nothing 302 | Private Function FindRibbonTab(ByVal Ribbon As Ribbon, Optional Create As Boolean = True) As RibbonTab 303 | Try 304 | Return Ribbon.RibbonTabs.Item(TabInternalName) 305 | Catch ex As Exception 306 | If Create Then 307 | Return CreateRibbonTab(Ribbon) 308 | Else 309 | Return Nothing 310 | End If 311 | End Try 312 | End Function 313 | 314 | ''' 315 | ''' Creates a new Ribbon Tab using the TabName specified in the ControlDefinition. 316 | ''' Returns the RibbonTab or Nothing if it could not be created. 317 | ''' 318 | ''' [Inventor.Ribbon] The ribbon object to add the new Tab to. 319 | ''' [Inventor.Ribbon] or Nothing 320 | Private Function CreateRibbonTab(ByVal Ribbon As Ribbon) As RibbonTab 321 | Return Ribbon.RibbonTabs.Add(TabName, TabInternalName, CLID, "id_TabTools") 322 | End Function 323 | 324 | ''' 325 | ''' Find a Ribbon Panel using the PanelInteranlName specified in the ControlDefinition. 326 | ''' Returns the RibbonPanel or Nothing if it is not found. 327 | ''' 328 | ''' [Inventor.RibbonTab] RibbonTab to search. 329 | ''' [Boolean](Optional | Default = True) Creates a new Ribbon Panel if not found. 330 | ''' [Inventor.RibbonPanel] or Nothing 331 | Private Function FindRibbonPanel(ByVal RibbonTab As RibbonTab, Optional Create As Boolean = True) As RibbonPanel 332 | Try 333 | Return RibbonTab.RibbonPanels.Item(PanelInternalName) 334 | Catch ex As Exception 335 | If Create Then 336 | Return CreateRibbonPanel(RibbonTab) 337 | Else 338 | Return Nothing 339 | End If 340 | End Try 341 | End Function 342 | 343 | ''' 344 | ''' Creates a new Ribbon Panel using the PanelName specified in the ControlDefinition. 345 | ''' Returns the RibbonPanel or Nothing if it could not be created. 346 | ''' 347 | ''' [Inventor.RibbonTab] RibbonTab to search. 348 | ''' [Inventor.RibbonPanel] or Nothing 349 | Private Function CreateRibbonPanel(ByVal RibbonTab As RibbonTab) As RibbonPanel 350 | Return RibbonTab.RibbonPanels.Add(PanelName, PanelInternalName, CLID) 351 | End Function 352 | 353 | ''' 354 | ''' Creates a CommandControl and adds it to the specified Ribbon Panel. 355 | ''' Returns the CommandControl or Nothing if it could not be created. 356 | ''' 357 | ''' [Inventor.RibbonPanel] Ribbon Panel that gets the button definition. 358 | ''' [Inventor.CommandControl] or Nothing 359 | Private Function CreatCommandControl(ByVal RibbonPanel As RibbonPanel) As CommandControl 360 | Try 361 | Dim ControlButton As CommandControl = RibbonPanel.CommandControls.AddButton(ButtonDefinition) 362 | With ControlButton 363 | .UseLargeIcon = LargeButtonFormat 364 | .ShowText = ShowButtonText 365 | End With 366 | Return ControlButton 367 | Catch ex As Exception 368 | Return Nothing 369 | End Try 370 | End Function 371 | 372 | ''' 373 | ''' Deletes the Command Control and ControlDefinition for the current control. 374 | ''' 375 | Public Sub RemoveCommand() 376 | On Error Resume Next 377 | _Addin.InvApp.CommandManager.ControlDefinitions.Item(ButtonInternalName).Delete() 378 | End Sub 379 | 380 | ''' 381 | ''' Adds the ButtonDefinition to the specified RibbonPanel. 382 | ''' This sub will try to find or create the specified RibbonTab and RibbonPanel defined in the ControlDefinition. 383 | ''' 384 | ''' [Inventor.Ribbon] The ribbon object to add the new items to. 385 | Private Sub AddButtonDefinitionToPanel(ByVal Ribbon As Ribbon) 386 | 387 | Dim rTab As RibbonTab, rPanel As RibbonPanel 388 | Try 389 | 'First validate that we have the needed parameters, else throw a specific error for each one. 390 | If TabName = Nothing OrElse TabName = "" Then Throw New ArgumentException("TabName is required when adding a command button to the UI!", ButtonName) 391 | If TabInternalName = Nothing OrElse TabInternalName = "" Then Throw New ArgumentException("TabInternalName is required when adding a command button to the UI!", ButtonName) 392 | If PanelName = Nothing OrElse PanelName = "" Then Throw New ArgumentException("PanelName is required when adding a command button to the UI!", ButtonName) 393 | If PanelInternalName = Nothing OrElse PanelInternalName = "" Then Throw New ArgumentException("PanelInternalName is required when adding a command button to the UI!", ButtonName) 394 | 395 | rTab = FindRibbonTab(Ribbon, True) 396 | rPanel = FindRibbonPanel(rTab, True) 397 | 398 | 'If the rTab & rPanel have been found then add the command. 399 | If Not rTab Is Nothing AndAlso Not rPanel Is Nothing Then ButtonCommand = CreatCommandControl(rPanel) 400 | 401 | Catch ex As ArgumentException 402 | Dim Message As String = "A value for the parameter " & ex.ParamName & 403 | " was not specified during the creation of the """ & ButtonName & 404 | """ ButtonDefinition." & vbNewLine & "The control could not be added to the UI." 405 | _Addin.Logging.WriteToErrorLog(Message, _Addin, Ex:=ex) 406 | Catch ex As Exception 407 | _Addin.Logging.WriteToErrorLog("An error occurred while trying to add the " & ButtonName & " to the " & PanelName & " panel.", _Addin, Ex:=ex) 408 | Finally 409 | rTab = Nothing 410 | rPanel = Nothing 411 | End Try 412 | End Sub 413 | 414 | ''' 415 | ''' Turns the visibility of the Command Button On or Off. 416 | ''' 417 | ''' [Boolean] 418 | ''' [String](Optional | Default = Calling Command Button) Specifies a specific button to turn on/off visibility. 419 | ''' If not specified the defaults to internal name of command calling the method. 420 | Public Sub ChangeButtonVisibility(Visibile As Boolean, Optional InternalName As String = Nothing) 421 | Dim cPanel As RibbonPanel = _Addin.InvApp.UserInterfaceManager.ActiveEnvironment.Ribbon.RibbonTabs.Item(TabInternalName).RibbonPanels.Item(PanelInternalName) 422 | Dim inName As String = Nothing 423 | If Not InternalName Is Nothing Then 424 | inName = InternalName 425 | Else 426 | inName = ButtonInternalName 427 | End If 428 | 429 | Select Case Visibile 430 | Case True 431 | cPanel.CommandControls.Item(inName).Visible = True 432 | Case False 433 | cPanel.CommandControls.Item(inName).Visible = False 434 | End Select 435 | End Sub 436 | 437 | End Class --------------------------------------------------------------------------------