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  










« 5 tips for creating a successful Autodesk Exchange app | Main | Adding an expanding textbox to AutoCAD’s ribbon using .NET »

September 14, 2011

Adding a textbox to AutoCAD’s ribbon using .NET

This is a really cool little sample put together by Philippe Leefsma, from our DevTech team in Europe, with the help of George Varghese from the AutoCAD Engineering team. Thanks, Philippe and George! :-)

This question came up, recently: an ADN member wanted to be able to add an editable textbox to the ribbon inside AutoCAD and then be notified of the data entered into it, as well as being notified when the control gained and lost focus.

Here’s some simple C# code that does just this:

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.EditorInput;

using Autodesk.AutoCAD.Runtime;

using Autodesk.Windows;

using System.Windows.Controls;

using System.Windows.Input;

using System.Windows;

using System;

 

namespace NotifyingRibbonTextbox

{

  public class Commands

  {

    public bool _added = false;

 

    [CommandMethod("RTB")]

    public void RibbonTextBox()

    {

      if (!_added)

      {

        // Look for the standard "Plug-ins" tab

 

        RibbonControl rc = ComponentManager.Ribbon;

        RibbonTab rt = null;

 

        foreach (RibbonTab tab in rc.Tabs)

        {

          if (tab.AutomationName == "Plug-ins")

          {

            rt = tab;

            break;

          }

        }

 

        // If we didn't find it, create a custom tab

 

        if (rt == null)

        {

          rt = new RibbonTab();

          rt.Title = "Custom";

          rt.Id = "ID_CUSTOMRIBBONTAB";

          rc.Tabs.Add(rt);

        }

 

        // Create our custom panel, add it to the ribbon tab

 

        RibbonPanelSource rps = new RibbonPanelSource();

        rps.Title = "Notifying Textbox";

        RibbonPanel rp = new RibbonPanel();

        rp.Source = rps;

        rt.Panels.Add(rp);

 

        // Create our custom textbox, add it to the panel

 

        NotifyingTextBox tb = new NotifyingTextBox(150);

        tb.IsEmptyTextValid = false;

        tb.AcceptTextOnLostFocus = true;

        tb.InvokesCommand = true;

        tb.CommandHandler = new TextboxCommandHandler();

        rps.Items.Add(tb);

 

        // Set our tab to be active

 

        rt.IsActive = true;

 

        // We only want to add it once, so set a flag

 

        _added = true;

      }

    }

 

    public static void Print(string s)

    {

      // A simple helper to write to the command-line

 

      Document doc =

        Autodesk.AutoCAD.ApplicationServices.

        Application.DocumentManager.MdiActiveDocument;

      doc.Editor.WriteMessage(s);

    }

  }

 

  public class TextboxCommandHandler : ICommand

  {

#pragma warning disable 67

    public event EventHandler CanExecuteChanged;

#pragma warning restore 67

 

    public bool CanExecute(object parameter)

    {

      // Yes, we can execute

 

      return true;

    }

 

    public void Execute(object parameter)

    {

      // Dump the textbox contents to the command-line

 

      NotifyingTextBox tb = parameter as NotifyingTextBox;

      if (tb != null)

      {

        Commands.Print(

          "\nRibbon Textbox: " +

          tb.TextValue + "\n"

        );

        tb.ClearText();

      }

    }

  }

 

  public class NotifyingTextBox : RibbonTextBox

  {

    public NotifyingTextBox(double width)

    {

      Width = width;

      MinWidth = width;

 

      // Register our focus-related event handlers

 

      EventManager.RegisterClassHandler(

        typeof(TextBox), TextBox.GotKeyboardFocusEvent,

        new RoutedEventHandler(OnGotFocus)

      );

 

      EventManager.RegisterClassHandler(

        typeof(TextBox), TextBox.LostKeyboardFocusEvent,

        new RoutedEventHandler(OnLostFocus)

      );

    }

 

    public void ClearText()

    {

      TextValue = "";

    }

 

    // Both events call the same helper, with a custom message

 

    private void OnGotFocus(object sender, RoutedEventArgs e)

    {

      OnFocusChange(sender, e, "\nTextbox got focus :)\n");

    }

 

    private void OnLostFocus(object sender, RoutedEventArgs e)

    {

      OnFocusChange(sender, e, "\nTextbox lost focus :(\n");

    }

 

    // Our helper function to print  a message only when

    // our custom textbox exists

 

    private void OnFocusChange(

      object sender, RoutedEventArgs e, string msg

    )

    {

      if (e != null && e.Source != null)

      {

        TextBox tb = e.Source as TextBox;

 

        if (tb != null)

        {

          NotifyingTextBox mtb =

            tb.DataContext as NotifyingTextBox;

 

          if (mtb != null)

          {

            Commands.Print(msg);

          }

        }

      }

    }

  }

}

 

There are a few points worth noting about this implementation:

  • We register event handlers to check when our custom NotifyingTextBox receives or loses focus.
    • These both call the same helper function, to avoid duplicated code.
  • We attach a "command handler" that notifies us when the user hits enter after typing a string.
    • It's important to set the IsEmptyTextValid flag to false if we want to stop empty “commands” from coming through (this doesn’t stop the TextBox from being empty, just from it calling through to Execute() when it is).
    • During the Execute() method of the handler, we extract the TextValue from the NotifyingTextBox before clearing it.

Let’s see what happens when you build this code into a .NET assembly, NETLOAD it and execute the RTB command. Firstly, it adds a new control to the “Plug-ins” tab, if it’s found (otherwise it will create its own “Custom” tab):

Notifying textbox in the ribbon

As we set focus to that control and set it back elsewhere, we see messages printed to the command-line:

Command: RTB

Command:

Textbox got focus :)

Textbox lost focus :(

As we enter text into the custom textbox, and hit return:

Our typed message

We see the text echoed to the command-line, too:

Ribbon Textbox: This is a message from Kean

That's it for today’s post. Next time we'll extend this implementation to auto-resize as text is entered into the box.

blog comments powered by Disqus

Feed/Share

10 Random Posts