views:

235

answers:

1

I'm working in Visual Studio 2008 and I would like for Edit > Outlining > Collapse to Definitions to be run whenever I open a file. It would be nice if, after that, all regions were expanded. I tried the code that Kyralessa offered in a comment on The Problem with Code Folding, and that works very nicely as a macro that I have to run manually. I tried to expand this macro to act as an event by placing the following code in the EnvironmentEvents module in the Macro IDE:

Public Sub documentEvents_DocumentOpened(ByVal Document As EnvDTE.Document) Handles DocumentEvents.DocumentOpened
    Document.DTE.ExecuteCommand("Edit.CollapsetoDefinitions")
    DTE.SuppressUI = True
    Dim objSelection As TextSelection = DTE.ActiveDocument.Selection
    objSelection.StartOfDocument()
    Do While objSelection.FindText("#region", vsFindOptions.vsFindOptionsMatchInHiddenText)
    Loop
    objSelection.StartOfDocument()
    DTE.SuppressUI = False
End Sub

However, this does not seem to do anything when I open a file from my Solution in VS. To test that the macro was getting run, I put a MsgBox() statement in that subroutine and noticed that code before Document.DTE.ExecuteCommand("Edit.CollapsetoDefinitions") ran fine, but nothing seemed to get hit after that line. When I debugged and set a breakpoint within the subroutine, I would hit F10 to continue to the next line and control would leave the subroutine as soon as that ExecuteCommand line ran. Despite this, that line seems to do nothing, i.e. it doesn't collapse the outlining.

I also tried using just DTE.ExecuteCommand("Edit.CollapsetoDefinitions") within the subroutine but with no luck.

This question tries to obtain the same end result as this one, but I'm asking about what I might be doing wrong in my event-handling macro.

+1  A: 

The problem is that the document is not really active when the event fires. One solution is to use a "fire once" timer to execute the code a short delay after the DocumentOpened event occured:

Dim DocumentOpenedTimer As Timer

Private Sub DocumentEvents_DocumentOpened(ByVal Document As EnvDTE.Document) Handles DocumentEvents.DocumentOpened
    DocumentOpenedTimer = New Timer(AddressOf ExpandRegionsCallBack, Nothing, 200, Timeout.Infinite)
End Sub

Private Sub ExpandRegionsCallBack(ByVal state As Object)
    ExpandRegions()
    DocumentOpenedTimer.Dispose()
End Sub

Public Sub ExpandRegions()
    Dim Document As EnvDTE.Document = DTE.ActiveDocument
    If (Document.FullName.EndsWith(".vb") OrElse Document.FullName.EndsWith(".cs")) Then
        If Not DTE.ActiveWindow.Caption.ToUpperInvariant.Contains("design".ToUpperInvariant) Then
            Document.DTE.SuppressUI = True
            Document.DTE.ExecuteCommand("Edit.CollapsetoDefinitions")
            Dim objSelection As TextSelection = Document.Selection
            objSelection.StartOfDocument()
            Do While objSelection.FindText("#region", vsFindOptions.vsFindOptionsMatchInHiddenText)
            Loop
            objSelection.StartOfDocument()
            Document.DTE.SuppressUI = False
        End If
    End If
End Sub

I haven't tested it extensively, so there might be some bugs... Also, I added a check to verify that the active document is a C# or VB source code (not tested with VB though) and that it's not in design mode.
Anyway, hope it works for you...

Julien Poulin
Holy crap, it works! I had to add an `Imports System.Threading` line in my EnvironmentEvents macro for `Timer` and `Timeout`, but it works! I open my CS files now and, after about a second, all my definitions are collapsed. Thanks!
Sarah Vessels
I have noticed that when I open a new Solution and it remembers what files I had open last time, the macro IDE has to close because of an error.
Sarah Vessels
Yep, I got the error too. I tried to solve the problem but couldn't find a solution and I've already spend too much time on it. If I think of something else, I'll post it. In the meantime, you could just use a boolean (set to false in the Solution_Opened event) to activate/deactivate the feature and bind it to a keyboard shortcut.
Julien Poulin