< Free Open Study > 

Making Good Use of DTE Events

Now that you have seen how to set up and trap the major events within the IDE, you may be asking what you can do with the information. In this section, you are going to add code to some of the event handlers that will allow you to provide useful features to an add-in. This will not be an exhaustive study of the events, but it should spark your thinking and cause you to look for ways to use the information provided by the events.

Using the WindowActivated Event

The WindowActivated event is raised each time a window receives focus. This gives you an opportunity to enforce a small, but significant standard. When a new class, module, or form is added to the project, the first thing that you should do is change the default name of the file from Module1, Class1, or Form1 to some more meaningful name that will describe its contents or purpose. Yet, many times in the heat of the battle, developers forget to do simple things like this. Later on, they find themselves wondering where some code is located. Giving meaningful names to files and methods, which provides developers a good head start on organizing their code, could have solved that problem.

In the WindowActivated event, I have called the CkForRemindOfDefaultName of the CReminder class. This method looks for forms, modules, and classes whose names have never been changed from the default name provided when they were initially added to the project.


Visual Studio .NET makes it easy for the user to change a default name. At the time that a new item is added to the project, the Add New Item dialog box is displayed to allow the user to choose or confirm the type of item to be added. At the same time, the default name is highlighted in the Name text box. All developers have to do is to start typing the name of the new item. Therefore, you should not worry about reminding them if they did not take advantage of that option when adding the new item.

If you implement such a feature in your add-in, you might consider having a way to turn this feature off, as it may become annoying to developers who choose not to change the name. However, this feature can be used to enforce a standard of changing to a meaningful name.With this feature activated, developers will probably change the name just so they will not have to keep clicking the OK button on the message box.

Listing 11-14 shows the new code for the WindowActivated event handler. It calls a method of the Creminder class that is shown in Listing 11-17.

Listing 11-14: Using the WindowActivated Event

start example
 Private Sub eventWindows_WindowActivated(ByVal GotFocus As EnvDTE.Window, _    ByVal LostFocus As EnvDTE.Window)     Handles eventWindows.WindowActivated    ' Let's do something useful    ' if the window name is a default name, e.g, Form(n),    ' Module(n) or Class(n)    ' suggest to the user that they need to rename it    oRemind.CkForRemindOfDefaultName(GotFocus.Caption)    ' task item removed does not always fire because of    ' multiple events firing, so place the calls in this    ' event to force the closing of the task list    If GotFocus.Caption.StartsWith("Task List") Then       oRemind.CkForClosingTaskList()    End If    If LostFocus.Caption.StartsWith("Task List") Then       oRemind.CkForClosingTaskList()    End If End Sub 
end example

Figure 11-1 shows a display of the message box reminding the user to change the default name of Form1.

click to expand
Figure 11-1: Reminding the user to change the name of Form1

Using the TaskList Object's ItemAdded Event

When you enter a line of code into the Text Editor that will generate a compile error, a to-do item is automatically placed into the Task List.


A to-do item is placed automatically in the Task List in Visual Basic only. This is not done in Visual C# until you compile the project.

Although I do not want to have to answer a message box, it would be nice for the Task List to automatically open and remain open to remind me to correct the problem immediately. Sometimes I may have to enter some other code before the error is cleared up. This would be the case if I enter a call to a procedure that does not yet exist. Even in this case, I may need to be reminded to code that procedure. Having the Task List automatically open to show the to-do item seems to me to be a nice touch.

I have added special code to the TaskAdded event handler. This code automatically opens the Task List when an item is added to the Task List. In addition to opening the window, I have set the AutoHides property to False. This will keep me from ignoring the error and attempting to compile the program only to find, to my surprise, that I have one or more errors. Along with the code that I have added to the TaskRemoved event handler, the window will stay open until I have corrected all of the lines with errors in them.


If you implement this feature in your add-in, you might consider having a way to disable it. This feature may annoy the developer that uses your add-in and it does not enforce any standards—it is simply a quick reminder of errors being created as the developer is coding.

Listing 11-15 shows the code for the new ItemAdded event of the TaskListEvents object.

Listing 11-15: TaskListEvents ItemAdded Event

start example
 Private Sub taskListEvents_TaskAdded(ByVal TaskItem As EnvDTE.TaskItem) _    Handles taskListEvents.TaskAdded    ow.WriteOutputWindow("TaskListEvents::TaskAdded", _       vbTab & "Task description:        " & TaskItem.Description)    oRemind.ActivateTaskList() End Sub 
end example

Using the TaskRemoved Event

Listing 11-16 shows the new code for the ItemRemoved event of the TaskListEvents object. This code calls the CkForClosingTaskList method of the CReminder class. That method checks the count of items in the Task List, and if it is zero, it automatically hides the Task List window.

Listing 11-16: New TaskRemoved Event

start example
 Private Sub taskListEvents_TaskRemoved(     ByVal TaskItem As EnvDTE.TaskItem)     Handles taskListEvents.TaskRemoved    ow.WriteOutputWindow("TaskListEvents::TaskRemoved",        vbTab & "Task description: " &        TaskItem.Description)    ORemind.CkForClosingTaskList() End Sub 
end example


You cannot always depend on the sequence of the firing of events, and in fact, you cannot always depend on certain events firing if other events are firing at the same time, which is often the case. For that reason, the ItemRemoved event of the TaskListEvents object does not always fire. Therefore, the CkForClosingTaskList method may not always be called. In testing, I have found this sequence to be erratic at best. For that reason, I have placed calls to the CReminder class in the WindowActivated event handler. Placing these extra calls helps get the Task List closed.

Figure 11-2 shows a display of the Task List that has been activated because an item has been added to the Task List. You will note that Task List already has some error items in it. Even if the developer closes the Task List with errors in it, it will pop up again if another error is entered into the Task List.

click to expand
Figure 11-2: Task List activated by code with errors

CReminder Class

I have created a new class called the CReminder class. Initially it contains only three public methods that perform the functions described in the two previous sections. However, this class provides the container for other methods and functionality that you can add as you think through some of the features that you would like to trigger upon the occurrence of a DTE event. Listing 11-17 shows the code for this class.


In the CkForRemindOfDefaultName method I keep a record of the files that have been passed to the method. I did this so that I will not display the reminder message every time the window is activated. That would be a little too annoying to developers. It will remind them once per instance of the IDE.

You will notice that I am using the StringBuilder object at the beginning of the CkForRemindOfDefaultName method. The StringBuilder object is new to Visual Basic .NET. It creates a mutable (changeable) string that can be appended to without having to recreate a new string as it does when you simply use a String variable. The StringBuilder object, sb, is created in the constructor of the CReminder class.

Listing 11-17: CReminder Class

start example
 Imports Microsoft.Office.Core Imports Extensibility Imports System.Runtime.InteropServices Imports EnvDTE Public Class CReminders    Private DefaultName As String    Private sb As System.Text.StringBuilder    Private oVB As EnvDTE.DTE    Public Sub CkForRemindOfDefaultName(ByVal winCaption As String)       ' Display message to remind the developer to change       ' the name of the file from the default name if they       ' have not already done so. However, don't do it but       ' once per instance of the IDE.       ' DefaultName is a string variable which simply contains       ' the winCaption parameter concatenated with all previous       ' names, separated by "_".       ' if the name is extant in the string, don't put it       ' there again or notify the user.       If sb.ToString.IndexOf(winCaption) > -1 Then Exit Sub       If (Left(winCaption, 4) = "Form" And _           winCaption.EndsWith("[Design]")) Or _          Left(winCaption, 6) = "Module" Or _          Left(winCaption, 5) = "Class" _          Then          MsgBox(winCaption & " still has a default name;" &              vbLf &              "it should be changed to a more meaningful name.",              MsgBoxStyle.Exclamation, "Change Default Name")          sb.Append(winCaption & "_")    End If End Sub Public Sub ActivateTaskList()    Dim win As Window =            oVB.Windows.Item(Constants.vsWindowKindTaskList)       win.Activate()       win.AutoHides = False    End Sub    Public Sub CkForClosingTaskList()       Dim win As Window =           oVB.Windows.Item(Constants.vsWindowKindTaskList)       Dim tskList As TaskList = win.Object       If tskList.TaskItems.Count = 0 Then          win.AutoHides = True       End If       win.Activate()    End Sub    Public Sub New(ByVal roVB As EnvDTE.DTE)       oVB = roVB       sb = New System.Text.StringBuilder() End Sub End Class 
end example

 < Free Open Study > 

Writing Add-Ins for Visual Studio  .NET
Writing Add-Ins for Visual Studio .NET
ISBN: 1590590260
EAN: 2147483647
Year: 2002
Pages: 172
Authors: Les Smith © 2008-2017.
If you may any questions please contact us: