Introduction
This is an alternate to the Source Code Outliner Power Toy and the Class View. It is an add-in that places a drop-down list (DDL) of methods next to the Help menu. Select a method and jump to that spot in code, the full line is highlighted and the first line is scrolled to the top of the code window.
This project exercises VS. NET 2008 IDE Extensibility. The first incarnation was a VB6 project to do the same DDL for the MS Office IDE. I missed the Methods DDL functionality in VS.NEt. I'm posting the project so others can either use (at their own risk) or customize for their own use.
Background
The Methods DDL overcomes shortcomings of the std. IDE navigation.
- The std. dual DDL approach is cumbersome for navigation, requiring selection from two DDLs.
- After selecting the navigation target, because the line is not highlighted, it can be difficult to find the selected line.
- The std. methods DDL has used and unused methods, so it can be quite long.
The Methods DDL takes less real estate than the Source Code Outliner Power Toy, and is simpler to navigate than the class viewer.
Using the Code
Two downloads are available: an installer and source code.
To install and use the add-in:
- Unzip and run Setup.exe. (Uninstall from Add/Remove Programs).
- When VS is opened, you'll see the DDL next to the Help DDM. (The first time VS is opened after the install, you may see two instances of the DDL. The second DDL will disappear the next time VS is started.)
- When a module (std or class) is opened for editing, the DDL list repopulates.
- The list is updated as you add or delete methods in your source code.
- Drop down the list of methods and select one to navigate to the first line of the target method.
- The code pane scrolls if possible so that the first line of the target method is at the top of the pane.
The following is for developers interested in modifying/working with the code:
The source code project is for VS2008 in VB.NET. Unzip to your Visual Studio 2008 Projects folder. The source code is set up to run in debug and uses a special .addin. The special .addin is named "Proc_DDL - For Testing.AddIn" and needs to be placed in "C:\Documents and Settings\%USERNAME%\My Documents\Visual Studio 2008\Addins". You will need to unzip the special .addin from the Debug_Addin zip to the Addins folder. Only the Assembly node in the .addin is different between the debug and release usage; examples are shown below. Be sure the installed version is uninstalled via Add/Remove Programs; if you plan to use the project in Debug mode, then open the .sln with VS2008.
<Assembly>C:\Documents and Settings\%USERNAME%\My Documents\Visual
Studio 2008\Projects\Proc_DDL\Proc_DDL\bin\Proc_DDL.dll</Assembly>
The installable uses a different .addin with an Assembly
line like this:
<Assembly>Proc_DDL_Addin\Proc_DDL.dll</Assembly>
Which locates the add-in DLL in the Proc_DDL_Addin folder of the target add-in folder, in my case:
[PersonalFolder]\Visual Studio 2008\Addins
Where [PersonalFolder] is C:\Documents and Settings\%USERNAME%\My Documents (the default location in the setup project).
If you need to switch the project back from Debug to Release mode, special care is needed with the .addin files. For Debug mode, use "Proc_DDL - For Testing.AddIn". For Release mode, rename "Proc_DDL - For Testing.AddIn" to "Proc_DDL - For Testing.AddIn_" so the release version "Proc_DDL.AddIn" will work. Reverse that process to go back to Debug mode. The .addin specifies where the .dll is located. "Proc_DDL - For Testing.AddIn" specifies the project folder with the debug info. "Proc_DDL.Addin" specifies the target installation folder from the setup project, in this case "[PersonalFolder]\Visual Studio 2008\Addins\Proc_DDL". Both .addins are actually placed in "[PersonalFolder]\Visual Studio 2008\Addins":
- for testing/debug "Proc_DDL - For Testing.AddIn" must be the active .addin,
- an install will put "Proc_DDL.Addin" in "[PersonalFolder]\Visual Studio 2008\Addins".
If both .addins are active, the Methods DDL will not work. Hence the renaming of the test version of .addin when you install the add-in for "release" usage.
Carlos Quintero, MzTools, has a detailed discussion of the .addin locations, see Default .AddIn file locations for Visual Studio add-ins. For MzTools, internationalization requires a different kind of DLL locator, so the Registry has SatelliteDLLName and Path info for MzTools (registered with RegAsm).
If you plan on modifying the source code, please visit the MSDN library, under Visual Studio 2008, find "Visual Studio Automation and Extensibility", subtopic "Walkthrough: Debugging an Add-in Project."
Running the project in debug requires setting the configuration to "Debug", and under Tools/Options, expand the Debugging node, then under General, clear "Warn if no user code on launch". This prevents an annoying warning popping up during testing. Regardless of the warning, test runs work fine (as long as the .addin is configured correctly).
Points of Interest
In the VB6 incarnation for the MS Office IDE, I was unable to get at IDE events, so I used a Refresh button to restock the DDL of methods. The VS IDE events expose two important improvements for the Methods DDL: windows and code model events (without these events, a Refresh button would be needed as in the MS Office IDE).
Avenues of exploration are:
- IDE events which are quite rich in VS Extensibility,
- Menu bars and controls, and
- The code model navigation, pane, and text management.
To get at the target events, begin with IDTExtensibility2.OnConnection
which gets wired up when the Extensibility type project gets selected under the [New>Project>Other Project Types] menu in Visual Studio. A casting cascade is needed to go from the general connection object variable (oApp
) down to Events2 which is needed for oWinEvents
and oCodeModelEvents
. (I relied on MSDN to get samples of much of this code.)
Public Sub OnConnection( _
ByVal oApp As Object, _
ByVal oConnectMode As ext_ConnectMode, _
ByVal oThis_AddIn As Object, _
ByRef custom As Array) _
Implements IDTExtensibility2.OnConnection
Dim oEvents2 As EnvDTE80.Events2
oDTE2 = CType(oApp, DTE2)
oAddIn = CType(oThis_AddIn, AddIn)
oEvents2 = CType(oDTE2.Events, EnvDTE80.Events2)
oWinEvents = CType(oEvents2.WindowEvents(Nothing), EnvDTE.WindowEvents)
oCodeModelEvents = oEvents2.CodeModelEvents(Nothing)
The event objects that must work in the VS IDE need to be public with events as implemented in the following code segment:
Public Class Connect
Implements IDTExtensibility2
Private oDTE2 As DTE2
Private oAddIn As AddIn
Public WithEvents oWinEvents As EnvDTE.WindowEvents
Public WithEvents oCodeModelEvents As EnvDTE80.CodeModelEvents
Public WithEvents cbComboBox As CommandBarComboBox
Private oTbl As DataTable
Private oDocCurrent As Document
pb_ProcDDLStarted
is a flag used to ensure that there is only one DDL insert; it is set to False
during class initialization.
If you want to relocate or resize the Methods DDL, reposition by changing cbControl_Help
as you like or the width and drop down lines for cbComboBox
.
If Not pb_ProcDDLStarted Then
pb_ProcDDLStarted = True
Dim oCommands As Commands2 = CType(oDTE2.Commands, Commands2)
Dim cbs As CommandBars = CType(oDTE2.CommandBars, CommandBars)
Dim mbCommandBar As CommandBar = cbs.Item("MenuBar")
Dim cbControl_Help As CommandBarControl = mbCommandBar.Controls.Item("Help")
Dim iCmdPosition As Integer = CInt(CType(cbControl_Help.Index, Long) + 1)
Dim cbControls As CommandBarControls = mbCommandBar.Controls
cbComboBox = CType(cbControls.Add(MsoControlType.msoControlComboBox), _
CommandBarComboBox)
Try
With cbComboBox
.Enabled = False
.Width = 300
.DropDownLines = 70
End With
oWinEvents_WindowActivated
calls a refresh sub to repopulate the methods DDL if window.kind
is "Document." OnCodeElement_Added
and OnCodeElement_Deleted
handle refreshing after adding and deleting methods. OnCodeElement_Changed
was not necessary, see line 284 (if the code changes, the start point is handled automatically) (I left OnCodeElement_Changed
in comments in case you want to use it).
(I also left in the code for a Refresh button in the event that you want to play with that.)
Refresh Method
Start by examining sb_Refresh
. sb_OutlineCode
and sb_OutlineElement
populate oTbl
which is used by sb_PopulateCombobox
. The outline functionality walks through the file code model, then the code elements recursively to capture all the function names.
Go To DDL Selection
Wiring up cbComboBox
to handle the selection of a method is done in OnConnection
, see the pb_ProcDDLStarted
block above. The code is pretty straightforward except for the use of MsoControlType.msoControlComboBox
. The use of the MS Office control types in Visual Studio seemed a bit odd to me.
sb_OutlineCode
is used again except the search function moves to the start point of the selected method, selects the entire line, then attempts to move the start point for the function to the top of the pane. There is a side effect if the code is collapsed; when the + sign is clicked on a fully selected line, the expanded section is all selected. The following code does the move to start point, line select, and code pane adjustment.
If oCTElems.Item(i).Name = sProcName Then
Dim oSel As TextSelection _
= CType(oDocCurrent.Selection, TextSelection)
Dim oTextPane As TextPane _
= oSel.TextPane
With oSel
.MoveToPoint(oCTElems.Item(i).StartPoint)
.SelectLine()
oTextPane.TryToShow(oCTElems.Item(i).StartPoint, vsPaneShowHow.vsPaneShowTop)
End With
End If
History
- First release: 2009.07.23.
- Beta test: 2009.07.27: David Larson reported two DDLs for initial use of the add-in. Subsequent uses of the add-in only had one DDL. Despite special care to prevent more than one DDL, the VS IDE was firing the add-in
onConnection
twice on the first use. During testing, I saw the same initial two DDLs.
- Beta test: 2009.07.27. The add-in does not work with VS2008 Express Edition.
- 2009.08.07: Added handler for Forms Designer. Add-in was not skipping the outline for design documents.
- 2009.08.07: Tested in WPF to be sure the outliner was skipped for XAML documents.