Application-Level Events
This section covers events that occur at the Application level. This includes either events raised on the Application object or events that are raised on the main Outlook windows. The two primary windows displayed by Outlook are represented in the Outlook object model by the Explorer object and the Inspector object. An Explorer object represents the main Outlook window in which the contents of folders display. An Inspector object represents the Outlook window that appears when you double-click an Outlook itemfor example, when you double-click a mail item in your inbox. Figure 10-1 shows representative Explorer and Inspector windows.
Figure 10-1. An Explorer window and an Inspector window.
It is possible to have zero or more Explorer and zero or more Inspector windows open at any given time. For example, if you right-click a document in the My Documents folder and choose Mail Recipient from the Send To menu, Outlook launches with only an Inspector window open. If you launch Outlook by picking it from the Start menu, it typically starts up with just the main Outlook window open, which is an Explorer window. If you right-click a folder within Outlook and choose Open in New Window, doing so creates an additional Explorer window to display that folder. Outlook can also run in a mode with neither an Explorer nor an Inspector window runningfor example, when it is started by the ActiveSync application shipped by Microsoft for syncing phones and PDAs to Outlook.
Startup and Quit Events
Outlook raises several events during startup and shutdown:
- Application.Startup is raised when Outlook has completely started up. This event is raised after add-ins have been loaded so that an add-in can handle this eventthat is, it is not raised before add-ins are loaded (as are some events in Word and Excel).
- Application.MAPILogonComplete is raised after Outlook has logged on to the mail services it is configured to connect to.
- Application.Quit is raised when Outlook is about to exit. This event is raised before add-ins have been unloaded so that an add-in can handle this event. A VSTO Outlook add-in is unloaded before the Quit event is raised and should use the Shutdown event instead.
Quit is the name of both a method and an event on the Application object. Because of this collision, you will not see the Quit event in Visual Studio's pop-up menu of properties, events, and methods associated with the Application object. Furthermore, a warning displays at compile time when you try to handle this event. To get Visual Studio's pop-up menus to work and the warning to go away, you can cast the Application object to the ApplicationEvents_11_Event interface, as shown in Listing 10-1. |
The order in which IDTExtensibility2 methods associated with a COM add-in (described in Chapter 23, "Developing COM Add-Ins for Word and Excel") and Outlook's Startup, Quit, and MAPILogonComplete events occur is shown here:
- User launches Outlook.
OnConnection method of IDTExtensibility2 is called.
OnStartupComplete method of IDTExtensibility2 is called.
Startup event is raised.
MAPILogonComplete event is raised.
- User quits Outlook.
Quit event is raised.
OnBeginShutdown of IDTExtensibility2 is called.
OnDisconnection of IDTExtensibility2 is called.
Listing 10-1 shows an add-in that handles these three events. It also displays message boxes when the methods of IDTExtensibility2 are called.
For simplicity, the COM add-in listings in this chapter do not include the fix described in Chapter 24, "Creating Outlook Add-Ins with VSTO," that is required to get Outlook to always shut down reliably when loading a COM add-in. Even though this book includes some COM add-in samples, our recommendation is that you create VSTO Outlook add-ins rather than COM add-ins to avoid the issues described in Chapter 24. |
Listing 10-1. A COM Add-In That Handles the Application Object's Quit, Startup, and MAPILogonComplete Events
namespace MyAddin2 { using System; using Extensibility; using Outlook = Microsoft.Office.Interop.Outlook; using System.Windows.Forms; using System.Runtime.InteropServices; [GuidAttribute("FEC2B9E7-9366-4AD2-AD05-4CF0167AC9C6"), ProgId("MyAddin2.Connect")] public class Connect : Object, Extensibility.IDTExtensibility2 { Outlook.Application applicationObject; public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) { applicationObject = (Outlook.Application)application; applicationObject.Startup += new Outlook.ApplicationEvents_11_StartupEventHandler( ApplicationObject_Startup); ((Outlook.ApplicationEvents_11_Event)applicationObject). Quit += new Outlook.ApplicationEvents_11_QuitEventHandler( ApplicationObject_Quit); applicationObject.MAPILogonComplete += new Outlook.ApplicationEvents_11_MAPILogonCompleteEventHandler( ApplicationObject_MAPILogonComplete); MessageBox.Show("OnConnection"); } public void OnDisconnection( Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom) { MessageBox.Show("OnDisconnection"); } public void OnAddInsUpdate(ref System.Array custom) { } public void OnStartupComplete(ref System.Array custom) { MessageBox.Show("OnStartupComplete"); } public void OnBeginShutdown(ref System.Array custom) { MessageBox.Show("OnBeginShutdown"); } void ApplicationObject_Startup() { MessageBox.Show("Startup Event"); } void ApplicationObject_MAPILogonComplete() { MessageBox.Show("MAPILogonComplete Event"); } void ApplicationObject_Quit() { MessageBox.Show("Quit Event"); } } }
The order in which a VSTO Outlook add-in's Startup and Shutdown event handlers and Outlook's Startup, Quit, and MAPILogonComplete events occur is shown here:
- User launches Outlook.
VSTO Startup event is raised.
Outlook Application object's Startup event is raised.
Outlook Application object's MAPILogonComplete event is raised.
- User quits Outlook.
Outlook Application object's Quit event is raisedthe VSTO add-in system uses this event to control how the add-in unloads so you may or may not see this event. Your code should handle the Shutdown event instead.
VSTO Shutdown event is raised.
Activation Events
When an Explorer or Inspector window becomes the active window (activates) or loses focus to another window (deactivates), events are raised:
- Explorer.Activate is raised on an Explorer object when the window it corresponds to becomes the active window.
- Inspector.Activate is raised on an Inspector object when the window it corresponds to becomes the active window.
Activate is the name of both a method and an event on the Explorer and Inspector object. Because of this collision, you will not see the Activate event in Visual Studio's pop-up menu of properties, events, and methods associated with the Explorer or Inspector object. Furthermore, a warning displays at compile time when you try to handle this event. To get Visual Studio's pop-up menus to work and the warning to go away, you can cast the Explorer object to the ExplorerEvents_10_Event interface and the Inspector object to the InspectorEvents_10_Event interface, as shown in Listing 10-2.
- Explorer.Deactivate is raised on an Explorer object when the window it corresponds to loses focus to another window.
- Inspector.Deactivate is raised on an Inspector object when the window it corresponds to loses focus to another window.
Listing 10-2 shows a VSTO Outlook add-in that handles Activate and Deactivate events for the Explorer object.
For simplicity, future VSTO Outlook add-in listings in this chapter omit the using… lines of code at the beginning of the VSTO ThisApplication class, the region marked with #region VSTO generated code, and the Shutdown event handler. |
Listing 10-2. A VSTO Add-In That Handles the Explorer Object's Activate and Deactivate Events
using System; using System.Windows.Forms; using Microsoft.VisualStudio.Tools.Applications.Runtime; using Outlook = Microsoft.Office.Interop.Outlook; namespace OutlookAddin1 { public partial class ThisApplication { Outlook.Explorer explorer; private void ThisApplication_Startup(object sender, EventArgs e) { explorer = this.ActiveExplorer(); ((Outlook.ExplorerEvents_10_Event)explorer).Activate += new Outlook.ExplorerEvents_10_ActivateEventHandler( Explorer_Activate); explorer.Deactivate += new Outlook.ExplorerEvents_10_DeactivateEventHandler( Explorer_Deactivate); } void Explorer_Activate() { MessageBox.Show(String.Format( "The explorer with caption {0} was activated.", explorer.Caption)); } void Explorer_Deactivate() { MessageBox.Show(String.Format( "The explorer with caption {0} was deactivated.", explorer.Caption)); } private void ThisApplication_Shutdown(object sender, EventArgs e) { } #region VSTO generated code private void InternalStartup() { this.Startup += new EventHandler(ThisApplication_Startup); this.Shutdown += new EventHandler(ThisApplication_Shutdown); } #endregion } }
New Window Events
When a new Explorer or Inspector window is created, Outlook raises an event:
- Explorers.NewExplorer is raised when a new Explorer window is created. The newly created Explorer is passed as a parameter to this event.
- Inspectors.NewInspector is raised when a new Inspector window is created. The newly created Inspector is passed as a parameter to this event.
Listing 24-1 shows an example of handling these events.
Window Events
When an Explorer or Inspector window is maximized, minimized, moved, or resized, events are raised by Outlook. All of these events can be cancelled to prevent the change to the window from occurring:
- Explorer.BeforeMaximize is raised on an Explorer object when the window it corresponds to is about to be maximized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent Outlook from maximizing the window.
- Inspector.BeforeMaximize is raised on an Inspector object when the window it corresponds to is about to be maximized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent Outlook from maximizing the window.
- Explorer.BeforeMinimize is raised on an Explorer object when the window it corresponds to is about to be minimized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent Outlook from minimizing the window.
- Inspector.BeforeMinimize is raised on an Inspector object when the window it corresponds to is about to be minimized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from minimizing the window.
- Explorer.BeforeMove is raised on an Explorer object when the window it corresponds to is about to be moved. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from moving the window.
- Inspector.BeforeMove is raised on an Inspector object when the window it corresponds to is about to be moved. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from moving the window.
- Explorer.BeforeSize is raised on an Explorer object when the window it corresponds to is about to be resized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent Outlook from resizing the window.
- Inspector.BeforeSize is raised on an Inspector object when the window it corresponds to is about to be resized. Outlook passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from resizing the window.
Close Events
When an Explorer or Inspector window is closed, Outlook raises an event:
- Explorer.Close is raised on an Explorer object when the window it corresponds to has been closed.
- Inspector.Close is raised on an Inspector object when the window it corresponds to has been closed.
Close is the name of both a method and an event on the Explorer and Inspector object. Because of this collision, you will not see the Close event in Visual Studio's pop-up menu of properties, events, and methods associated with the Explorer or Inspector object. Furthermore, a warning displays at compile time when you try to handle this event. To get Visual Studio's pop-up menus to work and the warning to go away, you can cast the Explorer object to the ExplorerEvents_10_Event interface and the Inspector object to the InspectorEvents_10_Event interface, as shown in Listing 9-1. |
Listing 24-1 shows an example of handling these events.
View and Selection Change Events
As you navigate from folder to folder in an Explorer window, Outlook displays a view of the items in the folder you have selected. The user can also change the view for a particular folder by using the View menu and choosing a different view from the Current View menu in the Arrange By menu. Outlook raises events when the view changes or the selection changes:
- Explorer.BeforeViewSwitch is raised on an Explorer object when the user changes the view for a particular folder by using the View menu. This event is not raised when the user simply switches from folder to folder thereby changing the view (but the ViewSwitch event is). Outlook passes a newView parameter that is of type object. This parameter can be cast to a string value representing the name of the view about to be switched to. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to true by your event handler to prevent Outlook from switching to the view the user selected.
- Explorer.ViewSwitch is raised on an Explorer object when the view changes either because the user changed the view using the View menu or because the user selected another folder.
- Inspector.SelectionChange is raised on an Explorer object when the selection in the Explorer window changes.
- Explorer.BeforeFolderSwitch is raised on an Explorer object before the active folder changes. Outlook passes a newFolder parameter of type object. This parameter can be cast to a MAPIFolder that represents what the new active folder will be. Outlook also passes by reference a bool cancel parameter. The cancel parameter can be set to TRue by your event handler to prevent Outlook from switching to the folder the user selected.
- Explorer.FolderSwitch is raised on an Explorer object when the active folder changes.
Listing 10-3 shows a VSTO Outlook add-in that handles these events.
Listing 10-3. A VSTO Add-In That Handles View and Selection Change Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.Explorer explorer; private void ThisApplication_Startup(object sender, EventArgs e) { explorer = this.ActiveExplorer(); explorer.BeforeViewSwitch += new Outlook.ExplorerEvents_10_BeforeViewSwitchEventHandler( Explorer_BeforeViewSwitch); explorer.ViewSwitch += new Outlook.ExplorerEvents_10_ViewSwitchEventHandler( Explorer_ViewSwitch); explorer.SelectionChange +=new Outlook.ExplorerEvents_10_SelectionChangeEventHandler( Explorer_SelectionChange); explorer.BeforeFolderSwitch += new Outlook.ExplorerEvents_10_BeforeFolderSwitchEventHandler( Explorer_BeforeFolderSwitch); explorer.FolderSwitch += new Outlook.ExplorerEvents_10_FolderSwitchEventHandler( Explorer_FolderSwitch); } void Explorer_BeforeViewSwitch(object newView, ref bool cancel) { MessageBox.Show(String.Format( "About to switch to {0}.", newView)); } void Explorer_ViewSwitch() { Outlook.View view = explorer.CurrentView as Outlook.View; if (view != null) { MessageBox.Show(String.Format( "The view has been switched. Current view is now {0}.", view.Name)); } } void Explorer_SelectionChange() { MessageBox.Show(String.Format( "Selection changed. {0} items selected.", explorer.Selection.Count)); } void Explorer_BeforeFolderSwitch(object newFolder, ref bool cancel) { Outlook.MAPIFolder folder = (Outlook.MAPIFolder)newFolder; MessageBox.Show(String.Format( "The new folder will be {0}.", folder.Name)); } void Explorer_FolderSwitch() { MessageBox.Show("Folder switch"); } } }
Folder Change Events
Given a collection of folders in Outlook, several events are raised when folders in that collection change:
- Folders.FolderAdd is raised on a Folders collection when a new folder is added. Outlook passes a folder parameter of type MAPIFolder representing the newly added folder.
- Folders.FolderRemove is raised on a Folders collection when a folder is deleted.
- Folders.FolderChange is raised on a Folders collection when a folder is changed. Examples of changes include when the folder is renamed or when the number of items in the folder changes. Outlook passes a folder parameter of type MAPIFolder representing the folder that has changed.
Listing 10-4 shows an add-in that handles folder change events for any subfolders under the Inbox folder. To get to a Folders collection, we first get a NameSpace object. The NameSpace object is accessed by calling the Application.Session property. The NameSpace object has a method called GetDefaultFolder that returns a MAPIFolder object to which you can pass a member of the enumeration OlDefaultFolders to get a standard Outlook folder. In Listing 10-4, we pass olFolderInbox to get a MAPIFolder for the Inbox. We then connect our event handlers to the Folders collection associated with the Inbox's MAPIFolder object.
Listing 10-4. A VSTO Add-In That Handles Folder Change Events
namespace OutlookAddin1 { public partial class ThisApplication { Outlook.Folders folders; private void ThisApplication_Startup(object sender, EventArgs e) { Outlook.NameSpace ns = this.Session; Outlook.MAPIFolder folder = ns.GetDefaultFolder( Outlook.OlDefaultFolders.olFolderInbox); folders = folder.Folders; folders.FolderAdd += new Outlook.FoldersEvents_FolderAddEventHandler( Folders_FolderAdd); folders.FolderChange += new Outlook.FoldersEvents_FolderChangeEventHandler( Folders_FolderChange); folders.FolderRemove += new Outlook.FoldersEvents_FolderRemoveEventHandler( Folders_FolderRemove); } void Folders_FolderAdd(Outlook.MAPIFolder folder) { MessageBox.Show(String.Format( "Added {0} folder.", folder.Name)); } void Folders_FolderChange(Outlook.MAPIFolder folder) { MessageBox.Show(String.Format( "Changed {0} folder. ", folder.Name)); } void Folders_FolderRemove() { MessageBox.Show("Removed a folder."); } } }