From the March 2002 issue of MSDN Magazine

MSDN Magazine

Visual Studio .NET: Setting Tab Order, Loading the Toolbox with an Add-in

Ken Spencer

Download the code for this article: Basics0203.exe (102KB)

Q In Visual Studio® .NET, how do you set the tab order of controls in an application? Is it similar to the way it was done in previous versions of Visual Basic® or did Microsoft leave out this feature?
A** Not only did Microsoft not leave this feature out, they added it and many other features into the designer. The Windows® controls have a TabIndex property just like Visual Basic controls in the past. The question is, how do you set the index easily? Figure 1 shows a simple form with three textboxes. They are not on the form in the order they were dropped, as the TabIndex property is set to 0, 2, and 1 from the top down.

Figure 1 Setting Tab Indexes
Figure 1 Setting Tab Indexes

      To set the tab order, you simply select all three textboxes, then select Tab Order from the View menu. Then just click the controls in the order you want the tabs to sit. As you click each control, the tab order will be displayed on the control to keep you up to date. Press Esc when you're finished.
Q** During the Microsoft® .NET tour and in your training classes, you show an add-in for loading the Visual Studio .NET Toolbox. Can you explain how this add-in was created?
A** This add-in demonstrates the serious power of Visual Studio .NET for both the individual developer and a development team. The add-in is used to load the Toolbox with code chunks.
      I'll describe its construction by first walking through the creation of a generic add-in. Then I'll discuss the other pieces of code you need to create the toolbox add-in.
      To create an add-in, follow these steps:

  1. Start a new project using File | New Project.

  2. Select Visual Studio .NET Add-in as the project type from the Other Projects | Extensibility Projects folder, as shown in Figure 2.

    Figure 2 Visual Studio .NET Add-in
    Figure 2 Visual Studio .NET Add-in

  3. Enter a file name, then click OK. This will start the add-in wizard.

  4. Click Next on the introductory screen of the wizard.

  5. Select the language to use (Visual Basic .NET, of course), then click Next.

  6. Select whether the add-in will work only in Visual Studio .NET or in the macro IDE, then click Next.

  7. Enter a name and description for the add-in, then click the Next button.

  8. On the Options page, select the first checkbox to create a Tools menu option. Select any other options you need on this page. For this macro, I chose to leave the others blank. Click Next when finished, then click Finish to complete the add-in framework.

      The wizard creates Connect.vb and other files for the project and creates a setup project that will generate a Windows Installer file to install your add-in on another system. That's it. Now you have the code for the add-in—or at least the code that makes the add-in work.
      The rest of the add-in is where the .NET Framework comes in. Your add-in can do all sorts of things because it's a .NET application that happens to hook into Visual Studio .NET. Let's look at a few of the pieces.
      The wizard creates the Exec procedure that is executed when the add-in runs, as shown in Figure 3. In this procedure, you hook your custom code into the add-in. For my application, I created a Windows Form named frmToolBoxLoader. This form contains the interface that allows the developer to select which code files to load into the toolbox. At this point, the form can access the file system, a database, or any other resource needed by the application.
      To add the Windows Form to the application, add a reference to System.Windows.Forms by right-clicking the References folder and selecting System.Windows.Forms, as shown in Figure 4.

Figure 4 Add a Reference
Figure 4 Add a Reference

      Now you can add a Windows Form just like you would in a Windows-based application. The application is shown in Figure 5.

Figure 5 Code Loader
Figure 5 Code Loader

      Just after the handled = True line in Figure 3, add the following two lines to call the form:

  Dim frmLoad As New frmToolBoxLoader(applicationObject)
  
frmLoad.Show()

This instantiates the form and passes it the instance of the current DTE (Design-Time Environment) object.
      The only magic in the form so far is one line of code. The following line of code creates a reference to the design environment that will allow the application to access features such as the Solution Explorer or the Toolbox:

  Private applicationObject As EnvDTE.DTE 
  

The previous line of code is placed just after the class definition.
      The next code change occurs in the constructor. The new constructor shown here performs a couple of tasks:

  Public Sub New(ByVal CurrentDTE As EnvDTE.DTE)
  
MyBase.New()
Cursor.Current = Arrow
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the
'InitializeComponent() call
applicationObject = CurrentDTE
LoadSnippets()
End Sub

The interface to the constructor has one parameter: the current DTE passed in from the Exec routine. Then the applicationObject variable is set to this value, and finally the LoadSnippets function is called to load all of the code modules found.
      I will spare you all of the LoadSnippets details as it simply calls a GetFiles function to find all of the files in the code directory. You can walk through the samples for the LoadSnippets details, which is available for download at the link at the top of this article. The file names are loaded into an array which is then sorted alphabetically by calling the Sort method of the Array class. Then the array is processed and a Checkbox is added to the form for each name.
      The code in Figure 6 comes from the GetFiles function and shows how the checkboxes are loaded on the form. You can see how each checkbox is created and then added to the Controls collection. The x and y variables control the location of each checkbox to place them properly on the form, spacing them out and putting them into multiple columns as necessary.
      To use the add-in, the developer starts it from the menu (or puts it on a toolbar), then selects the checkboxes to load and clicks the LoadToolbox button, which calls the procedure shown in Figure 7. This code loops through the Controls collection to find the Checkbox controls selected by the developer. The General and DataCode items were checked as they were loaded and were disabled (so they cannot be unchecked). As the controls are processed, the DeleteTab function is called to delete the tab from the toolbox if it already exists. This limits the custom items in the toolbox to those selected during the current operation. For each control that was checked, the SetupSnippets function is called to load the selection. The code for this procedure is shown in Figure 8.
      You can see how the ToolBox item is referenced, then used to add the node. First, a tab is created complete with the tab name:

  tab = tbox.ToolBoxTabs.Add(sTabName) 
  

Then the code loops through the nodes from the XML file and adds each item to the new tab by calling the Add method:

  For Each node In nodes
  
tab.ToolBoxItems.Add(node.Attributes(0).Value, _
node.InnerText, _
vsToolBoxItemFormat.vsToolBoxItemFormatText)
Next

Finally, the tab is activated, like so:

  tab.Activate() 
  

You can watch all of this happen if you have the toolbox showing when you click the Load button.
      The DeleteTab code shown in Figure 9 is quite simple. It loops through the tabs on the toolbox and deletes the matching tab. This add-in is nice because you can use it to access all types of code, load it into your project, and quickly add it to your apps.
      The next step in this application is to replace the XML features and point to data housed in a shared database. Then any number of developers can access the same codebase. You can also point the DotNetSeminarinfo.xml file (which goes in your Windows NT® or Windows directory) at a network location for the SnippetPath (which contains the code files):

  <?xml version="1.0"?>
  
<ToolBoxTab Name="Seminar Information">
<SnippetPath XMLDir="C:\DotNetDevTraining\DemoSnippets">
</SnippetPath>
</ToolBoxTab>


      The other piece of this add-in is the setup process. You can simply build the setup project, then locate the .MSI file. This is the distribution file for moving the add-in to another system.

Conclusion

      This month I showed you how Visual Studio .NET can be used to make development easier, faster, and more reusable. The .NET Framework coupled with Visual Studio .NET can reduce both the time and cost of your development project quite a bit (including the maintenance), especially if you use proper design and development techniques.

Send questions and comments for Ken to basics@microsoft.com.

Ken Spencer works for the 32X Tech Corporation (https://www.32X.com), which produces a line of developer courseware. Ken also spends much of his time consulting or teaching private courses.