Implementing task dialogs inside AutoCAD using .NET - Part 1

This is a topic I've been meaning to get to for some time... as I finally had to research it for a side project I'm working on, I decided to go ahead and post my findings here.

AutoCAD 2009 makes heavy use of task dialogs, which are basically message-boxes on steroids. MSDN contains documentation on Microsoft's implementation of task dialogs, although our implementation is a little different.

Why bother with these new task dialogs? They provide a way of asking more user-friendly questions using actual actions as answers rather than yes/no/cancel etc. It's a bit like the way I now often seem to be asked questions such as "who packed this bag?" when flying, these days, rather than "did you pack this bag yourself?" - you have to think a little more, but that usually increases the chances of getting accurate information. Alright, perhaps the airline security analogy wasn't all that appropriate, after all, but hopefully you get the idea.

In this first part of the two-part series we're going to look at the basic steps to add task dialogs to our projects, showing a very basic example that gives an idea of their capabilities, and in the next part we'll see a much more concrete, real-world implementation example.

The first thing to do to make use of task dialogs in your application is to add a reference to the AdWindows.dll assembly. You should find it in AutoCAD 2009 (but not previous versions), in the root application folder. As usual when adding AutoCAD's managed assemblies to your project, remember to set the "Copy Local" flag to false, to avoid problems later. Once we've added this reference we're able to use the Autodesk.Windows namespace (not to be confused with Autodesk.AutoCAD.Windows, which is AutoCAD-specific).

Here's our initial C# code to show a very basic task dialog, without doing very much with the information provided:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.Windows;

namespace TaskDialogs

{

  public class Commands

  {

    [CommandMethod("Task1")]

    public static void TestingTaskDialogOptions()

    {

      Editor ed =

        Application.DocumentManager.MdiActiveDocument.Editor;

      // Create the task dialog itself

      TaskDialog td = new TaskDialog();

      // Set the various textual settings

      td.WindowTitle = "The title";

      td.MainInstruction = "Something has happened.";

      td.ContentText =

        "Here's some text, with a " +

        "<A HREF=\"http://adn.autodesk.com\">" +

        "link to the ADN site</A>";

      td.VerificationText = "Verification text";

      td.FooterText =

        "The footer with a "+

        "<A HREF=\"http://blogs.autodesk.com/through" +

        "-the-interface\">link to Kean's blog</A>";

      td.EnableHyperlinks = true;

      td.EnableVerificationHandler = true;

      // And those for collapsed/expanded text

      td.CollapsedControlText =

        "This control text can be expanded.";

      td.ExpandedControlText

        = "This control text has been expanded..." +

          "\nTo span multiple lines.";

      td.ExpandedText = "This footer text has been expanded.";

      td.ExpandFooterArea = true;

      td.ExpandedByDefault = false;

      // Set some standard icons and display of the progress bar

      td.MainIcon = TaskDialogIcon.Shield;

      td.FooterIcon = TaskDialogIcon.Information;

      td.ShowProgressBar = true;

      // A marquee progress bas just loops,

      // it has no range  fixed upfront

      //td.ShowMarqueeProgressBar = true;

      // Now we add out task action buttons

      td.UseCommandLinks = true;

      td.Buttons.Add(

        new TaskDialogButton(

          1,

          "This is one course of action."

        )

      );

      td.Buttons.Add(

        new TaskDialogButton(

          2,

          "Here is another course of action."

        )

      );

      td.Buttons.Add(

        new TaskDialogButton(

          3,

          "And would you believe we have a third!"

        )

      );

      // Set the default to be the third

      td.DefaultButton = 3;

      // And some radio buttons, too

      td.RadioButtons.Add(new TaskDialogButton(4, "Yes"));

      td.RadioButtons.Add(new TaskDialogButton(5, "No"));

      td.RadioButtons.Add(new TaskDialogButton(6, "Maybe"));

      // Set the default to be the second

      td.DefaultRadioButton = 5;

      // Allow the dialog to be cancelled

      td.AllowDialogCancellation = false;

      // Implement a callback for UI event notification

      td.Callback =

          delegate(

            ActiveTaskDialog atd,

            TaskDialogEventArgs e,

            object sender

          )

          {

            ed.WriteMessage(

              "\nButton ID: {0}",

              e.ButtonId

            );

            ed.WriteMessage(

              "\nNotification: {0}",

              e.Notification

            );

            if (e.Notification ==

              TaskDialogNotification.VerificationClicked)

            {

              atd.SetProgressBarRange(0, 100);

              atd.SetProgressBarPosition(80);

            }

            else if (e.Notification ==

              TaskDialogNotification.HyperlinkClicked)

            {

              ed.WriteMessage(" " + e.Hyperlink);

            }

            ed.WriteMessage("\n");

            // Returning true will prevent the dialog from

            // being closed

            return false;

          };

      td.Show(Application.MainWindow.Handle);

    }

  }

}

When we execute the TASK1 command, we can see this dialog gets displayed:

Basic task dialog with all the options

This dialog exercises most of the UI options available in the TaskDialog class. You'll see a progress bar (which gets modified via the ActiveTaskDialog passed into the notification callback - try checking the "Verification text" box to see that happen) as well as option buttons, action buttons and some expandable text.

Here's how the dialog looks with the text expanded and the verification checkbox ticked:

Our basic task dialog with expanded text and verification ticked

It's worth playing around with the code to see how the notification is provided to the application, and how the ActiveTaskDialog can be used from there to modify the state of the dialog. One thing you'll notice is that the hyperlinks don't automatically result in a browser being launched, which overall is a good thing, as the links can then be set up to result in other actions (the application has all the information it needs to know what was clicked in the notification callback - if it wants to launch a browser to the clicked URL, it is free to do so).

Now that we've explored the various options open to us, in the next post we'll look at a more real-world example of using a task dialog to help manage potentially time-consuming application behaviour.

Update

In AutoCAD 2010 the TaskDialogEventArgs class was renamed to TaskDialogCallbackArgs, apparently to be more consistent with .NET naming conventions. If you receive an error such as "The type or namespace name 'TaskDialogEventArgs' could not be found (are you missing a using directive or an assembly reference?)" when building your application, updating the name to be TaskDialogCallbackArgs will resolve it.

8 responses to “Implementing task dialogs inside AutoCAD using .NET - Part 1”

  1. Hi Kean,
    Good topic.
    I translated this into VB, and had a conundrum on this part:

    td.Callback = delegate(
    ActiveTaskDialog atd,
    TaskDialogEventArgs e,
    object sender
    )....
    so I pulled it out to it's own function and did this:
    td.Callback = AddressOf tdCallBack

    which does seem to be catching the callbacks, but it threw an error on "atd.SetProgressBarState(Autodesk.Windows.ProgressBarState.Normal)"
    and ultimately crashed AutoCAD after a second error that occured after the callback. I commented out that line and it seems to work fine.
    the error was System.NotSupportedException
    Message="Specified method is not supported."
    Source="AdWindows"
    and came with a stack trace 52 calls long.

  2. Hi David,

    Strange - not sure why it would be different in your version... I don't remember especially why I put the SetProgressBarState() call in there, so it could possibly be redundant or even erroneous (although I didn't see a crash).

    Kean

  3. Kean,

    I received the same error as David on the same line.

    The crash manifests when you hit the checkbox at the bottom of the dialog.

    AutoCAD 2009
    Visual C# Express 2008
    .NET 3.5

  4. David, Glenn,

    OK - you have me convinced. ๐Ÿ™‚

    For some reason it works fine on my (Vista) machine, but I can see no reason for the call being there & removing it does nothing to the behaviour. I suspect it's just an artifact from me testing out the various properties/methods.

    So I've removed it from the post. Thanks for the report & confirmation!

    Kean

  5. Glenn did not mention his OS but I am on ACAD2009, VB pro 2005, .NET 2, and XP pro. Just for giggles I looked at the link above to the Microsoft implementation, and it says the required version is Vista, so that's probably it.

  6. Autodesk's implementation was independent - I'm assuming to support XP as well as Vista. So that's not going to be the problem.

    The call doesn't need to be made there, so it's safe to ignore the problem (I expect calling it on TaskDialog rather than ActiveTaskDialog works just fine).

    Kean

  7. Thomas Keymeulen Avatar
    Thomas Keymeulen

    Hi Kean,

    I'm currently working in a furniture firm on the enginering department. Last year I followed 1 year Visual.NET programming.
    This morning I received the question wether I could develop a program in AutoCAD 2009 speed up the design of furniture. The thing is, I've never developped something in AutoCAD with VBA.
    Can I try this best with VBA or start programming in VB.NET?
    Do you know where I can find information/tutorials/help the help me develop this application?

    Many thanks!!!

    Kind regards

  8. Hi Thomas,

    I would start directly with VB.NET: Microsoft is putting everything behind their .NET technology and VBA isn't really supported by them anymore (there's no native 64-bit version of VBA, for instance).

    So go directly with VB.NET (or C#), using either standard Visual Studio or Visual Basic (C#) Express.

    I would (of course ๐Ÿ™‚ recommend using this blog as a resource, and you can post your questions to the AutoCAD .NET Discussion Group. If your company is serious about helping your customization work, they might also invest in an ADN membership.

    Regards,

    Kean

Leave a Reply to David Osborne Cancel reply

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