Access/Use "File Open - Options"-Dialog Via API

Access/Use "File Open - Options"-Dialog Via API

carsten.seeber
Participant Participant
202 Views
3 Replies
Message 1 of 4

Access/Use "File Open - Options"-Dialog Via API

carsten.seeber
Participant
Participant

Hello,

I have the following scenario: "Execute PlaceComponent command with possibility to specifiy options via API".

The filepath of the component is known and also the required modelstate. But I want to give the user the possibility to specify e.g. "DesignViewRepresentation" or "PositionalRepresentation" for IAM.

 

Do I have the possibilty to call this shown GUI and pre-set "ModelState" (Modellzustand) and extract the values afterwards?

carstenseeber_0-1750926392419.png

 

For the placement I found the following solutions:

 

- A: Placing using command execution => How to show Options-Dialog and apply Options?

CommandManager commandManager = inventorApplication.CommandManager;
commandManager.PostPrivateEvent(PrivateEventTypeEnum.kFileNameEvent, documentFileName);

ControlDefinition placeComponentControl = commandManager.ControlDefinitions["AssemblyPlaceComponentCmd"];
placeComponentControl.Execute2(true);

Source: https://modthemachine.typepad.com/my_weblog/2009/03/running-commands-using-the-api.html

 

- B: Placing using "Occurrences.AddWithOptions" => How to show Options-Dialog and extract Options?

' Set the representations to use when creating the occurrence.
Call oOptions.Add("ModelState", "MyModelState")
Call oOptions.Add("PositionalRepresentation", "MyPositionalRep")
Call oOptions.Add("DesignViewRepresentation", "MyDesignViewRep")
Call oOptions.Add("DesignViewAssociative", True)

' Add the occurrence.
Dim oOcc As ComponentOccurrence
Set oOcc = oAsmCompDef.Occurrences.AddWithOptions("C:\Temp\Reps.iam", oMatrix, oOptions)

Source: https://help.autodesk.com/view/INVNTOR/2022/ENU/?guid=OccurrenceAddWithOptions_Sample

 

If possible I would prefer a solution to use Options with solution A because with that approach the user can choose placement position and do multiple placements.

 

Basically I could "re-build" custom GUIs for Option Dialogs, but then I could only use solution B. Maybe you guys have a suitable solution for my problem. 

 

Thanks in advance

0 Likes
Accepted solutions (1)
203 Views
3 Replies
Replies (3)
Message 2 of 4

WCrihfield
Mentor
Mentor

Hi @carsten.seeber.  This can be a relatively complex scenario to fully describe or explain, but I think we may be able to fully automate all of that the way you want to be able to, but would have to do it entirely with Inventor API & vb.net, without any 'command' (ControlDefinition) execution.  It seems like we can do pretty much everything that is involved in that whole process.  We can create an Inventor.FileDialog and show it, for 'insert' instead of just open or save.  We can enable the Options button in that dialog.  We can catch the event of the user clicking that options button.  We can get the resulting options chosen.  We can start a user interaction session which pauses code execution, and waits on the user to do stuff, and can react to events they do during that time...for things like clicking where they want to place instances, and can simulate the 'preview' of the model following their mouse.  We can then use the Occurrences.AddWithOptions method mentioned above to place instances where all the click locations.  And so on.  But I would have to almost write a book here to explain it all.  All that would probably be best done within an Inventor Add-In, instead of with simple iLogic rules though.  Might be possible to do with external iLogic rules, but would probably be difficult to manage properly.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 4

WCrihfield
Mentor
Mentor
Accepted solution

Here are some links to Inventor API online help pages that may help you along the way, if attempting the add-in route.  I honestly have not done a lot with client preview graphics besides a little dabbling yet, but the thought was to use that to cause the preview of the selected source model, as a component occurrence, to follow the mouse as it moves, during the interaction events session.  I have done 'dragging' simulation before, which is similar, but not the same.  Most of the rest I have some experience with.  But I do not do add-ins myself, due to restrictions where I work.  But there are a lot of others here with plenty of experience & expertise in those areas.

Application.CreateFileDialog 

FileDialog 

FileDialog.InsertMode 

FileDialog.OptionsEnabled 

FileDialog.ShowOpen 

FileDialog.OptionValues 

FileDialog.FileDialogEvents 

FileDialogEvents.OnOptions 

CommandManager.CreateInteractionEvents 

InteractionEvents.MouseEvents 

MouseEvents.OnMouseMove 

MouseEvents.OnMouseClick 

InteractionEvents.InteractionGraphics 

InteractionGraphics.PreviewClientGraphics 

ClientGraphics.AddNode 

GraphicsNode.AddComponentGraphics 

InteractionEvents.Start 

InteractionEvents.Stop 

ComponentOccurrences.AddWithOptions 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 4 of 4

carsten.seeber
Participant
Participant

Thank you very much for your input @WCrihfield. And sorry for the late reply. I had to test multiple things to get things working.

I ended up with the following solution: Implementing a custom "Component Placer" with a "Re-Build" of "File open - Options"-GUI as pre-processing.

 

The problem in my case was, that we have an external AddIn, which registered a listener to execute a function everytime a "FileDialog.ShowOpen" was executed... and I found no way to suppress this "external" EventListening.. Maybe someone has an idea?

 

----

 

In case someone is interested in my solution, here is the coding:

 

InteractiveComponentPlacer.cs

public class InteractiveComponentPlacer
{
    private readonly Application _invApp;
    private readonly AssemblyDocument _asmDoc;
    private readonly string _componentPath;
    
    private readonly NameValueMap _loadOptions; // Options for placement/insertion
    private NameValueMap _openOptions; // Options required for preview image creation (hidden load)

    private InteractionEvents _interaction;
    private MouseEvents _mouseEvents;
    private KeyboardEvents _keyboardEvents;

    private GraphicsNode _previewContainer;
    private Document _compDoc;

    private Action _onFinished;

    public InteractiveComponentPlacer(Application inventorApp, string componentPath, NameValueMap loadOptions)
    {
        _invApp = inventorApp;
        _componentPath = componentPath;
        _loadOptions = loadOptions;
        _asmDoc = _invApp.ActiveDocument as AssemblyDocument ?? throw new InvalidOperationException("Aktives Dokument ist keine Baugruppe.");
        SetOpenOptions(loadOptions);
    }

    /// <summary>
    /// Since we need to open the document in hidden mode we have to extract the valid
    /// parameters for document function "OpenWithOptions()"
    /// see @ https://help.autodesk.com/view/INVNTOR/2025/ENU/?guid=Documents_OpenWithOptions
    /// </summary>
    /// <param name="loadOptions"></param>
    private void SetOpenOptions(NameValueMap loadOptions)
    {
        // At first copy given load options (insertion mode)
        _openOptions = _invApp.TransientObjects.CreateNameValueMap();
        for (int i = 1; i <= loadOptions.Count; ++i)
        {
            string name = loadOptions.Name[i];
            _openOptions.Add(name, loadOptions.Value[name]);
        }

        // Remove via validator false open options (we do not require info about removed options)
        InventorOpenOptionsValidator.ValidateNameValueMap(_componentPath, _openOptions);
    }

    public void StartPlacement(Action onFinished = null)
    {
        _onFinished = onFinished;

        _interaction = _invApp.CommandManager.CreateInteractionEvents();
        _interaction.InteractionDisabled = false;

        if (_invApp.LanguageCode.Equals("de-DE"))
        {
            _interaction.StatusBarText = "Klicke zum Platzieren. ESC zum Abbrechen.";
        }
        else
        {
            _interaction.StatusBarText = "Click to place. ESC to cancel.";
        }
        _interaction.OnTerminate += OnInteractionTerminated;

        _mouseEvents = _interaction.MouseEvents;
        _keyboardEvents = _interaction.KeyboardEvents;

        _mouseEvents.MouseMoveEnabled = true;
        _mouseEvents.OnMouseMove += OnMouseMove;

        _mouseEvents.OnMouseClick += OnMouseClick;
        _keyboardEvents.OnKeyDown += OnKeyDown;

        _interaction.Start();

        CreatePreviewGraphics();
        SetPreviewContainerTransformation();
    }

    private void OnMouseMove(MouseButtonEnum button, ShiftStateEnum shiftKeys, Point modelPosition, Point2d viewPosition, View view)
    {
        if (_previewContainer != null)
        {
            var matrix = _invApp.TransientGeometry.CreateMatrix();
            matrix.SetTranslation(_invApp.TransientGeometry.CreateVector(modelPosition.X, modelPosition.Y, modelPosition.Z));

            _previewContainer.Transformation = matrix;

            view.Update();
        }
    }

    private void OnMouseClick(MouseButtonEnum button, ShiftStateEnum shiftKeys, Point modelPosition, Point2d viewPosition, View view)
    {
        if (button != MouseButtonEnum.kLeftMouseButton)
        {
            return;
        }

        var matrix = _invApp.TransientGeometry.CreateMatrix();
        matrix.SetTranslation(_invApp.TransientGeometry.CreateVector(modelPosition.X, modelPosition.Y, modelPosition.Z));
        _asmDoc.ComponentDefinition.Occurrences.AddWithOptions(_componentPath, matrix, _loadOptions);

        // Each insertion "destroys" existing preview Container. It is necessary to build it again
        // so that OnMouseMove will display it correctly for further insertion
        CreatePreviewGraphics();
        SetPreviewContainerTransformation(matrix);
    }

    private void OnKeyDown(int keyCode, ShiftStateEnum shiftKeys)
    {
        if (keyCode == 27) // ESC
        {
            _interaction.Stop(); // Triggert OnInteractionTerminated
        }
    }

    private void OnInteractionTerminated()
    {
        _interaction.OnTerminate -= OnInteractionTerminated;

        _mouseEvents.OnMouseMove -= OnMouseMove;
        _mouseEvents.OnMouseClick -= OnMouseClick;
        _keyboardEvents.OnKeyDown -= OnKeyDown;

        _asmDoc.Views[1].Update();

        _compDoc?.Close(true);

        _interaction = null;
        if (_previewContainer != null)
        {
            _previewContainer.Delete();
        }

        _onFinished?.Invoke(); // Callback nach Abschluss
    }

    private void CreatePreviewGraphics()
    {
        if(_previewContainer != null)
        {
            _previewContainer.Delete();
        }

        _compDoc = _invApp.Documents.OpenWithOptions(_componentPath, _openOptions, false);

        var clientGraphics = _interaction.InteractionGraphics.PreviewClientGraphics;
        int nodeId = Guid.NewGuid().GetHashCode();
        _previewContainer = clientGraphics.AddNode(nodeId);

        ComponentDefinition compDef = null;

        if (_compDoc is PartDocument partDoc)
        {
            compDef = partDoc.ComponentDefinition as ComponentDefinition;
        }
        else if (_compDoc is AssemblyDocument asmDoc)
        {
            compDef = asmDoc.ComponentDefinition as ComponentDefinition;
        }
        else
        {
            throw new InvalidOperationException("Nur IPT oder IAM werden unterstützt.");
        }

        _previewContainer.AddComponentGraphics(compDef);
        _previewContainer.OverrideOpacity = 0.7;
    }

    private void SetPreviewContainerTransformation(Matrix matrix = null)
    {
        if(matrix == null)
        {
            // Initiale Transformation setzen (z. B. Ursprung)
            var initialMatrix = _invApp.TransientGeometry.CreateMatrix();
            initialMatrix.SetTranslation(_invApp.TransientGeometry.CreateVector(0, 0, 0), false);

            matrix = initialMatrix;
        }

        _previewContainer.Transformation = matrix;
    }
}

 

InventorOpenOptionsValidator.cs

/// <summary>
/// See https://help.autodesk.com/view/INVNTOR/2025/ENU/?guid=Documents_OpenWithOptions for more information
/// </summary>
public static class InventorOpenOptionsValidator
{
    /// <summary>
    /// Valid open options based on filetype
    /// </summary>
    private static readonly Dictionary<string, HashSet<string>> validOptions = new Dictionary<string, HashSet<string>>()
    {
        { 
            "Part", new HashSet<string>
            {
                "DesignViewRepresentation",
                "ModelState",
                "DeferFlatPatternUpdate",
                "FileVersionOption",
                "Password",
                "SkipAllUnresolvedFiles"
            }
        },
        {
            "Assembly", new HashSet<string>
            {
                "DesignViewRepresentation",
                "PositionalRepresentation",
                "ModelState",
                "ExpressModeBehavior",
                "FileVersionOption",
                "Password",
                "SkipAllUnresolvedFiles"
            }
        },
        {
            "Drawing", new HashSet<string>
            {
                "DeferUpdates",
                "FileVersionOption",
                "Password",
                "SkipAllUnresolvedFiles",
                "ImportNonInventorDWG"
            }
        }
    };

    /// <summary>
    /// Uses given options 
    /// </summary>
    /// <param name="filePath"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static List<string> ValidateNameValueMap(string filePath, NameValueMap options)
    {
        List<string> removedMessages = new List<string>();
        string fileType = GetInventorFileType(filePath);

        if (!validOptions.ContainsKey(fileType))
        {
            removedMessages.Add($"Unbekannter Dateityp: {fileType}");
            return removedMessages;
        }

        HashSet<string> allowedKeys = validOptions[fileType];
        List<string> keysToRemove = new List<string>();

        for (int i = 1; i <= options.Count; i++)
        {
            string key = options.Name[i];
            if (!allowedKeys.Contains(key))
            {
                keysToRemove.Add(key);
            }
        }

        foreach (string key in keysToRemove)
        {
            options.Remove(key);
            removedMessages.Add($"Ungültiges Schlüssel-Wert-Paar entfernt: '{key}' für Dateityp '{fileType}'");
        }

        return removedMessages;
    }

    private static string GetInventorFileType(string filePath)
    {
        string extension = Path.GetExtension(filePath).ToLowerInvariant();
        switch (extension)
        {
            case ".ipt": return "Part";
            case ".iam": return "Assembly";
            case ".idw":
            case ".dwg": return "Drawing";
            default: return "Unknown";
        }
    }
}

 

Usage:

var placer = new InteractiveComponentPlacer(inventorApplication, documentFileName, loadOptions);
placer.StartPlacement(() =>
{
    // Can be filled with additional methods, which are executed AFTER command finished
});