How to simulate the Polyline command through code?

How to simulate the Polyline command through code?

zhengyunyang2019
Advocate Advocate
1,553 Views
12 Replies
Message 1 of 13

How to simulate the Polyline command through code?

zhengyunyang2019
Advocate
Advocate

I need to implement a command to draw a polyline. I want to click a button in the window, and the window will hide. Then, I can use the mouse to draw the polyline, and when I'm done, the window will reappear.And during the drawing process, I hope to simulate the direct use of the PL (Polyline) command's effect, where a line connecting each selected point to the next one is displayed. This is because I am developing a window feature that requires drawing polylines, but I cannot close the window to use the PL command, as it would prevent me from saving my information.

0 Likes
Accepted solutions (2)
1,554 Views
12 Replies
Replies (12)
Message 2 of 13

kerry_w_brown
Advisor
Advisor
Accepted solution

@zhengyunyang2019 ,

Perhaps something like this ( from Gilles ) called from your button_click event handler would suit you.

Simpler than a Jig.

https://forums.autodesk.com/t5/net/drawing-polyine/m-p/5407101/highlight/true#M42505

 

Regards,

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 3 of 13

_gile
Consultant
Consultant

Hi,

 

The simplest way is to call the native "_PLINE" command with Editor.Command method.

Assuming the dialog is shown as modal dialog (i.e. shown with Application.ShowModalDialog method), you have to use Editor.StartUserInteraction method to automaically hide the dialog during the command.

You can get the ObjectId of the created polyline by using the Database.Handseed property.

        private void buttonDrawPolyline_Click(object sender, EventArgs e)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            long seed = db.Handseed.Value;
            using (ed.StartUserInteraction(this.Handle))
            {
                ed.Command("_pline");
            }
            var plineId = ObjectId.Null;
            for (long i = seed; i < db.Handseed.Value; i++)
            {
                if (db.TryGetObjectId(new Handle(i), out ObjectId id)
                    && id.ObjectClass.Name == "AcDbPolyline")
                    plineId = id;
            }
            AcAp.ShowAlertDialog($"Polyline ObjectId = {plineId}");
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 4 of 13

zhengyunyang2019
Advocate
Advocate
Thank you for your help. This looks pretty straightforward, but the compiler is indicating that there is no definition for the Command() function in 'ed'. Did I miss any references?
0 Likes
Message 5 of 13

zhengyunyang2019
Advocate
Advocate
I am developing based on the 2014 version of CAD. Could it be that the difference in versions is why the 2014 version doesn't have this function?
0 Likes
Message 6 of 13

_gile
Consultant
Consultant

The Editor.Command method came with AutoCAD 2015.

For prior version, you can try Tony Tanzillo's wrapper for the undocumented RunCommand method. You cannot use his wrapper with AutoCAD 2015 and later.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 13

zhengyunyang2019
Advocate
Advocate
I used Tony Tanzillo's wrapper and then successfully ran the code you provided. However, it didn't have the expected effect. After clicking the button, the window disappeared and immediately reappeared, so I couldn't draw anything. But after I closed the window again, the polyline command still worked, and I could continue drawing polylines.
0 Likes
Message 8 of 13

_gile
Consultant
Consultant

Do you show the dialog box with the Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog method?



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 9 of 13

zhengyunyang2019
Advocate
Advocate

I tested this code, and no matter what I do inside the curly braces, it just makes the window hide for a moment and then immediately reappear.Is this related to me using the 2010 version?

using (EditorUserInteraction eui = ed.StartUserInteraction(form.Handle))
{
    do anything...
}
0 Likes
Message 10 of 13

_gile
Consultant
Consultant

Difficult to reply viewing so few code. Please, reply to my previous question and/or show the code you use to show/open the dialog box.




Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 11 of 13

_gile
Consultant
Consultant
Accepted solution

Here's a minimalist code sample:

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using System;
using System.Windows.Forms;

using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;

namespace AddAttributeToBlockSample
{
    public partial class DialogBox : Form
    {
        public DialogBox()
        {
            InitializeComponent();
        }

        private void buttonDrawPolyline_Click(object sender, EventArgs e)
        {
            var doc = AcAp.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            long seed = db.Handseed.Value;
            using (ed.StartUserInteraction(this.Handle))
            {
                ed.Command("_pline");
            }
            var plineId = ObjectId.Null;
            for (long i = seed; i < db.Handseed.Value; i++)
            {
                if (db.TryGetObjectId(new Handle(i), out ObjectId id)
                    && id.ObjectClass.Name == "AcDbPolyline")
                    plineId = id;
            }
            AcAp.ShowAlertDialog($"Polyline ObjectId = {plineId}");
        }
    }

    public class Command
    {
        [CommandMethod("DLG")]
        public static void ShowModalDialog()
        {
            using (var dialog = new DialogBox())
            {
                AcAp.ShowModalDialog(dialog);
            }
        }
    }
}

 

And a screencast:

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 12 of 13

zhengyunyang2019
Advocate
Advocate

Thank you very much for your help, it's truly crucial to me.

I tested your code and found that it works if the runtime environment is CAD 2020+ VS 2017, yielding results consistent with those in the video you provided,it's great.

Unfortunately, in the case of CAD 2014+VS 2010, the code doesn't work as expected. The window reappears instantly after being hidden and doesn't wait.

 

The only notable difference between the two environments is that in the 2014 environment, the Editor class does not have a Commad() method.

So, i can only use the EditorInputExtension extension method.

I suspect that there might be some distinction between EditorInputExtension.Commad() and Editor.Commad(), but my knowledge in this area is limited, and I'm unable to resolve this issue. Do you have any suggestions?

I need to use CAD 2014, and in fact, I need to develop plugins for CAD 2014, 2016, and 2020 simultaneously.

 

Or maybe there's a difference in the StartUserInteraction method in different versions?

 

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;

namespace MyTest
{
    static class EditorInputExtension
    {
        public static PromptStatus Command(this Editor editor, params object[] args)
        {
            if (editor == null)
                throw new ArgumentNullException("Editor Extension");
            return runCommand(editor, args);
        }

        static Func<Editor, object[], PromptStatus> runCommand = GenerateRunCommand();

        static Func<Editor, object[], PromptStatus> GenerateRunCommand()
        {
            MethodInfo method =
                typeof(Editor).GetMethod("RunCommand", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            var instance = Expression.Parameter(typeof(Editor), "instance");
            var args = Expression.Parameter(typeof(object[]), "args");
            return Expression.Lambda<Func<Editor, object[], PromptStatus>>(Expression.Call(instance, method, args), instance, args).Compile();
        }
    }
}

 

 

0 Likes
Message 13 of 13

_gile
Consultant
Consultant

I no more have AutoCAD 2014 to test, but this issue is not due to StartUserInteraction because the dialog box hides itself (even if it shows quasi immediately). I suspect the EditorInputExtension.Command method to work slightly differently from the AutoCAD 2015 native one.

It looks like you have to mimic the _PLINE command with code.

@kerry_w_brown provided you a link to a method which can be used to draw a simple polyline (only line segments with no width), Kean Walmsley showed a way to draw a polyline with arc segments with a Jig here.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes