Cancelling an active command in AutoCAD

Thanks to Alexander Rivilis for this topic (he submitted a comment to my previous post that got me thinking about this addendum).

When you're asking AutoCAD to execute commands by submitting them to its command-line, it helps to make sure no command is currently active. The accepted approach is to send two escape characters to the command-line... this is adopted by our menu & toolbar macros that consistently start with ^C^C in MNU and now CUI files.

Why two? The first is to cancel the "most active" command, and the second is to drop out of either the dimension mode or the outermost command, if the innermost was actually being executed transparently. Strictly speaking there are probably a few cases where you might actually need three escape characters. Type "DIM VERT 'ZOOM" into the command-line, and you'll need three escapes to get back to the "Command:" prompt, but that's fairly obscure - two is generally considered enough for most realistic situations.

So... what constitutes an escape character? Well, luckily we no longer need to thumb back to the ASCII table in the back of our AutoCAD R12 Programming manuals to find this out. It's ASCII code 27, which is represented as 1B in hexadecimal notation.

A common way to send the character from C++ is to send the string "\x1B" for each escape character to AutoCAD. From VB you would tend to use Chr$(27) for the same purpose.

In terms of your choice for sending the character(s) across to AutoCAD... you can generally use one of the functions suggested previously, sendStringToExecute(), SendMessage() or SendCommand(). It won't work from ads_queueexpr(), but then given its typical usage context you shouldn't need to use it for this. Also, as Alexander very rightly pointed out in his comment, you might use PostMessage() or acedPostCommand() (more on this second one later).

SendMessage() and PostMessage() are very similar - you can check this article for the differences. I tend to prefer SendMessage() for synchronous use, as it waits to have an effect before returning, but PostMessage() is still good to have around in the toolbox (it's good for firing off keystrokes into a window's message loop).

acedPostCommand() is another undocumented function, which needs declaring in your code before use:

extern Adesk::Boolean acedPostCommand(const ACHAR* );

What's particularly interesting about this function is its use of the special keyword, which should get you back to the "Command:" prompt irrespective of command nesting:

acedPostCommand(_T("CANCELCMD"));

Then, of course, you can continue to use it as shown in my previous post:

acedPostCommand(_T("_POINT 6,6,0 "));

One quick note about cancelling commands from acedCommand(). If you pass RTNONE as the only argument to acedCommand(), this will be interpreted as an escape by AutoCAD.

27 responses to “Cancelling an active command in AutoCAD”

  1. As acedPostCommand() is undocumented, I guess it's not officially supported (i.e. via ADN support etc)? 😉 Otherwise it'd be an interesting alternative. Are there other keywords besides 'CANCELCMD'?

    I usually use PostMessage() to send the escape character.

  2. acedPostCommand() is indeed undocumented, but quite widely used and unlikely to change or disappear.

    A lot depends on your relative comfort level with using undocumented functions: you would notice at build time (during link) if it were to have disappeared from AutoCAD, and the signature is so simple I don't expect its behaviour to change. "CANCELCMD" is the only special keyword it supports, but is a useful one (as it cancels down through all active commands).

    Kean

  3. Thanks, Kean, for elaborating. Canceling down through all active commands is indeed very useful at times. I'll keep this trick in mind!

  4. Hi Kean,
    I need to cancel an command in DotNet. I tried it with acedPostCommand("CANCELCMD");
    But that doesnt work.
    All the specific forums doesn't help, so I ask here for help.
    Juergen

  5. Hi Juergen,

    So you tried to P/Invoke it, as per this post?

    Have you tried send escape characters (Chr(27)) using SendCommand() or SendStringToExecute?

    Regards,

    Kean

  6. Hi,
    thanks for your comment.
    I tried with P/Invoke (I think - I'm not sure).

    Here is the code:

    [DllImport("acad.exe", EntryPoint = "?acedPostCommand@@YAHPB_W@Z", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    private static extern int acedPostCommand(string strExpr);

    I've got the next function from the Eventwatcher-Sample. When the CommandWillStart-Events fired this function is executed. Thats OK, but the Command doesn'T cancel.

    private void callback_CommandWillStart(Object o, CommandEventArgs e)
    {
    // OK, I knew all command will be canceled, this ist only for working out.
    acedPostCommand("CANCELCMD");
    }

  7. Oh, it's from an event callback?

    You *might* be able to use doc.SendStringToExecute(Chr(27)+Chr(27)), assuming the command pauses for user-input, but otherwise you're better off vetoing the command using a DocumentLockModeChanged event, as per this post.

    Regards,

    Kean

  8. OK, now its works.
    I'd vetoing the command in the DocumentLockModeChanged event.

    Many, many thanks for your help. You are great.

    Regards
    Jürgen

  9. hi, i tried to calcel a command with ctrl+c but don't work, what can i do for that

  10. Ctrl-C is mapped to COPYCLIP. You may need to unmap it (if that's even possible) via the CUI command.

    This post is about programmatically cancelling commands, not about changing the keyboard shortcuts a user can use to cancel them.

    Kean

  11. Dear Kean,

    I'm writing an application that will run seperately from Autocad (*.exe) it will ask the base position using Utility.GetPoint, but this doesn't work when there is a command active in Autocad, how to cancel that command?
    I've tried to use above mentioned solutions, but none of them worked.

    Code:

    AcadApp = CType(GetObject(, "Autocad.application"), Autodesk.AutoCAD.Interop.AcadApplication)

    AcadDoc = AcadApp.ActiveDocument

    AcadDoc.SendCommand(Chr(3)) 'Doesn't work

    Dim point As Object = AcadDoc.Utility.GetPoint(, "Please give the startposition:")

    /code

    Kind regards,

    Maarten

  12. Have you tried sending Chr(27)?

    Kean

  13. CAN I GET THE SOLUTION FOR SAME. KILLING THE ACTIVE COMMAND THROUGH VB.NET

  14. ABOVE METHODS GIVING ERROR I TRIED THEM..HOW TO USE acedPostCommand(_T("CANCELCMD")); IN VB.NET

  15. You can use the P/Invoke declaration in this post.

    Kean

  16. BUT KEAN I AM CREATING A WINDOWS APPLICATION AND I AM NOT LOADING ANY DLL TO AUTOCAD,I NEED TO WORK FROM WITHIN .NET AS AN WINDOWS APPLICATION WHERE THE COMMANDS THE POST I TINK WORK ONLY WITHIN AUTOCAD NOT THROUGH .NET

  17. Try
    acadDoc.ActiveLayer = Cparcels
    'MsgBox r
    xc = Str(unsorted_array(0, r))
    yc = Str(unsorted_array(1, r))
    strcmd = "(command " & " ""bpoly"" " & " (list " & Trim(xc) & " " & Trim(yc) & ") " & " "" "")"
    acadDoc.SendCommand("_zoom" & vbCr & "C" & vbCr & Trim(xc) & "," & Trim(yc) & vbCr & "100" & vbCr)

    acadDoc.SendCommand(strcmd & vbCr & vbCr)

    Catch ex As Exception
    ''i need to kill the active command here

    MsgBox(r)
    acedPostCommand("P")

    End Try

  18. acedPostCommand("P") command doesnt work here

  19. Try sending escape characters (ASCII 27). If this doesn't work, please post your code to the discussion groups.

    Kean

  20. Hi kean,
    How do I cancel a region command. Its screwing my happiness. Anything I draw, either a line or a circle, or a polygon, this region is active on the base lines. I want to undo this. How do I do this?? Plz help me out..

    Regards
    Rohan

  21. Hi Rohan,

    Escape usually cancels commands waiting for command-line input. I suspect there's information I'm missing: please follow up via ADN or via the appropriate discussion group with more specifics about what you're attempting to do.

    Regards,

    Kean

  22. Thank u so much Kean...May God Bless you..

    Regards
    Rohan

  23. Hi, I am new to autocad plugins and found your posts really helpful. I am using ObjectArx throught .net.. When trying to sync data from another application to autocad, if the mouse wheel is used it will crash.. any ideas on how to prevent this ? i lock the document and start a transaction.. but in the middle of it, if the user uses the mouse wheel on autocad it crashes..

    1. Kean Walmsley Avatar

      Hello,

      That sounds like something that needs debugging. A bit beyond the scope of the help I can provide via this blog, I'm afraid.

      You might try posting to the AutoCAD .NET Discussion Group or to The Swamp.

      Regards,

      Kean

  24. Is there a way to change the NUM LOCK key to CANCELCMD? This would REALLY come in handy for me. Pardon the pun.

  25. Fernando Mejía Rodríguez Avatar
    Fernando Mejía Rodríguez

    Hi Kean, This is Fernando from México.
    I take this opportunity to express my gratitude for the excellent explanations in this and other posts.
    I am in a work where I intend to develop a protector where I need to prevent or cancel commands whose name is unknown because they arise from applications lisp, arx or .net and, I only know their name at runtime, once the user writes them. I have written a list of commands that are permissible and, linked to this, a commandWillStart event that discovers that the command in turn is not permissible and then I send the line:
    acDoc.SendStringToExecute("\x1B\x1B", true, false, true);

    This works efficiently but not in commands where user input is not required such as Pan or Oops.
    What if the anonymous command I try to prevent does not require user input?
    In another search the following line is not accepted in VS2012 (or something I am omitting):
    extern Adesk :: Boolean acedPostCommand (const ACHAR *);

    Maybe I should conduct my research to the following question:
    Can I obtain from my .Net program, at run time, the list of names of all the commands present in the drawing session?
    It may be too late after 12 years you have submitted this post.
    But August 14 was my birthday.
    Thanks in advance.
    Congratulations master, for such a splendid work.
    Fernando
    Viernes 11 de Enero de 2019

Leave a Reply to David Meza Cancel reply

Your email address will not be published. Required fields are marked *