Community
Inventor Programming - iLogic, Macros, AddIns & Apprentice
Inventor iLogic, Macros, AddIns & Apprentice Forum. Share your knowledge, ask questions, and explore popular Inventor topics related to programming, creating add-ins, macros, working with the API or creating iLogic tools.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Getting Inventor Application object in AddIns

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
awatt
546 Views, 11 Replies

Getting Inventor Application object in AddIns

A question regarding best practices.

 

When coding methods for an Inventor addin, which is preferred, passing m_inventorApplication from StandardAddInServer.CS (or .VB) to any class methods or getting the inventor object in each class / method with Marshal.GetActiveObject("InventorApplication") ?

 

I also ask because .Net CORE doesn't play nicely with Marshal, and if things go in that direction, the C# DllImport workaround is painful.

Labels (2)
11 REPLIES 11
Message 2 of 12
Frederick_Law
in reply to: awatt

Don't understand what you're asking.

 

In VB addin template:

#Region "Data"
    ' Inventor application object.
    Private m_inventorApplication As Application
#End Region
#Region "ApplicationAddInServer Members"
    Public Sub Activate(ByVal addInSiteObject As ApplicationAddInSite, ByVal firstTime As Boolean
                        ) Implements ApplicationAddInServer.Activate
      Try
        ' This method is called by Inventor when it loads the AddIn.
        ' The AddInSiteObject provides access to the Inventor Application object.
        ' The FirstTime flag indicates if the AddIn is loaded for the first time.
        ' Initialize AddIn members.
        m_inventorApplication = addInSiteObject.Application
      Catch ex As Exception
        Windows.Forms.MessageBox.Show(ex.ToString())
      End Try
    End Sub

#End Region

 

Message 3 of 12
awatt
in reply to: awatt

If I have other classes/methods in the same project but in other .vb files that require the application object is it best practice to pass the Inventor Application object to them as a parameter (m_inventorApplication) or have them get the object themselves?

 

Message 4 of 12
Frederick_Law
in reply to: awatt

I passed m_inventorApplication to another module.

 

Used oApp = addInSiteObject.Application in the class with Window Form for dialog.

 

They're converted from VBA macro to VB.Net.

 

Now I'm thinking, could I make m_inventorApplication public for both?

Message 5 of 12
awatt
in reply to: awatt

A good idea.  I just added a method to the StandardAddInServer class that will return the object.  It should be pretty stable. I'll start some testing.

(c#)

public Inventor.Application inventorAppObj(Inventor.ApplicationAddInSite addInSiteObject)
{
return addInSiteObject.Application;
}

Message 6 of 12
awatt
in reply to: awatt

Thinking further on this, it's not going to work.

 

The Activate method recieves the ApplicationAddInSite from inventor when it loads.

The method I just made won't get it from anywhere. I don't know what I was thinking.

 

I believe the most stable solution is to rewrite all my custom methods to accept an application object and pass it to them from within the activate method where it's available.

 

Message 7 of 12
etaCAD
in reply to: awatt

I use the Inventor object than comes from the Activate methode of your addin and store it in a global variable.

 

If you use Marshal to get Inventor you don't know which one you get when several Inventor windows are open.

Andreas
etaCAD

Message 8 of 12
Michael.Navara
in reply to: awatt

The best practice is to pass the Inventor application instance to constructor of your class which needs to do something with inventor. Below is the minimalistic sample of inventor addin implementation

 

class StandardAddInServer : ApplicationAddInServer
{
    Inventor.Application inventor;
    MyCommand myCommand;


    public void Activate(ApplicationAddInSite AddInSiteObject, bool FirstTime)
    {
        //Get inventor app instance
        inventor = AddInSiteObject.Application;

        //Pass the inventor app to the command class
        myCommand = new MyCommand(inventor);

        //Create buttons in ribbon
        inventor.UserInterfaceManager.Ribbons["ZeroDoc"].RibbonTabs["id_TabTools"].RibbonPanels["id_PanelP_ToolsOptions"].CommandControls.AddButton(myCommand.ButtonDefinition);
        inventor.UserInterfaceManager.Ribbons["Part"].RibbonTabs["id_TabModel"].RibbonPanels["id_PanelP_Model2DSketchCreate"].CommandControls.AddButton(myCommand.ButtonDefinition);
    }

    public void Deactivate()
    {
        //Clear all buttons from ribbon
        CommandControlsEnumerator myCommandControls = inventor.UserInterfaceManager.AllReferencedControls(myCommand.ButtonDefinition as ControlDefinition);
        foreach (CommandControl cmdCtrl in myCommandControls)
        {
            try { cmdCtrl.Delete(); }
            catch { }
        }

        //Clear button definition
        myCommand.ButtonDefinition.Delete();

        //Finalize the addin
        inventor = null;
    }

    // Obsolete
    public void ExecuteCommand(int CommandID) { }

    // Not implemented
    public object Automation => null;
}


class MyCommand
{
    private readonly Inventor.Application inventor;
    private ButtonDefinition buttonDef;
    public ButtonDefinition ButtonDefinition => buttonDef;

    public MyCommand(Inventor.Application inventor)
    {
        this.inventor = inventor;
        buttonDef = inventor.CommandManager.ControlDefinitions.AddButtonDefinition(
            "My command", "MyCommandInternalName", CommandTypesEnum.kQueryOnlyCmdType /* etc. */);
        buttonDef.OnExecute += MyCommand_OnExecute;
    }


    private void MyCommand_OnExecute(NameValueMap Context)
    {
        MessageBox.Show(inventor.ActiveDocument.DisplayName, "My command");
    }

}
Message 9 of 12
awatt
in reply to: awatt

Thank you. This helps loads. Just wrapping my brain around it. . .

So the _OnExecute method has access to the Inventor object because 'inventor' is given the inventor object when an instance of MyCommand is created? 

My methods in the past have all been static, so it's a new concept.

Message 10 of 12
Michael.Navara
in reply to: awatt

Here is modified version with renamed variables of Inventor application for better understanding.

If you pass the inventor using constructor you don't need to use them static.

 

 

class StandardAddInServer : ApplicationAddInServer
{
    Inventor.Application inventorAtAddInLevel;
    MyCommand myCommand;


    public void Activate(ApplicationAddInSite AddInSiteObject, bool FirstTime)
    {
        //Get inventor app instance
        inventorAtAddInLevel = AddInSiteObject.Application;

        //Pass the inventor app to the command class
        myCommand = new MyCommand(inventorAtAddInLevel);

        //Create buttons in ribbon
        inventorAtAddInLevel.UserInterfaceManager
            .Ribbons["ZeroDoc"]
            .RibbonTabs["id_TabTools"]
            .RibbonPanels["id_PanelP_ToolsOptions"]
            .CommandControls.AddButton(myCommand.ButtonDefinition);

        inventorAtAddInLevel.UserInterfaceManager
            .Ribbons["Part"]
            .RibbonTabs["id_TabModel"]
            .RibbonPanels["id_PanelP_Model2DSketchCreate"]
            .CommandControls.AddButton(myCommand.ButtonDefinition);
    }

    public void Deactivate()
    {
        //Clear all buttons from ribbon
        var myCommandButtonAsControlDef = myCommand.ButtonDefinition as ControlDefinition;
        var myCommandControls = 
            inventorAtAddInLevel.UserInterfaceManager.AllReferencedControls(myCommandButtonAsControlDef);

        foreach (CommandControl cmdCtrl in myCommandControls)
        {
            try { cmdCtrl.Delete(); }
            catch { /* IGNORE ALL ERRORS*/ }
        }

        //Clear button definition
        myCommand.ButtonDefinition.Delete();

        //Finalize the addin
        inventorAtAddInLevel = null;
    }

    // Obsolete
    public void ExecuteCommand(int CommandID) { }

    // Not implemented
    public object Automation => null;
}


class MyCommand
{
    private readonly Inventor.Application inventorAtMyCommandLevel;
    private ButtonDefinition buttonDef;
    public ButtonDefinition ButtonDefinition => buttonDef;

    public MyCommand(Inventor.Application inventorAsArgument)
    {
        inventorAtMyCommandLevel = inventorAsArgument;
        buttonDef = inventorAtMyCommandLevel.CommandManager.ControlDefinitions.AddButtonDefinition(
            "My command", "MyCommandInternalName", CommandTypesEnum.kQueryOnlyCmdType /* etc. */);
        buttonDef.OnExecute += MyCommand_OnExecute;
    }


    private void MyCommand_OnExecute(NameValueMap Context)
    {
        MessageBox.Show(inventorAtMyCommandLevel.ActiveDocument.DisplayName, "My command");
    }

}

 

Message 11 of 12
awatt
in reply to: awatt

A million thanks. And a Like or two.

Message 12 of 12
awatt
in reply to: awatt

I've implemented the above successfully, and would like to add I found a way to get the Application object from the Document object:

DOCUMENT.DOCUMENTINTERESTS.APPLICATION

It's not exactly well-advertised.  I tend to think of my methods as recieving only the document object, not both the application and document objects.

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report