I need to turn menus on and off, based on the language of the current window, in a solution with multiple language types. How can I determine the type of project language that I am in when a window is activated?
The problem is a bit tricky. Assuming that you have registered an event to fire when the user activates a new or different window in the IDE, you cannot check the project type of the window as soon as the WindowActivated event fires. The reason for this is that the event fires before the focus has switched to the new window. If you are using the methodology of testing the file extension of the ActiveWindow Caption, you will pick up the name of the window from which the developer is switching, not the one to which they are moving. It will not do any good to try DoEvents, as the Add-in does not relinquish control back to the IDE until it does an exit from the WindowActivated event.
My solution to this problem was to create a wrapper class for a System.Timers object and start a new thread in that class. At that point, control can be passed back to the IDE by exiting the WindowActivated event. The timer will fire in 100ms and by that time the IDE will have completed the switching to the newly selected window. It can then safely check the type of file that is in the new window. The code shown below is the code that handles the WindowActivated event and starts the timer class.
| Private Sub eventWindows_WindowActivated(ByVal GotFocus As EnvDTE.Window, _ ByVal LostFocus As EnvDTE.Window) Handles eventWindows.WindowActivated Dim t As System.Threading.Thread ' set up file type so we can toggle windows Try t = New System.Threading.Thread(AddressOf CkForTogglingMenus) t.Start() Catch End Try End Sub |
| ' Created when a window is activated or opened ' to ck the file type after the window has had ' time to change. Imports System.Timers Public Class CWindowTimer Private oVB As EnvDTE.DTE Private oUtil As CUtilities WithEvents WindowTimer As New System.Timers.Timer() Public Sub New(ByRef roVB As EnvDTE.DTE) oVB = roVB Me.WindowTimer.Interval = 100 WindowTimer.Enabled = True oUtil = New CUtilities(oVB) End Sub Private Sub WindowTimer_Elapsed(ByVal sender As Object, _ ByVal e As System.Timers.ElapsedEventArgs) _ Handles WindowTimer.Elapsed Try Dim i As Integer = oUtil.GetFileType(oVB.ActiveDocument) If i <> 0 Then modMain.FileType = i modMain.ToggleMenus(i) End If Me.WindowTimer.Enabled = False Me.WindowTimer.Interval = 0 Catch End Try End Sub Protected Overrides Sub Finalize() MyBase.Finalize() On Error Resume Next WindowTimer.Enabled = False WindowTimer.Interval = 0 WindowTimer = Nothing End Sub End Class |