CHAPTER 10
In the prior chapters, we’ve looked at the Visual Studio environment and the solution and projects that a user can edit. In this chapter, we are going to explore the open windows and files that a user can be working with in Visual Studio at any given time.
When you open Visual Studio, even without a solution open, a number of windows are created by the application for helping with the development tasks. These are referred to as your tool windows. When you edit a source code file or a form, these are open in an editor window, and referred to as document windows. You can do some interaction with these windows, such as resizing them, moving them, activating and closing them, etc.
When you open Visual Studio, the following tool windows are generally open even before you open a solution.
You can find the associated window by stepping through the Windows Collection property on the application object. The window object will have basic window manipulation properties, but you can cast it to a specific window type, such as the Solution Explorer, the Error List, etc. We will cover some of the tool windows in more detail in Chapter 14.
Once you open a solution in Visual Studio, every open source-file will be placed into a document window. The type of window varies depending on the type of file being edited. The Code Window holds source code files, such as VB or C# code. HTML or ASPX files have another editor, visual design tools, etc.
The Window object contains properties and methods to do basic manipulation of the window itself, not its contents.
You can manipulate the window’s location and behavior using the coordinates and some Boolean options:
You can manipulate the window using a few methods:
The ActiveWindow property returns a reference to the window object that currently has focus in Visual Studio. Typically, this will be a document window containing the code currently being edited, but can be any window the user clicked on. If no solution is open, the ActiveWindow will return the main window. You can test the Kind property to see if a “document” or “tool” window is currently active.
The main window is a special window distinct from other windows in the environment. It is typically maximized and the docking window for all the other tool and document windows the user might have open. The Boolean properties of AutoHides and IsFloating are not defined for the main window.
The main window’s Kind property will be Tool and its Type property will be vsWindowTypeMainWindow.
The windows collection contains a list of all windows in the IDE (some of which may not be visible). You can iterate through this list or search for a particular toll window using the vsWindowsKind constants. For example, the following code sample gets a few selected windows and saves them to variables for easier reference:
|
DTE2 theApp = _applicationObject; Window theSolExploer = theApp.Windows.Item(Constants.vsWindowKindSolutionExplorer); Window theProperties = theApp.Windows.Item(Constants.vsWindowKindProperties); Window theCallStack = theApp.Windows.Item(Constants.vsWindowKindCallStack); |
You can also walk through the windows collection, or search for all document windows as the following code sample illustrates:
|
foreach (Window theWind in _applicationObject.Windows) { if (theWind.Kind == "Document") { MessageBox.Show(theWind.Caption); } } |
This can be useful if you want your add-in to provide an option to scan all open documents rather than the entire project.
The following WindowKind constants are available to find particular windows in the collection:
You can use these constants to find a particular window, or test the ObjectKind property of a window against the constant to know the window you are interacting with, as follows:
|
if (theWind.ObjectKind == EnvDTE.Constants.vsWindowKindCallStack) { // Do something with call stack. } |
Several of the various tool windows can be cast to object types to allow properties and methods specific to that particular tool. These include:
|
CommandWindow theCMD = _applicationObject.ToolWindows.CommandWindow; ErrorList theErrs = _applicationObject.ToolWindows.ErrorList; UIHierarchy theSolExplore = _applicationObject.ToolWindows.SolutionExplorer; OutputWindow theOutput = _applicationObject.ToolWindows.OutputWindow; TaskList theTaskList = _applicationObject.ToolWindows.TaskList; ToolBox theToolBox = _applicationObject.ToolWindows.ToolBox; |
The tool window types are explored in more detail in Chapter 14.
In addition to the supporting tool windows, there are a number of different editors that might be used when a source file is open. The most common is the code window (which we discuss in Chapter 12 and Chapter 13); however, you can use the window object to gather some information about the source code being edited.
When you obtain a window’s object, either through the ActiveWindow property or by searching the Windows collection, you can use the Kind property of “document” to know it is a source file being editing in the IDE. The window will also have an Object property associated with it, and you can test the type of this property to determine what kind of source window is being looked at. For example, the following code can test whether Visual Studio is looking at some sort of HTML code:
|
Window ActiveWin = _applicationObject.ActiveWindow; // Grab the active window. if (ActiveWin.Object is HTMLWindow) { HTMLWindow theHTML = (HTMLWindow)ActiveWin.Object; // Cast as an HTML window. } |
You can use the Visual Basic Assemblies, which are automatically included in VB projects but need to be added manually to C# projects, to determine the type of a window. The following code shows the type of window, which you can then cast the object to:
Microsoft.VisualBasic.Information.TypeName(ActiveWin.Object) |
If you want to have your add-in manipulate different kinds of windows, this can help you find the window type to cast the object property to.
For a simple example of how to use the window object, we are going to write an add-in that will determine whether the HTML or ASPX code currently open in the active window appears to be using AJAX. AJAX requires a script manager object and at least one Update Panel. This wizard will look at the HTML code in the designer window and see if both elements are found.
We are still going to use the wizard to create our basic add-in, so fire up the wizard with the following:
Although this is a simple wizard, it will show the basics of how to parse HTML code being edited in Visual Studio.
In our Exec() method of the code, we need to get the active window and make sure it is not a tool window. The following code does that:
|
if(commandName == "IsAjaxEnabled.Connect.IsAjaxEnabled") { handled = true; Window ActiveWin = _applicationObject.ActiveWindow; // Grab the active window. if (ActiveWin.Kind != "Document") { // Tell user only wants on document windows. MessageBox.Show("Please select an HTML or ASPX page to check...."); return; } |
Note: Don’t forget to add the reference to System.Windows.Forms for the MesageBox().
Once we know it is a document window, we want to confirm it is a HTML window and if so, typecast the window object to HTML Window.
|
// And only for HTML modules (ASPX, HTML, etc.). if (ActiveWin.Object is HTMLWindow) { HTMLWindow theHTML = (HTMLWindow)ActiveWin.Object; // Cast as an HTML window. Boolean FoundSM = false; Boolean FoundUP = false; |
We are also setting up our flags to check the AJAX code samples we are searching for.
We can write our own HTML code parser if we are feeling particularly ambitious, but to keep things simple, we will use Microsoft’s parser instead.
The HTML Window object we created previously has a property called CurrentTab, which can be:
If the HTML window is on the design page, the CurrentTabObject property will contain a reference to the HTML document object from the page. So we are going to save the user's current mode, and if need be, switch to the design tab so we can grab that HTML document for our parsing purposes.
|
vsHTMLTabs PriorMode = theHTML.CurrentTab; // See if in Design mode, and if not, switch to it. if (theHTML.CurrentTab != vsHTMLTabs.vsHTMLTabsDesign) { theHTML.CurrentTab = vsHTMLTabs.vsHTMLTabsDesign; } if (theHTML.CurrentTab == vsHTMLTabs.vsHTMLTabsDesign) { // Get an HTML document from the current object in the design window. IHTMLDocument2 theHTMLDoc = (IHTMLDocument2)theHTML.CurrentTabObject; |
Note: You’ll need to add a reference to Microsoft.mshtml to create the HTML document object.
Once you have the HTML document object, you can use the object to walk through the entire document model. For our code, we are simply searching each element to see if we find a script manager and an update panel.
|
foreach (IHTMLElement element in theHTMLDoc.all) { try { if (element.outerHTML.ToUpper().Contains("ASP:SCRIPTMANAGER")) { FoundSM = true; } if (element.outerHTML.ToUpper().Contains("ASP:UPDATEPANEL")) { FoundUP = true; } } catch { } } |
There is a lot of functionality built into the HTML document object. You could simply set the BGColor property and the IDE will add the appropriate element to the document and mark the source HTML file as edited. The scope of the HTML document is beyond this book, but can be a very useful starting point if you want to manipulate HTML or ASPX code opened in Visual Studio.
Once we’ve made our loop through the HTML elements, we want to return the designer back to its original mode, and then report our findings.
|
if (theHTML.CurrentTab != PriorMode) { theHTML.CurrentTab = PriorMode; } // Evaluate flags to see if we are using AJAX. if (FoundSM && FoundUP) { MessageBox.Show("AJAX appears to be in use on this form"); } else { if (FoundSM) { MessageBox.Show("Script Manager found, but no update panels..."); } if (FoundUP) { MessageBox.Show("Update Panel(s) found, but missing Script Manager..."); } } if (FoundSM == false && FoundUP == false) { MessageBox.Show("AJAX does not appears to be used on this form"); } |
While this add-in module performs a very simple task, it does provide an example of how to easily parse HTML code. Microsoft .NET provides a nice collection of tools to manipulate HTML, and plugging that into the windows of the add-in code should give you a good starting point to develop tools for your HTML code.