Helixoft Blog

Peter Macej - lead developer of VSdocman - talks about Visual Studio tips and automation

How To Show Full File Path (or Anything Else) in VS 2005 Title Bar

I saw an interesting request on discussion forums today. A user wants to show the full path of currently edited file in the IDE main window caption. This used to be case in VS .NET 2003 but VS 2005 shows only solution name.

Visual Studio 2005 title bar showing only solution name

I thought it had to be easy to write macro which does the job. It turned it was more difficult than it seemed but finally it worked. Your title bar will look like this:

New VS 2005 title bar with full file path

To create and apply this macro:

  1. Go to menu Tools - Macros - Macros IDE...
  2. In the Macros IDE Class View navigate to MyMacros - {} MyMacros - EnvironmentEvents. Open (double-click) EnvironmentEvents.
  3. Paste this code inside module (just before End Module line):
        Private timer As System.Threading.Timer
        Private ideTitle As String = Nothing
    
        Declare Auto Function SetWindowText Lib "user32" (ByVal hWnd As System.IntPtr, _
        ByVal lpstring As String) As Boolean
    
        '''<summary>Called when any window in VS gets activated.</summary>
        '''<param name="GotFocus">Window that got focus.</param>
        '''<param name="LostFocus">Window that lost focus.</param>
        Private Sub WindowEvents_WindowActivated(ByVal GotFocus As EnvDTE.Window, ByVal LostFocus As EnvDTE.Window) Handles WindowEvents.WindowActivated
            Try
                If timer Is Nothing Then
                    ' Create timer which refreshes the caption because
                    ' IDE resets the caption very often
                    Dim autoEvent As New System.Threading.AutoResetEvent(False)
                    Dim timerDelegate As System.Threading.TimerCallback = _
                        AddressOf tick
                    timer = New System.Threading.Timer(timerDelegate, autoEvent, 0, 200)
                End If
    
                If GotFocus.Document Is Nothing Then
                    ideTitle = Nothing
                Else
                    ideTitle = GotFocus.Document.FullName
                    showTitle(ideTitle)
                End If
            Catch ex As System.Exception
            End Try
        End Sub
    
        ''' <summary>Dispose the timer on IDE shutdown.</summary>
        Public Sub DTEEvents_OnBeginShutdown() Handles DTEEvents.OnBeginShutdown
            If Not timer Is Nothing Then
                timer.Dispose()
            End If
        End Sub
    
        '''<summary>Called by timer.</summary>
        Public Sub tick(ByVal state As Object)
            Try
                If Not ideTitle Is Nothing Then
                    showTitle(ideTitle)
                End If
            Catch ex As System.Exception
            End Try
        End Sub
    
        '''<summary>Shows the title in main window.</summary>
        Private Sub showTitle(ByVal title As String)
            SetWindowText(New System.IntPtr(DTE.MainWindow.HWnd), title & " - " & DTE.Name)
        End Sub
  4. That's all. Close macro IDE and restart VS.

How it works

This macro handles VS events. To do so, you must write it in special module: EnvironmentEvents. In this case we handle WindowEvents.WindowActivated event.

There were several problems that I needed to solve:

  1. You cannot use DTE.MainWindow.Caption to set the title bar. It throws an exception. This property can only be used for reading it. To set the title, we need to use API call to SetWindowText.
  2. VS IDE is very aggressive when setting the caption. Once we set our own caption in event handler when some document window is selected, the IDE sets its own caption immediatelly after that. So I had to set the timer which refreshes the title bar every 200 milliseconds. This seems to work perfectly. If you know better solution, please let us know here in comment section.
  3. We cannot use Timer class from Windows.Forms namespace. It simply doesn't work in macro. We need to use System.Threading.Timer.

You can of course change title bar text to anything you want. The macro code is really simple.

Comments   

0 # kyong 2007-07-31 18:20
tried it out, but having to refresh every 200 milliseconds kills the mojo for me... maybe if there was a simpler way.. =) but nice work!!
Reply | Reply with quote | Quote
0 # Charles 2007-10-11 23:15
This is GREAT! It works well... now how about something similar for Visual Studio 6? For long paths, all I get is "[C:\...\DStrin gUtils.h]"

Charles.
Reply | Reply with quote | Quote
0 # santosh 2008-01-30 05:46
The Macro is not compiling [ok I am trying this for VS 2003]
SetWindowText(D TE.MainWindow.H Wnd, ideTitle & " - " & DTE.Name)
HWND is integer whereas it is expected System.IntPtr.

Did you try this with 2003 as well? or is there some setting with that IDE?

Thanks for your time!!
Reply | Reply with quote | Quote
0 # Peter Macej 2008-01-30 09:05
You are right. You have probably set Option Strict On in your macros. The solution is simple. Just use:
SetWindowText(New System.IntPtr(D TE.MainWindow.H Wnd), ideTitle & " - " & DTE.Name)
I will update the main post as well.
Reply | Reply with quote | Quote
0 # Jimmy 2008-02-05 00:20
I love this macro but I noticed it causes some undesirable side effects in the IDE:

1) Find in Files window has focus taken away from it when I click in it. The workaround is to first click the titlebar for the window and then I can navigate around in it, but the usability is really hampered here.

2) The IDE usually crashes on shutdown. The crash happens in the VS Macros host.

3) The macro only works if a source file is opened. Is there a way to have it use the path of the open Solution instead in that case?

Any ideas how these issues could be worked around?
Reply | Reply with quote | Quote
0 # yusheng 2008-03-03 09:11
This article is very useful for me. I want to write a samilar macros, however, there are some errors.
when the WindowActivated event occurs, I want to adjust the activetated document window. I try to set the GotFocus.Width, it throws an Exception. Then I use the SetWindowPos for a try. But the value of GotFocus.HWnd is zero. The HWnd property is only used for Microsoft in MSDN. I'm not good at VB. I hope you can give me some suggestion about how to adjust the window in this situation. Please email me,
Reply | Reply with quote | Quote
0 # Jimmy 2008-03-03 12:31
I solved all of the problems I mentioned in my Feb 5 post.

The crash on shutdown is due to the Timer not being Disposed(). I added the following to fix that:

Public Sub DTEEvents_OnBeg inShutdown() Handles DTEEvents.OnBeginShutdown
If Not timer Is Nothing Then
timer.Dispose()
End If
End Sub

Since I wanted the macro to display information on the solution, I changed the event to be this:

Public Sub SolutionEvents_ OnOpened() Handles SolutionEvents.Opened
SetupTitlebar()
End Sub

Private Sub SetupTitlebar()
Try
If timer Is Nothing Then
' Create timer which refreshes the caption because
' IDE resets the caption very often
Dim autoEvent As New System.Threading.AutoResetEvent(False)
Dim timerDelegate As System.Threadin g.TimerCallback = _
AddressOf tick
timer = New System.Threadin g.Timer(timerDe legate, autoEvent, 0, 1000)
End If

If DTE.Solution Is Nothing Then
ideTitle = Nothing
Else
Dim StartIndex As Integer
Dim EndIndex As Integer
Dim Found As Boolean

Found = False

ideTitle = DTE.Solution.FullName

StartIndex = InStr(ideTitle. ToLower(), ":\")
If (StartIndex > 0) Then
ideTitle = Mid(ideTitle, StartIndex + 2)
Found = True

StartIndex = InStr(ideTitle. ToLower(), "dev\")
If (StartIndex = 1) Then
ideTitle = Mid(ideTitle, StartIndex + 4)
End If
End If

If (Found) Then
EndIndex = InStr(ideTitle, "\")
If (EndIndex > 0) Then
ideTitle = Left(ideTitle, EndIndex - 1)
End If
End If
End If

showTitle(ideTitle)
Catch ex As System.Exception
End Try
End Sub

This also fixed the focus problems with FindInFiles
Reply | Reply with quote | Quote
0 # Peter Macej 2008-03-03 12:43
Thank you Jimmy. You are right, the timer needs to be disposed when IDE closes. I have updated the code with your function.
Reply | Reply with quote | Quote
0 # Derek Morin 2008-04-02 02:08
Seems to work like a charm. Too bad it is flashy, but sounds like that is visual studios problem, and you've managed a good workaround.
Reply | Reply with quote | Quote
0 # Phil 2008-12-09 20:49
Related note: As an alternative, for Visual Studio 2005 you can use the command File -> Advanced Save Options. The dialog displays the full path of the current file, and you are able to copy the text.
Reply | Reply with quote | Quote
0 # Michael 2009-01-26 18:10
THANK YOU!!!!!!!
Reply | Reply with quote | Quote
0 # Jimmy 2009-02-22 22:18
I have been using this for about a year now (see my earlier post) Unfortunately I have been unable to completely fix the hang on shutdown problem, even with the Timer.Dispose call. I wish there was a way to fix this.
Reply | Reply with quote | Quote
0 # Tom Pester 2010-09-21 11:17
Thanks for the macro. I just tried it in VS2010 and it seems to work ok..
Reply | Reply with quote | Quote
0 # shane 2011-01-26 01:49
This is awesome, good nice work
Reply | Reply with quote | Quote
0 # . 2012-03-10 00:51
THANK YOU
Reply | Reply with quote | Quote
0 # Kevin Whitefoot 2012-05-03 14:26
Thanks. It just works! Running it in VS2010. We maintain multiple releases of the same software and often have to do a side by side comparison during debugging. Without the path it is impossible to tell just from the names which release I am looking at, this saves me a lot of messing about.
Reply | Reply with quote | Quote
0 # Lee Willis 2012-05-03 23:36
I used this for a while, but had problems when I tried to record a macro (probably caused by the timer). I use the MKLINK command to create a link to the solution. Have a look on this page - http://willissoftware.com/?p=72
Reply | Reply with quote | Quote
0 # Kevin Whitefoot 2012-05-07 10:04
I made a couple of changes, the most important for me was to display the solution path as well. In order to conserve space I also split the common substring of the solution and file paths to show that first:

...

Dim sSolution = GotFocus.Document.DTE.Solution.FullName
Dim sDocument = GotFocus.Document.FullName
Dim iPrefixLen = CommonPrefixLen gth(sSolution, sDocument)
Dim sPrefix = sSolution.Subst ring(0, iPrefixLen)
ideTitle = sSolution.Subst ring(0, iPrefixLen) & " - " & sSolution.Subst ring(iPrefixLen ) & " - " & sDocument.Substring(iPrefixLen)

...

Private Function CommonPrefixLen gth(ByVal s1 As String, ByVal s2 As String) As Integer
Dim iMax = Math.Min(s1.Len gth, s2.Length)
For i = 0 To iMax - 1
If s1(i) s2(i) Then
Return i
End If
Next
Return iMax
End Function
Reply | Reply with quote | Quote
0 # dratengon 2012-10-16 11:54
Kevin Whitefoot, "If s1(i) s2(i) Then" is "s1(i) > s2(i)" or "s1(i)
Reply | Reply with quote | Quote
0 # dratengon 2012-10-16 11:55
where do u put these code?
Reply | Reply with quote | Quote
0 # User 2013-02-25 20:03
Works gr8 with VS2010. thnx dude.
Reply | Reply with quote | Quote
0 # lyen 2014-03-24 06:45
This doesn't work for my Visual Studio 2005 Version 8.0.50727.867 :-(
Reply | Reply with quote | Quote
0 # Peter Macej 2014-03-24 08:44
Do ANY of your macros work? If not, it's probably a known issue caused by February Windows update. See http://visualstudioextensions.vlasovstudio.com/2014/02/13/visual-studio-2010-macros-stop-working-after-february-2014-windows-update/ for solutions how to fix it.
Reply | Reply with quote | Quote

Add comment


Security code
Refresh

 

Start generating your .NET documentation now!
DOWNLOAD
Free, fully functional trial

VSdocman

Document your .NET code on professional level.

XML comments - generate MSDN documentation and IntelliSense

Create MSDN-like class documentation with IntelliSense and F1 help for your C# and VB projects. See how easy the code commenting can be with powerful comment templates and sophisticated WYSIWYG comment editor.

More... | Download