How to 'Project Objects To Profile View' with C# from Modeless Dialog?

How to 'Project Objects To Profile View' with C# from Modeless Dialog?

tipitasa
Enthusiast Enthusiast
417 Views
3 Replies
Message 1 of 4

How to 'Project Objects To Profile View' with C# from Modeless Dialog?

tipitasa
Enthusiast
Enthusiast

How can I use the 'Project Objects To Profile View' command using the Civil 3D API, with C#, to project a selected Solid3d to the selected Profile View from a Modeless Dialog?

The API does not support this call, I followed this https://forums.autodesk.com/t5/net/how-can-i-use-project-objects-to-profile-view-with-c/td-p/1287474... topic to use the Editor.Command();

However, when I try to call this command from the Modeless Dialog, I get an 'Invalid input' exception.

My command uses this flag:

[CommandMethod("DoProjectToProfileView", CommandFlags.UsePickSet)]


This is the relevant code:

// clear the pickfirst set
_ed.SetImpliedSelection(new ObjectId[0]);

// create selection sets
ObjectId[] solidIds = { selectedSolidId };
ObjectId[] profViewIds = { _selectedProfileViewId };
var solidSelectionSet = SelectionSet.FromObjectIds(solidIds);
var profileSelectionSet = SelectionSet.FromObjectIds(profViewIds);

// project
_ed.Command("_.AECCPROJECTOBJECTSTOPROF", solidSelectionSet, "", profileSelectionSet, "");


I tried to surround the Editor.Command with using (_doc.LockDocument()), same as when calling transactions from the Modeless dialog, but it does not help, same exception shows.

If I Close(); the dialog and then try to do the above code, I again get the same exception.

I tried to use the dynamic variable, and got half a result. I can successfully run the command, but cannot set the selection sets.

dynamic doc = _doc.GetAcadDocument();
doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r");

// this works as well:
doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF ");

// but none of these do!
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, "", profileSelectionSet);
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, "", profileSelectionSet, "");
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, "\r", profileSelectionSet);
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, "\r", profileSelectionSet, "");
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, " ", profileSelectionSet);
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, " ", profileSelectionSet, "");
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, "\r", profileSelectionSet, "\r");
            doc.SendCommand("_.AECCPROJECTOBJECTSTOPROF\r", solidSelectionSet, " ", profileSelectionSet, " ");

 
What else could I try, or do not understand? Calling the C3D commands is always a heavy guesswork for me, on trying to replicate the C3D workflow.

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

hippe013
Advisor
Advisor

I find that sometimes going over to LISP might help in understanding what arguments a particular method requires. 

 

 

(princ "\nSelect Solids: ")
(setq ss (ssget '(( 0 . "3DSOLID"))))
(setq ent (car (entsel "\nSelect Profile View: ")))
(command "_.AECCPROJECTOBJECTSTOPROF" ss "" ent "")

 

 

The above LISP code will run and then display the dialog for choosing the projection style. 

Note that the command is being passed a selection set for the solid's argument, but a single objectID for the profile view argument. 

 

Using VB.NET (sorry, not sorry), I was successful with the following code: 

 

 

Dim selOpt As New PromptSelectionOptions
selOpt.MessageForAdding = vbCrLf & "Select Solids:"

Dim tvs(0) As TypedValue
tvs.SetValue(New TypedValue(DxfCode.Start, "3DSOLID"), 0)

Dim selFilter As New SelectionFilter(tvs)

Dim selRes As PromptSelectionResult = ed.GetSelection(selOpt, selFilter)

If selRes.Status <> PromptStatus.OK Then Exit Sub

Dim opt As New PromptEntityOptions(vbCrLf & "Select Profile View: ")
opt.SetRejectMessage(vbCrLf & "Selected entity must be a Profile View. Try again.")
opt.AddAllowedClass(GetType(ProfileView), True)

Dim res As PromptEntityResult = ed.GetEntity(opt)

If res.Status <> PromptStatus.OK Then Exit Sub

ed.Command("_.AECCPROJECTOBJECTSTOPROF", selRes.Value, "", res.ObjectId, "")

 

The dialog box then displays prompting the user to select the projection style.

 

I hope that this helps!

 

EDIT - Being that you are invoking your command from a Modeless UI you will want to consider the coding required by a Modeless dialog, some of which you are already aware of, such as Locking the Document. Though, I am not sure if you also need to call the StartUserInteraction method or not. 

 

Message 3 of 4

norman.yuan
Mentor
Mentor
Accepted solution

The issue is that editor.Command() cannot be used in Application context, which is the context when you start the code execution from an modeless UI. A recent discussion in the .NET forum provides the exact solution yo are looking for:

 

https://forums.autodesk.com/t5/net/run-a-sample-command-with-parameters-using-c-net/td-p/13334844 

 

 

Norman Yuan

Drive CAD With Code

EESignature

Message 4 of 4

tipitasa
Enthusiast
Enthusiast

Thank you both! I was not truly aware of the changed context in the Modeless Dialog.

I now call the command using the extension method from @ActivistInvestor  from the above linked topic
 https://forums.autodesk.com/t5/net/run-a-sample-command-with-parameters-using-c-net/m-p/13335435/hig...

// clear the pickfirst set
_ed.SetImpliedSelection(new ObjectId[0]);

ObjectId[] solidIds = { selectedSolidId };
ObjectId[] profViewIds = { _selectedProfileViewId };
var solidSelectionSet = SelectionSet.FromObjectIds(solidIds);
var profileSelectionSet = SelectionSet.FromObjectIds(profViewIds);

DocumentCollection docs = Application.DocumentManager;
try
{
     await docs.CommandAsync("_.AECCPROJECTOBJECTSTOPROF", solidSelectionSet, "", profileSelectionSet, "");
}
catch (System.Exception ex)
{
     docs.MdiActiveDocument.Editor.WriteMessage($"Operation failed: {ex.Message}");
}