Author Topic: Editor.Command() vs Editor.CommandAsync()  (Read 26130 times)

0 Members and 1 Guest are viewing this topic.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Editor.Command() vs Editor.CommandAsync()
« Reply #15 on: March 25, 2015, 11:56:08 PM »
What I meant in previous post is you can Await anything like custom class CommandResult


Code - C#: [Select]
  1. public sealed class CommandResult : INotifyCompletion
  2. {
  3.     // Fields
  4.     private bool m_completed = false;
  5.     private Action m_continuation;
  6.  
  7.     // Methods
  8.     internal CommandResult()
  9.     {
  10.     }
  11.  
  12.     internal int Callback()
  13.     {
  14.         int num;
  15.         try
  16.         {
  17.             this.m_completed = true;
  18.             this.m_continuation();
  19.             return 0x13ec;
  20.         }
  21.         catch (Exception exception1)
  22.         {
  23.             UnhandledExceptionFilter.CerOrShowExceptionDialog(exception1);
  24.             num = -5002;
  25.         }
  26.         return num;
  27.     }
  28.  
  29.     public Editor.CommandResult GetAwaiter()
  30.     {
  31.         return this;
  32.     }
  33.  
  34.     public void GetResult()
  35.     {
  36.         if (acedCmdCWasCancelled())
  37.         {
  38.             Interop.ThrowExceptionForErrorStatus(180);
  39.         }
  40.     }
  41.  
  42.     public void OnCompleted(Action continuation)
  43.     {
  44.         this.m_continuation = continuation;
  45.     }
  46.  
  47.     // Properties
  48.     public bool IsCompleted
  49.     {
  50.         [return: MarshalAs(UnmanagedType.U1)]
  51.         get
  52.         {
  53.             return this.m_completed;
  54.         }
  55.     }
  56. }
  57.  


 Pretty neat can do it with extension methods also

http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx
Code - C#: [Select]
  1. await 3000;
  2. ..
  3. ....
  4. ...
  5.  
  6.      public static class Awaiters
  7.     {
  8.         public static TaskAwaiter GetAwaiter(this TimeSpan timeSpan)
  9.         {
  10.             return Task.Delay(timeSpan).GetAwaiter();
  11.         }
  12.         public static TaskAwaiter GetAwaiter(this Int32 millisecondsDue)
  13.         {
  14.             return TimeSpan.FromMilliseconds(millisecondsDue).GetAwaiter();
  15.         }
  16.     }
  17.  


Kean

  • Newt
  • Posts: 48
Re: Editor.Command() vs Editor.CommandAsync()
« Reply #16 on: March 26, 2015, 12:37:06 PM »
Just to follow up on this... the docs do indeed need to be fixed. You can rely on Editor.Command() completing commands for you rather than cancelling them: so you should only need a while loop if you need finer-grained control over the command tokens.

Kean

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Editor.Command() vs Editor.CommandAsync()
« Reply #17 on: December 11, 2023, 05:05:22 PM »
This might be an example of using CommandAsync to interact more in command. If you are wanting to use PLINE command with arcs but keep a constant angle with ability to negate/filp arc easily.
Here is another topic explaining same issue https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/draw-polyline-arc-circuits-it-essential-for-electrical-and/td-p/9837927
The weird part is to change a angle once entered the PLINE command requires using escape during the command and not letting it run through and cancel the command but now as I post it I think I could of handled this without using rightclick to end command and could of done it a little differently.

But basically
The pretranslate handlers
  • Catch spacebar and change to esc and set flag to negate angle
  • Catch right click and sends cancel and sets flag to end command
The command
  • Prompts for point/or can set angle here
  • Adds pretranslate handlers to watch for spacebar/rightclick. Spacbar filps/negates angle and rightclick ends command
  • Start the command await Ed.CommandAsync("_.PLINE", ppr.Value, "A");
  • Start a loop and check if angle needs to be negated(always false first time) and await Ed.CommandAsync("A", angle, Editor.PauseToken);
    • If point selected then loop starts back over entering previous angle
    • If spacebar pressed then catch block catches it and loop starts back over, but negating the angle, and can keep negating back and forth with spacebar
    • If rightclicked pressed then throws to outer catch block which supresses error if a user break and in its finally block removes handler
Code - C#: [Select]
  1.         private const int VK_SPACE = 32;
  2.         private const int VK_ESCAPE = 27;
  3.         const int WM_CHAR = 258;
  4.         /// </summary>
  5.         private const int MK_SHIFT = 4;
  6.         /// <summary>
  7.         /// The w m_ rbuttonup
  8.         /// </summary>
  9.         private const int WM_RBUTTONUP = 517;
  10.         /// <summary>
  11.         /// The w m_ lbuttonup
  12.         /// </summary>
  13.         private const int WM_LBUTTONUP = 514;
  14.         /// <summary>
  15.         /// The w m_ lbuttondown
  16.         /// </summary>
  17.         private const int WM_LBUTTONDOWN = 513;
  18.         /// <summary>
  19.         /// The w m_ rbuttondown
  20.         /// </summary>
  21.         private const int WM_RBUTTONDOWN = 516;
  22.  
  23.         /// <summary>
  24.         /// Handles the PreTranslateMessage event of the Application control.
  25.         /// </summary>
  26.         /// <param name="sender">The source of the event.</param>
  27.         /// <param name="e">The <see cref="PreTranslateMessageEventArgs"/> instance containing the event data.</param>
  28.         private void Application_PreTranslateMessage(object sender, PreTranslateMessageEventArgs e)
  29.         {
  30.             var wp = e.Message.wParam.ToInt64();
  31.  
  32.      
  33.             if (e.Message.message == WM_CHAR && wp == VK_SPACE)
  34.             {
  35.                 System.Windows.Interop.MSG msg = e.Message;
  36.                 negate = true;
  37.                 msg.wParam = new IntPtr(VK_ESCAPE);
  38.                 e.Message = msg;;
  39.             }
  40.  
  41.             if (e.Message.message == WM_RBUTTONDOWN && (wp != 6 && wp != MK_SHIFT))
  42.             {
  43.                 e.Handled = true;
  44.             }
  45.             if (e.Message.message == WM_RBUTTONUP && wp != MK_SHIFT)
  46.             {
  47.                 Application.PreTranslateMessage -= Application_PreTranslateMessage;
  48.                 e.Handled = true;
  49.                 endCommand = true;
  50.                 Application.DocumentManager.MdiActiveDocument.SendCancel();
  51.             }
  52.         }
  53.  
  54.         int angle = 60;
  55.         bool negate = false;
  56.         private bool endCommand = false;
  57.  
  58.         [CommandMethod("parc")]
  59.         public async void parc()
  60.         {
  61.  
  62.             negate = false;
  63.             endCommand = false;
  64.             PromptPointOptions ppo = new PromptPointOptions("\nSelect Point");
  65.             ppo.Keywords.Add("Angle");
  66.             PromptPointResult ppr = Ed.GetPoint(ppo);
  67.  
  68.             if (ppr.Status == PromptStatus.Keyword)
  69.             {
  70.                 PromptIntegerOptions pio = new PromptIntegerOptions("\nEnter Angle");
  71.                 pio.AllowNegative = true;
  72.                 pio.DefaultValue = angle;
  73.                 PromptIntegerResult pir = Ed.GetInteger(pio);
  74.                 if (pir.Status != PromptStatus.OK) return;
  75.                 angle = pir.Value;
  76.                 ppo.Keywords.Clear();
  77.                 ppr = Ed.GetPoint(ppo);
  78.             }
  79.             if (ppr.Status != PromptStatus.OK) return;
  80.  
  81.  
  82.             try
  83.             {
  84.                 Application.PreTranslateMessage += Application_PreTranslateMessage;
  85.  
  86.                 await Ed.CommandAsync("_.PLINE", ppr.Value, "A");
  87.                 while (Settings.Variables.CMDNAMES.ToUpper().IndexOf("PLINE", System.StringComparison.Ordinal) >= 0)
  88.                 {
  89.                     try
  90.                     {
  91.                         if (negate)
  92.                         {
  93.                             negate = false;
  94.                             angle = angle * -1;
  95.                         }
  96.                         await Ed.CommandAsync("A", angle, Editor.PauseToken);
  97.                     }
  98.  
  99.                     catch (Autodesk.AutoCAD.Runtime.Exception ex)
  100.                     {
  101.                         if (ex.ErrorStatus != ErrorStatus.UserBreak)
  102.                         {
  103.                             throw;
  104.                         }
  105.                         if (endCommand)
  106.                         {
  107.                             throw;
  108.                         }
  109.  
  110.                     }
  111.  
  112.                 }
  113.             }
  114.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  115.             {
  116.                 if (ex.ErrorStatus != ErrorStatus.UserBreak)
  117.                 {
  118.                     throw;
  119.                 }
  120.  
  121.             }
  122.             finally
  123.             {
  124.                 Application.PreTranslateMessage -= Application_PreTranslateMessage;
  125.  
  126.             }
  127.         }
  128.  

*EDIT*
Sorry the command had custom OSNAPS, temporary systemvariables, and DocData class used for setting and cloning layers that are mapped to commands and block names, and I thought I stripped most of it out but missed the SendCancel, and look at ealier example by gile on looping checking CMDNAMES variables
Code - C#: [Select]
  1.  
  2.         public static void SendCommand(this Document doc, string command)
  3.         {
  4.             dynamic acadDoc = doc.GetAcadDocument();
  5.             acadDoc.SendCommand(command);
  6.         }
  7.         public static void SendCancel(this Document doc)
  8.         {
  9.             doc.SendCommand("\x03\x03");
  10.         }
  11.  





« Last Edit: December 12, 2023, 01:48:48 AM by Jeff H »