How to repeat a command which actually send another command to AutoCAD

How to repeat a command which actually send another command to AutoCAD

ptranU2KHX
Advocate Advocate
694 Views
8 Replies
Message 1 of 9

How to repeat a command which actually send another command to AutoCAD

ptranU2KHX
Advocate
Advocate

Hi everyone,

 

Thank you for stopping by and reading my post.

I am writing a function that sends a command string to AutoCAD. The problem is the user would like to have the ability to repeat the function, not the command which that function calls. Are there any ways that I could work on this?

 

e.g. I have a function with command 'createLine'. The 'createLine' function will have some works before sending the command 'line' to AutoCAD. When the user hit the space bar to repeat the function, AutoCAD calls 'line' but not the 'createLine' function.

 

My function is writtent in .net.

I appreciate for all your helps. Thank you.

0 Likes
Accepted solutions (2)
695 Views
8 Replies
Replies (8)
Message 2 of 9

_gile
Consultant
Consultant

Hi,

 

It should work if you call the command with Editor.Command method.

        [CommandMethod("TEST")]
        public static void Test()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var opts = new PromptPointOptions("\nStart point: ");
            var res = ed.GetPoint(opts);
            if (res.Status != PromptStatus.OK) return;
            var pt1 = res.Value;

            opts.Message = "\nEnd point: ";
            opts.BasePoint = pt1;
            opts.UseBasePoint = true;
            res = ed.GetPoint(opts);
            if (res.Status != PromptStatus.OK) return;
            var pt2 = res.Value;

            ed.Command("_LINE", pt1, pt2, "");
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 9

ptranU2KHX
Advocate
Advocate

Hi @_gile , thanks for your help.

 

As far as I know, editor.command only work in the document context.

Due to some requirements, I have to work in the application context. Therefore I currently use AcadApplication.ActiveDocument.SendCommand to send the command to AutoCAD.

 

Are there anyways to work on this? 

0 Likes
Message 4 of 9

_gile
Consultant
Consultant

From an Application context (e.g. CommandFlags.Session, modeless UI) you can use SendStringToExecute to call the custom command which uses Editor.Command.

 

Here's a simple example:

        // Command which run in Application context
        [CommandMethod("APPTEST", CommandFlags.Session)]
        public static void ApplicationContextTest()
        {
            // Switch to Document context to call the DOCTEST command
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("DOCTEST\n", false, false, true);
        }

        // Command which only run in Document context
        [CommandMethod("DOCTEST")]
        public static void DocumentContextTest()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var opts = new PromptPointOptions("\nStart point: ");
            var res = ed.GetPoint(opts);
            if (res.Status != PromptStatus.OK) return;
            var pt1 = res.Value;

            opts.Message = "\nEnd point: ";
            opts.BasePoint = pt1;
            opts.UseBasePoint = true;
            res = ed.GetPoint(opts);
            if (res.Status != PromptStatus.OK) return;
            var pt2 = res.Value;

            ed.Command("_LINE", pt1, pt2, "");
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 9

ptranU2KHX
Advocate
Advocate

 

        // Command which run in Application context
        [CommandMethod("APPTEST", CommandFlags.Session)]
        public static void ApplicationContextTest()
        {
            // Switch to Document context to call the DOCTEST command
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("DOCTEST\n", false, false, true);
        }

 

I guess you misunderstand my idea. I tried your code but it did not seem what I expect.

After I call 'APPTEST' for the first time, I hit 'space bar'. The expect result here is AutoCAD should call 'APPTEST' instead of calling 'DOCTEST\n' command method.

 

Besides, if I use 'SendStringToExecute' or 'Command', I could not have AutoCAD stop calling the command when user hit 'escape key'.

 

Below is my current code which is continuously call 'QLEADER' and wait for user to create a leader. This loop only stops if the user hit 'escape key'. This is the reason why I use 'SendCommand' for my project since this is the only one works to stop with 'escape key'.

 

 

        While True 

            System.Windows.Forms.Application.DoEvents()
            If filter.bCanceled = True Then
                Exit While
            End If

            AcadApplication.ActiveDocument.SendCommand("QLEADER")
            
        End While

 

 

 

0 Likes
Message 6 of 9

_gile
Consultant
Consultant
Accepted solution

@ptranU2KHX  a écrit :

I guess you misunderstand my idea. I tried your code but it did not seem what I expect.

After I call 'APPTEST' for the first time, I hit 'space bar'. The expect result here is AutoCAD should call 'APPTEST' instead of calling 'DOCTEST\n' command method.


The APPTEST command (or any modeless dialog event handler) does nothing else than calling SendStringToExecute to launch the DOCTEST command in document context. All the stuff should be in the DOCTEST command.

This is what Kean's Walmsley recommended long time ago now for implementing modeless UI (and it can be applied to any command running in Application context).

"Once again there’s our important rule of thumb when it comes to implementing a modeless UI: rather than manually locking the current document, it’s safer to define a command – which will implicitly lock the current document – and call that from the UI via SendStringToExecute()."

 

Try this example which is closer to your request:

        // Command which run in Application context
        [CommandMethod("APPTEST", CommandFlags.Session)]
        public static void ApplicationContextTest()
        {
            // Switch to Document context to call the DOCTEST command
            var doc = Application.DocumentManager.MdiActiveDocument;
            doc.SendStringToExecute("DOCTEST\n", false, false, true);
        }

        // Command which only run in Document context
        [CommandMethod("DOCTEST")]
        public static void DocumentContextTest()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var opts = new PromptPointOptions("\nStart point: ");
            opts.AllowNone = true; // <- this allows to break the loop by hiting Enter
            while (true)
            {
                var res = ed.GetPoint(opts);
                if (res.Status != PromptStatus.OK) break;
                ed.Command("_QLEADER", res.Value);
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 7 of 9

ptranU2KHX
Advocate
Advocate

Thanks @_gile , your help is precious to me. I do appreciate that. Have a nice day!

 

0 Likes
Message 8 of 9

ptranU2KHX
Advocate
Advocate

Hi @_gile ,

One more question is coming up, I used ed.Command("MTEXT", "Line Spacing") and it worked well. However, are there anyways that let the users hit 'enter' or 'space' before executing to 'Line Spacing'? 

Right now, ed.Command("MTEXT", "Line Spacing") will lead user to 'Line Spacing' without letting them choose another options.

 

ptranU2KHX_1-1667792539294.png

 

0 Likes
Message 9 of 9

_gile
Consultant
Consultant
Accepted solution

You can try something like this:

        [CommandMethod("DOCTEST")]
        public static void DocumentContextTest()
        {
            var ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var pointOptions = new PromptPointOptions("\nSpecify the first corner: ");
            pointOptions.AllowNone = true; // <- this allows to break the loop by hiting Enter

            var oldEcho = Application.GetSystemVariable("cmdecho");
            Application.SetSystemVariable("cmdecho", 0);
            try
            {
                while (true)
                {
                    var pointResult = ed.GetPoint(pointOptions);
                    if (pointResult.Status != PromptStatus.OK)
                        return;
                    var pt1 = pointResult.Value;

                    var cornerOptions = new PromptCornerOptions(
                        "\nSpecify opposite corner or [Height/Justify/Line spacing/Rotation/Style/Width/Columns]: ",
                        "Height Justify Line Rotation Style Width Columns",
                        pt1);
                    cornerOptions.AllowNone = true;  // <- this allows to select default keyword by hiting Enter
                    cornerOptions.Keywords.Default = "Line";
                    var cornerResult = ed.GetCorner(cornerOptions);
                    switch (cornerResult.Status)
                    {
                        case PromptStatus.Keyword:
                            ed.Command("_MTEXT", pt1, "_" + cornerResult.StringResult);
                            break;
                        case PromptStatus.OK:
                            ;
                            ed.Command("_MTEXT", pt1, cornerResult.Value);
                            break;
                        default:
                            return;
                    }
                }
            }
            finally { Application.SetSystemVariable("cmdecho", oldEcho); }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub