October 2014

Sun Mon Tue Wed Thu Fri Sat
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  










« F# takes an important step closer to official release | Main | Preventing a .NET module from being loaded by AutoCAD »

September 05, 2008

No muttering at the back! Reducing the background noise when sending commands to AutoCAD

Since posting three different options for Zooming to a Window or Entity inside AutoCAD, I've had a few discussions with a developer on how best to implement this cleanly. The requirement is to change the AutoCAD view via a smooth view transition (currently not exposed via any kind of view-modification API, only via the ZOOM command), but also to hide the fact we're sending commands to the command-line to do so.

While we were discussing, I remembered an old friend, the NOMUTT system variable, which allows almost all command-line noise to be filtered out - even the "Command:" prompt disappears. While this technique is useful for this specific situation, it's also potentially very useful for many other instances where sending commands are currently the best available method of accessing particular functionality inside AutoCAD.

A word of caution: setting NOMUTT to 1 can lead to severe user-disorientation. Please remember to set the variable back to 0, afterwards!

Here's the modified C# code showing this technique - this time using SendStringToExecute() from the .NET API, rather than the COM API's synchronous SendCommand():

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.Geometry;


namespace ZoomSmoothlyAndQuietly

{

  public class Commands

  {

    // Zoom to a window specified by the user


    [CommandMethod("LZW")]

    static public void LoudZoomWindow()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;


      Point2d min, max;

      if (GetWindowForZoom(ed, out min, out max))

        ZoomWin(ed, min, max, false);

    }


    [CommandMethod("QZW")]

    static public void QuietZoomWindow()

    {

      Document doc =

        Application.DocumentManager.MdiActiveDocument;

      Editor ed = doc.Editor;


      Point2d min, max;

      if (GetWindowForZoom(ed, out min, out max))

        ZoomWin(ed, min, max, true);

    }


    // Get the coordinates for a zoom


    static private bool GetWindowForZoom(

      Editor ed, out Point2d min, out Point2d max

    )

    {

      min = new Point2d();

      max = new Point2d();


      PromptPointOptions ppo =

        new PromptPointOptions(

          "\nSpecify first corner:"

        );


      PromptPointResult ppr =

        ed.GetPoint(ppo);


      if (ppr.Status != PromptStatus.OK)

        return false;


      min =

        new Point2d(ppr.Value.X, ppr.Value.Y);


      PromptCornerOptions pco =

        new PromptCornerOptions(

          "\nSpecify opposite corner: ",

          ppr.Value

        );


      ppr = ed.GetCorner(pco);


      if (ppr.Status != PromptStatus.OK)

        return false;


      max =

        new Point2d(ppr.Value.X, ppr.Value.Y) ;


      return true;

    }


    // Zoom by sending a command


    private static void ZoomWin(

      Editor ed, Point2d min, Point2d max, bool quietly

    )

    {

      string lower =

        min.ToString().Substring(

          1,

          min.ToString().Length - 2

        );


      string upper =

        max.ToString().Substring(

          1,

          max.ToString().Length - 2

        );


      string cmd =

        "_.ZOOM _W " + lower + " " + upper + " ";


      if (quietly)

      {

        // Get the old value of NOMUTT


        object nomutt =

          Application.GetSystemVariable("NOMUTT");


        // Add the string to reset NOMUTT afterwards


        cmd += "_NOMUTT " + nomutt.ToString() + " ";


        // Set NOMUTT to 1, reducing cmd-line noise


        Application.SetSystemVariable("NOMUTT", 1);

      }


      // Send the command(s)


      ed.Document.SendStringToExecute(

        cmd, true, false, !quietly

      );

    }

  }

}

Here's what happens when we run the "loud" command (LZW), and then the "quiet" one (QZW):

Command: LZW

Specify first corner:

Specify opposite corner:

Command: _.ZOOM

Specify corner of window, enter a scale factor (nX or nXP), or

[All/Center/Dynamic/Extents/Previous/Scale/Window/Object] <real time>: _W

Specify first corner: 13.1961936276982,12.972925917324 Specify opposite corner:

30.6221132095147,0.482638801189623

Command: QZW

Specify first corner:

Specify opposite corner:

Command:

Both versions of the command deliver the results in terms of smooth view transitions, but the quiet version reduces the command-line clutter by a) passing a flag to SendStringToExecute() to stop the command from being echoed and b) setting the NOMUTT system variable to prevent the command "muttering" from being echoed. It uses a simple trick to reset the system variable afterwards by appending "_NOMUTT 0 " to the string to be executed (which we don't see, as NOMUTT is still set to 1 :-). Assuming the ZOOM command terminates correctly, the NOMUTT system variable should be reset: there is a slight risk that something causes ZOOM to fail, at which point it might be worth checking NOMUTT from time to time elsewhere in your app: as mentioned earlier, having NOMUTT set to 1 can be very disconcerting for the user. I should, in fact, probably just force NOMUTT to 0 after the ZOOM (if you check the the above code, you'll see we reset it to the prior value, which is generally a good technique when modifying system variables as they retain the value previously chosen by the user). Anyway - I'll leave the final choice up to you, but do be aware of the risk.

Update:

Undo is a problem with this implementation - havin NOMUTT as a separate command leaves it at risk of being undone by the user (leaving the system in a scary, silent state). This post presents an enhanced approach which provides much better support for undo.

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83452464869e200e554d76c3b8833

Listed below are links to weblogs that reference No muttering at the back! Reducing the background noise when sending commands to AutoCAD:

blog comments powered by Disqus

Feed/Share

10 Random Posts