Allow for changing command options during a user input operation.

Allow for changing command options during a user input operation.

Yehoshua18
Enthusiast Enthusiast
758 Views
5 Replies
Message 1 of 6

Allow for changing command options during a user input operation.

Yehoshua18
Enthusiast
Enthusiast

Hi folks. 


Any idea how to allow for changing command options not directly related to current user input action. Below you can see an example of a stock AutoCAD command "pline", where you can interrupt a GetPoint action to change some options. I use C#.

 

Thanks for the help!

Regards

- Joshua

 

 

joshuaW5HNW_0-1678785399372.png

 

0 Likes
Accepted solutions (2)
759 Views
5 Replies
Replies (5)
Message 2 of 6

_gile
Consultant
Consultant
Accepted solution

Hi,

 

You can add keywords to the PromptOptions.

Here's a simple example which prompts the user for a point (center of a circle) and also purpose to choose a 'Layer' and 'Color' options.

        [CommandMethod("DRAWCIRCLEWITHOPTIONS")]
        public static void DrawCircleWithOptions()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var promptPointOptions = new PromptPointOptions(
                    "\nSpecify the center or [Layer/Color]: ",
                    "Layer Color");
                ObjectId layerId = db.Clayer;
                int colorIndex = 256;
                Point3d center;
                var layerTable = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);

                // Prompt the user for the center until he specifies the point (or cancels)
                while (true)
                {
                    var promptPointResult = ed.GetPoint(promptPointOptions);

                    // If the user entered a keyword
                    if (promptPointResult.Status == PromptStatus.Keyword)
                    {
                        // The user choosed the 'Layer' option
                        if (promptPointResult.StringResult == "Layer")
                        {
                            // Prompt the user to enter a layer name
                            var promptResult = ed.GetString("\nEnter the layer name: ");
                            if (promptResult.Status == PromptStatus.OK)
                            {
                                // Check if the layer exists
                                if (layerTable.Has(promptResult.StringResult))
                                    layerId = layerTable[promptResult.StringResult];
                                else
                                    Application.ShowAlertDialog($"Layer '{promptResult.StringResult}' not found");
                            }
                        }
                        // The user choosed the 'Color' option
                        else
                        {
                            // Prompt the user to enter a color index
                            var promptIntegerOptions = new PromptIntegerOptions("\nEnter the color index: ");
                            promptIntegerOptions.LowerLimit = 0;
                            promptIntegerOptions.UpperLimit = 256;
                            var promptIntegerResult = ed.GetInteger(promptIntegerOptions);
                            if (promptIntegerResult.Status == PromptStatus.OK)
                                colorIndex = promptIntegerResult.Value;
                        }
                    }
                    // If the user specified a point, break the loop
                    else if (promptPointResult.Status == PromptStatus.OK)
                    {
                        center = promptPointResult.Value;
                        break;
                    }
                    // If the user cancels, exit the command
                    else
                    {
                        return;
                    }
                }

                // Prompt the user to specify the radius
                var promptDistanceOptions = new PromptDistanceOptions("\nSpecify the radius: ");
                promptDistanceOptions.UseBasePoint = true;
                promptDistanceOptions.BasePoint = center;
                var promptDistanceResult = ed.GetDistance(promptDistanceOptions);
                if (promptDistanceResult.Status != PromptStatus.OK)
                    return;
                double radius = promptDistanceResult.Value;

                var curSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                var circle = new Circle(center, Vector3d.ZAxis, radius)
                {
                    ColorIndex = colorIndex,
                    LayerId = layerId
                };
                circle.TransformBy(ed.CurrentUserCoordinateSystem);
                curSpace.AppendEntity(circle);
                tr.AddNewlyCreatedDBObject(circle, true);
                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 6

Yehoshua18
Enthusiast
Enthusiast

Brilliant @_gile.

 

Thank you very much!

0 Likes
Message 4 of 6

Yehoshua18
Enthusiast
Enthusiast

Thank you so much, your help has been invaluable to so many people here. Its amazing. One last question for awhile. 

 

I've created a class (below) containing program settings. How might I store these values between running instances of my main command method? I want the user to be able to set these settings once, and then every time they run the command again, while the current drawing is open, to have these settings already set and ready to go. I don't need these settings themselves saved into the DWG file. 

 

Thanks!

 

public class UTOptions
        {
            //public Options(string utname1, string utname2, string confltlyr, string userName, float utdiameter1, float utddiaeter2, float utwallthickness1, float utwallthickness2)
            //{
            //}

            public string utname1 { get; set; } = "Utility 1";
            public double utdiameter1 { get; set; } = 0;
            public double utwallthickness1 { get; set; } = 0;
            public string utname2 { get; set; } = "Utility 2";
            public double utdiameter2 { get; set; } = 0;  
            public double utwallthickness2 { get; set; } = 0;
            public string confltlyr { get; set; } = "Utility_Conflits";
            public string userName { get; set; } = Environment.UserName;
}

 

 

0 Likes
Message 5 of 6

_gile
Consultant
Consultant
Accepted solution

When you define a non-static command (CommandMethod decored method) in a class, an instance of this class is created once for the current drawing the first time the method is run. So, if you need per-document data, the simplest way is to use instance (non-static) fields of this class (you can read this topic).

Here's an example:

 

    public class UTOptionCommands
    {
        // private instance fields
        private string utName1 = "Utility 1";
        private double utDiameter1 = 0.0;
        private double utWallThickness1 = 0.0;
        private string utName2 = "Utility 2";
        private double utDiameter2 = 0;
        private double utWallThickness2 = 0;
        private string confltlyr = "Utility_Conflits";
        private string userName = Environment.UserName;

        // instance command
        [CommandMethod("TEST")]
        public void TestUtility()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;

            var distanceOptions = new PromptDistanceOptions("\nSpecify diameter 1: ");
            distanceOptions.UseDefaultValue = true;
            distanceOptions.DefaultValue = utDiameter1;
            var distanceResult = ed.GetDistance(distanceOptions);
            if (distanceResult.Status == PromptStatus.OK)
            {
                utDiameter1 = distanceResult.Value;
                // you can use the new utDiameter1 value in the whole class.
            }

            distanceOptions.Message = "\nSpecify wall thickness 1: ";
            distanceOptions.DefaultValue = utWallThickness1;
            distanceResult = ed.GetDistance(distanceOptions);
            if (distanceResult.Status == PromptStatus.OK)
            {
                utWallThickness1 = distanceResult.Value;
                // you can use the new utWallThickness1 value in the whole.
            }
        }
    }

 

 

Another way could be using the Document.UserData HashTable, see this topic.

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 6 of 6

Yehoshua18
Enthusiast
Enthusiast

Hi! Thanks!

 

The Document.UserData HashTable method was the way to go for me!

0 Likes