How to: Handle Automation Events (Visual C#)

The procedure below demonstrates how to handle window-related events by using a Visual C# add-in.

Note

The dialog boxes and menu commands you see might differ from those described in Help depending on your active settings or edition. These procedures were developed with the General Development Settings active. To change your settings, choose Import and Export Settings on the Tools menu. For more information, see Customizing Development Settings in Visual Studio.

  1. Create a Visual Studio add-in project by using Visual C#.

  2. In the OnConnection method, initialize a variable to intercept events. In the example below, this variable is named events.

    EnvDTE.Events events = _applicationObject.Events;
    
  3. In the OnConnection method, retrieve the event objects from the automation model.

    winEvents = (EnvDTE.WindowEvents)events.get_WindowEvents(null);
    

    In this example, the variable is called winEvents. Other objects in the automation model relate to other types of events. For example, FindEvents applies to events related to find operations, and TaskListEvents applies to events related to the Task List. For a complete list of available events, see Responding to Automation Events.

  4. In the OnConnection method, connect to each delegate exposed from the event objects retrieved in step three (3) by using the += operator. For example, to connect the delegates exposed by the WindowClosing event, you would use:

    winEvents.WindowClosing += new  
    _dispWindowEvents_WindowClosingEventHandler(this.WindowClosing);
    
  5. Add procedures for each event related to the event object. For example, to handle the event that occurs when a window is closed (WindowClosing), you would use:

    public void WindowClosing(EnvDTE.Window closingWindow)
    {
        outputWindowPane.OutputString ("WindowEvents::WindowClosing\n");
        outputWindowPane.OutputString("\tWindow: " + 
        closingWindow.Caption + "\n");
    }
    

    In the case of the WindowEvents object, you must have procedures for all of its events, namely:

  6. Finally, to prevent Visual Studio from slowing your system by continuing to monitor window-related events after you close the add-in, disable event handling. In Visual C#, this is done by using the -= operator. For example, to disable event handling for WindowClosing you would use:

    public void OnDisconnection(ext_DisconnectMode disconnectMode, 
    ref Array custom)
    {
        if (winEvents != null)
        {
            winEvents.WindowClosing -= new 
            _dispWindowEvents_WindowClosingEventHandler     
            (this.WindowClosing);
        }
    }
    

    This turns off event handling whether the add-in is shut down, or the IDE is shut down while the add-in is still running. When the IDE is shut down, all running add-ins are automatically shut down first.

Example

The following example is a basic Visual C# add-in that demonstrates how to intercept and handle window-related events in Visual Studio. Whenever window-related events occur, a notification message is sent to the Output window.

namespace CSEventsAddin
{
    using System;
    using Microsoft.VisualStudio.CommandBars;
    using Extensibility;
    using EnvDTE;
    using EnvDTE80;

    public class Connect : Object, IDTExtensibility2
    {
        public Connect()
        {
        }

        public void OnConnection(object application, ext_ConnectMode 
        connectMode, object addInInst, ref Array custom)
        {
            _applicationObject = (DTE2)application;
            _addInInstance = (AddIn)addInInst;

            // Retrieve the event objects from the automation model.
            EnvDTE.Events events = _applicationObject.Events;
            // Send event messages to the Output window.
            OutputWindow outputWindow = 
            (OutputWindow)_applicationObject.Windows.Item
            (Constants.vsWindowKindOutput).Object;
            outputWindowPane = outputWindow.OutputWindowPanes.Add("DTE 
Event Information");
            // Retrieve the event objects from the automation model.
            winEvents = 
            (EnvDTE.WindowEvents)events.get_WindowEvents(null);

            // Connect to each delegate exposed from each object 
            // retrieved above.
            winEvents.WindowActivated += new 
            _dispWindowEvents_WindowActivatedEventHandler
            (this.WindowActivated);
            winEvents.WindowClosing += new  
            _dispWindowEvents_WindowClosingEventHandler
            (this.WindowClosing);
            winEvents.WindowCreated += new  
            _dispWindowEvents_WindowCreatedEventHandler
            (this.WindowCreated);
            winEvents.WindowMoved += new 
            _dispWindowEvents_WindowMovedEventHandler
            (this.WindowMoved);
        }

        public void OnDisconnection(ext_DisconnectMode disconnectMode, 
        ref Array custom)
        {
            // If the delegate handlers have been connected, then 
            // disconnect them here. 
            // If this is not done, the handlers may still 
            // fire until the next garbage collection event.
            if (winEvents != null)
            {
                winEvents.WindowActivated -= new 
                _dispWindowEvents_WindowActivatedEventHandler
                (this.WindowActivated);
                winEvents.WindowClosing -= new 
                _dispWindowEvents_WindowClosingEventHandler
                (this.WindowClosing);
                winEvents.WindowCreated -= new 
                _dispWindowEvents_WindowCreatedEventHandler
                (this.WindowCreated);
                winEvents.WindowMoved -= new 
                _dispWindowEvents_WindowMovedEventHandler
                (this.WindowMoved);
            }
        }

        // Window-related events.
        public void WindowClosing(EnvDTE.Window closingWindow)
        {
            outputWindowPane.OutputString
("WindowEvents::WindowClosing\n");
            outputWindowPane.OutputString("\tWindow: " + 
closingWindow.Caption + "\n");
        }

        public void WindowActivated(EnvDTE.Window gotFocus,   
        EnvDTE.Window lostFocus)
        {
            outputWindowPane.OutputString
("WindowEvents::WindowActivated\n");
            outputWindowPane.OutputString("\tWindow receiving focus: " 
+ gotFocus.Caption + "\n");
            outputWindowPane.OutputString("\tWindow that lost focus: " 
+ lostFocus.Caption + "\n");
        }

        public void WindowCreated(EnvDTE.Window window)
        {
            outputWindowPane.OutputString
            ("WindowEvents::WindowCreated\n");
            outputWindowPane.OutputString("\tWindow: " + window.Caption 
+ "\n");
        }

        public void WindowMoved(EnvDTE.Window window, int top, int 
        left, int width, int height)
        {
            outputWindowPane.OutputString
            ("WindowEvents::WindowMoved\n");
            outputWindowPane.OutputString("\tWindow: " + window.Caption 
+ "\n");
            outputWindowPane.OutputString("\tLocation: (" + 
top.ToString() + " , " + left.ToString() + " , " + 
width.ToString() + " , " + height.ToString() + ")\n");
        }

        public void OnAddInsUpdate(ref Array custom)
        {
        }

        public void OnStartupComplete(ref Array custom)
        {
        }

        public void OnBeginShutdown(ref Array custom)
        {
        }

        private DTE2 _applicationObject;
        private AddIn _addInInstance;
        private EnvDTE.WindowEvents winEvents;
        private OutputWindowPane outputWindowPane;
    }
}

Compiling the Code

To compile this code, create a new Visual C# add-in project and replace the code of the Connect class with the code in the example.

See Also

Tasks

How to: Handle Automation Events (Visual Basic)

Reference

+= Operator (C# Reference)

Other Resources

Responding to Automation Events

Responding to Events (Visual Basic and Visual C# Projects)