Teach Yourself Visual Studio® .NET 2003 in 21 Days [Electronic resources]

Jason Beres

نسخه متنی -صفحه : 270/ 181
نمايش فراداده

Examining the Macro Recorder Code

When using macros and add-ins, the EnvDTE COM object is what gives you the properties, methods, and events that enable you work to with the objects in the Visual Studio .NET IDE. Using the properties, methods, and events of the EnvDTE object, you can create your own macro code or modify the code generated by the macro recorder.

If you look at the References node of a project in the Macros IDE, you'll notice that the following objects are referenced:

  • EnvDTE

  • Microsoft.Vsa

  • Office

  • System

  • System.Windows.Forms

  • VSLangProj

  • VsMacroHierarchyLib

Most of those objects are COM objects that are also used in other Microsoft applications. You can see that the macro and extensibility that is being used in Visual Studio .NET is giving you some of the same functionality that you have in Office.

When you looked at the code generated for the TryCatchBlock macro, the first item in the module was the Imports statement that imported the EnvDTE namespace. The EnvDTE namespace has the properties, methods, and events that you use to manipulate the Visual Studio .NET IDE. The code that did the actual typing of the Try/Catch block was using the ActiveDocument property of the DTE object. The DTE object is the design time environment object of the current Visual Studio .NET IDE. All the objects you work with are under DTE in the object hierarchy.

The remaining code in the macro you recorded uses the DTE.ActiveDocument.Selection property to retrieve the selected area of the topmost window in the IDE. Using methods such as LineUp, LineDown, and Text, the text that you typed can be repeated by this macro.

You use two classes in the DTE object to accomplish most of your macro work: the Document object and the TextSelection object. Before you get into the objects of the EnvDTE object, you must create a new macro project to which you can add the code you write for the rest of today.

Creating a New Macro Project

To create a new macro project, close the Macros IDE and return to the LearnMacro Visual Studio .NET project.

From the Macro Explorer, right-click the topmost node and select New Macro Project, as Figure 16.7 demonstrates.

Figure 16.7. The New Macro Project menu.

When the New Macro Project pops up, name the new project Utilities as Figure 16.8 shows.

Figure 16.8. The Add New Macro Project dialog box.

After the new macro project is added to the Macro Explorer, right-click on the default Module1 in the Utilities project. Select Rename from the contextual menu and rename the module to VSMacros, as shown in Figure 16.9.

Figure 16.9. Renaming the Module1 module to VSMacros.

Next, right-click the VSMacros module and select Edit. You're now in the Macros IDE, as Figure 16.10 demonstrates.

Figure 16.10. The Utilities project in the Macros IDE.

In the next section, you're going to learn about the Document and TextSelection objects and add code to the VSMacros module.

Working with the Document Object

When you refer to the ActiveDocument in a macro, the EnvDTE returns a Document object for the ActiveDocument. Using the properties, methods, and events of the returned Document object enables you to manipulate the IDE.

To get an idea of what the Document object gives you, examine Tables 16.1 and 16.2, which respectively present the properties and methods of the Document object.

Table 16.1. Properties of the Document Object

Property

Description

ActiveWindow

Returns the current active window, or the topmost window if no others are active; returns Nothing if no windows are open

Collection

Returns the Documents collection

DTE

Returns the top-level extensibility object

Extender

Returns the requested extender object if it's available for this object

ExtenderCATID

Returns the extension category ID (CATID) for the object

ExtenderNames

Returns a list of available extenders for the object

FullName

Returns the full path and filename of a document

Kind

Returns a GUID string indicating the kind or type of the object

Name

Returns the filename of the object without the path

Path

Returns the path, without the filename, for the directory containing the document

ProjectItem

Returns the ProjectItem object associated with the given object

ReadOnly

Returns whether the document in memory can be edited

Saved

Returns True if the object has been saved since last being changed

Selection

Returns the current selection in the active window associated with this document (or the topmost window of the document if none is active)

Windows

Returns a Windows collection containing the windows that display in the object

Table 16.2. Methods of the Document Object

Method

Description

Activate

Moves the focus to the current item and makes it active

Close

Closes the open document and optionally saves it

NewWindow

Creates a new window in which to view the document

Object

Returns an interface or object that can be accessed by name at runtime

Redo

Re-executes the last action that was undone by the Undo method or the user

Save

Saves the document

SaveAll

Saves all documents currently open in the environment

Undo

Reverses the action last performed by the user in the document

An example of using the Document object properties to retrieve information about the document in the active code window is presented in Listing 16.3. Add this code to the VSMacros module as the GetDocumentInfo subprocedure.

Listing 16.3 Using the ActiveDocument Property to Retrieve Document Properties

Sub GetDocumentInfo()
If (DTE.ActiveDocument.ReadOnly) Then
MsgBox("This document is Read Only")
Else
MsgBox("This document is Writable")
End If
MsgBox("Document name = " & DTE.ActiveDocument.Name)
MsgBox("Document full name = " & DTE.ActiveDocument.FullName)
MsgBox("Document path = " & DTE.ActiveDocument.Path)
End Sub

Remember that the ActiveDocument property actually returns a Document object. To modify this to make your coding less wordy, you can create a variable of type Document and reference the object using a variable. Listing 16.4 shows the altered code to use the Document object. Add the code in Listing 16.4 to your VSMacros module as the GetDocumentInfo2 subprocedure.

Listing 16.4 Using the Document Object to Retrieve Document Properties

Sub GetDocumentInfo2()
' Create a Document variable
Dim doc As Document
If (doc.ReadOnly) Then
MsgBox("This document is Read Only")
Else
MsgBox("This document is Writable")
End If
MsgBox("Document name = " & doc.Name)
MsgBox("Document full name = " & doc.FullName)
MsgBox("Document path = " & doc.Path)
End Sub

By creating the Document variable, you still have the nice features of auto-complete and auto-list members; you just don't have to type in DTE.ActiveDocument each time you want to reference the document in the active window.

The Document object also is a member of the Documents collection. Because Visual Studio .NET enables you to have many windows open, you can write macros that use the Save and Close methods of the Document object while iterating through the Documents collection of the Windows property of the Document object. The code in Listing 16.5 is a useful snippet that saves and closes all the open windows in the IDE. Add the code in Listing 16.5 to your VSMacros module.

Listing 16.5 Saving and Closing a Document Using the Methods of the Document Object

Sub CloseAllWindows()
Dim doc As Document
For Each doc In DTE.Windows.DTE.Documents
doc.Save()
doc.Close()
Next
End Sub

By iterating through the Documents collection, you can use the Save and Close methods to take care of your open windows. This is cool because as your projects become larger, you have a bunch of tabs across the top of your designer. When you close a project, the state of the open windows is remembered for the next time you open the project. By closing all the windows, the project will have no windows open the next time you start it, which makes the startup time shorter.

The Documents collection also has a few methods that alleviate having to use the Save and Close methods on each open document. Table 16.3 lists the methods of the Documents collection.

Table 16.3. Methods of the Documents Collection

Method

Description

CloseAll

Closes all open documents in the environment and optionally saves them

Item

Returns an indexed member of a collection

SaveAll

Saves all documents currently open in the environment

Working with the TextSelection Object

The TextSelection object is the second most useful object when working with macros and the IDE. The TextSelection object directly reflects editor commands in the Visual Studio .NET IDE.

Table 16.4 lists the properties of the TextSelection object and Table 16.5 lists its methods.

Table 16.4. Properties of the TextSelection Object

Property

Description

ActivePoint

Returns the current endpoint of the selection

AnchorPoint

Returns the origin point of the selection

BottomPoint

Returns the point at the end of the selection

DTE

Returns the top-level extensibility object

IsActiveEndGreater

Indicates whether the active point is equal to the bottom point

IsEmpty

Indicates whether the anchor point is equal to the active point

Mode

Sets or returns a value determining whether dragging the mouse selects in stream mode or block mode

Parent

Returns the parent object; in this case, the TextDocument object

Text

Returns the selected text

TextPane

Returns the text pane that contains the selection

TextRanges

Returns a TextRanges collection with one TextRange object for each line or partial line in the selection

TopPoint

Returns the top end of the selection

Table 16.5. Methods of the TextSelection Object

Method

Description

ChangeCase

Changes the case of the selected text.

CharLeft

Moves the object the specified number of characters to the left.

CharRight

Moves the object the specified number of characters to the right. The default is one character.

ClearBookmark

Clears any unnamed bookmarks on the current line.

Collapse

Collapses the selection to the active point.

Copy

Copies the selection to the clipboard.

Cut

Copies the selected text to the clipboard and deletes it from its original location.

Delete

Deletes the selected text.

DeleteLeft

Deletes a specified number of characters to the left of the active point.

DeleteWhitespace

Deletes white space horizontally or vertically around the current location.

DestructiveInsert

Inserts text that overwrites the existing text.

EndOfDocument

Moves the object to the end of the document.

EndOfLine

Moves the object to the end of the current line.

FindPattern

Searches for the given pattern from the active point to the end of the document.

FindText

Searches for the given text from the active point to the end of the document.

GoToLine

Moves to the beginning of the indicated line and selects the line if requested.

Indent

Indents the selected lines by the given number of indentation levels.

Insert

Inserts the given string at the specified location.

InsertFromFile

Inserts the contents of the specified file at the current location.

LineDown

Moves the selected line down a specified number of lines.

LineUp

Moves the selected line up a specified number of lines.

MoveToAbsoluteOffset

Moves the active point to the given 1-based absolute character offset.

MoveToDisplayColumn

Moves the active point to the indicated display column.

MoveToLineAndOffset

Moves the active point to the given position.

MoveToPoint

Moves the active point to the given position.

NewLine

Inserts a line break at the active point.

NextBookmark

Moves to the location of the next bookmark in the document.

OutlineSection

Creates an outlining section based on the current selection.

PadToColumn

Fills the current line with white space to the given column.

PageDown

Moves the active point a specified number of pages down in the document, scrolling the view.

PageUp

Moves the active point a specified number of pages up in the document, scrolling the view.

Paste

Inserts the clipboard contents at the current location.

PreviousBookmark

Moves to the location of the previous bookmark in the document.

ReplacePattern

Searches for the given pattern in the selection and replaces it with new text.

ReplaceText

Searches for the given pattern in the selection and replaces it with new text.

SelectAll

Selects the document.

SelectLine

Selects the line containing the active point.

SetBookmark

Sets an unnamed bookmark on the current line.

SmartFormat

Formats the indicated line of text based on the current language.

StartOfDocument

Moves the object to the beginning of the document.

StartOfLine

Moves the object to the beginning of the current line.

SwapAnchor

Exchanges the positions of the active point and the anchor point.

Tabify

Converts spaces to tabs in the selection according to your tab settings.

UnIndent

Removes indents from the selected text by the number of indentation levels given.

Untabify

Converts tabs to spaces in the selection according to the user's tab settings.

WordLeft

Moves the object the specified number of words to the left.

WordRight

Moves the object the specified number of words to the right. The default is one word.

Using the TextSelection object, you can modify the TryCatchBlock macro you created earlier. Listing 16.6 shows how to use the TextSelection object to create a better Try/Catch macro. Add the code in Listing 16.6 to your VSMacros module.

Listing 16.6 Adding the Try/Catch Block with Streamlined Code to the VSMacros Module

Sub TryCatchBlock_vb()
Dim txt As TextSelection = _
DTE.ActiveDocument.Selection
With txt
.Text = "Try"
.NewLine(3)
.Text = "Catch ex as Exception"
.NewLine(2)
.Text = "Finally"
.NewLine(2)
.LineUp(False, 7)
End With
End Sub

Sub TryCatchBlock_cs()
Dim txt As TextSelection = _
DTE.ActiveDocument.Selection
With txt
txt.Text = "try"
.NewLine()
.Text = "{"
.NewLine(2)
.Text = "}"
.NewLine()
.Text = "catch (System.Exception ex)"
.NewLine()
.Text = "{"
.NewLine(2)
.Text = "}"
.LineUp(False, 5)
End With
End Sub

In Listing 16.6, you're creating a TextSelection variable based on the ActiveDocument.Selection property. Then, using straightforward Visual Basic .NET code, you're doing exactly what the Macro Recorder did earlier. You can see that the code you write is much cleaner than what the Macro Recorder generates. They both accomplish the same thing though: They add a Try/Catch block to your code window without you having to do it manually!

To test the code, select Close and Return from the File menu. You're now back at the Visual Studio .NET IDE, and you can double-click on your macros to test them. Your Macro Explorer should look like Figure 16.11 at this point.

Figure 16.11. The Macro Explorer with the Utilities project.

The next step is to make your macros more accessible by creating a toolbar for them.