More Outlook Resource Sites

Microsoft Developer Network (MSDN)

FAQs and other general resources

share code 25-Oct-2014 09:31

Looking for help with Outlook programming projects — VSTO, add-ins, VBA, custom Outlook forms, etc.? You′ve come to the right place!

NEW! >> Subscribe to this site via RSS. For more RSS options, see the complete list of feeds on our main news page.

Login Password
Remember me
Register | Send my password
Code level: intermediate    Code area: Outlook and .NET Printer Friendly Version
Title: C# AddIn sample: InspectorWrapper & CommandBar
Description: This sample shows howto wrap an Inspector / Item and creates a CommandBar and MenuItems.

This sample is somewhat outdated. For a newer version, see http://www.outlookcode.com/codedetail.aspx?id=1734.
Date: 05-Mar-2005  07:28
Code level: intermediate
Code area: Outlook and .NET
Posted by: Helmut Obertanner
This message is displayed as VB.NET
 This Sample is created with Visual Studio .Net 2003 Shared AddIn Wizard.
There are 2 Files: Connect.cs and XMailItem.cs.

------------------------------------------------------------------------Connect.cs --------------------------------------------------------------------------
// ##################################################################################
//
// Sample for Wrapping Mail Inspectors and creates a CommandBar, MenuItems
// by Helmut Obertanner ( flash [at] x4u dot de)
//
// ##################################################################################
namespace XConnect
{
	using System;
	using System.Collections ; 
	using System.Diagnostics ;
	using Microsoft.Office.Core;
	using Extensibility;
	using System.Runtime.InteropServices;
	using System.Windows.Forms; 

	// Note: When AddIn was created with Visual Studio Wizard, remove reference to Office.dll and
	// add reference to COM Office11 (Office 2003)
	using Ol = Microsoft.Office.Interop.Outlook ;  
	using MSO = Microsoft.Office.Core;  


	#region Read me for Add-in installation and setup information.
	// When run, the Add-in wizard prepared the registry for the Add-in.
	// At a later time, if the Add-in becomes unavailable for reasons such as:
	//   1) You moved this project to a computer other than which is was originally created on.
	//   2) You chose 'Yes' when presented with a message asking if you wish to remove the Add-in.
	//   3) Registry corruption.
	// you will need to re-register the Add-in by building the MyAddin21Setup project 
	// by right clicking the project in the Solution Explorer, then choosing install.
	#endregion
	
	/// <summary>
	///   The object for implementing an Add-in.
	/// </summary>
	/// <seealso class='IDTExtensibility2' />
	[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.Connect")]
	public class AddIn : Object, Extensibility.IDTExtensibility2
	{

		/// <summary>
		/// The Outlook Application Object
		/// </summary>
		private Ol.Application myApplicationObject;

		/// <summary>
		/// My COM AddIn Instance
		/// </summary>
		private object myAddInInstance;


		/// <summary>
		/// The Inspectors Collection
		/// </summary>
		private Ol.InspectorsClass myInspectors;

		/// <summary>
		/// This Hashtable holds a reference to the active Inspectors
		/// </summary>
		private Hashtable myActiveItems = null;



		/// <summary>
		///		Implements the constructor for the Add-in object.
		///		Place your initialization code within this method.
		/// </summary>
		public AddIn()
		{
		}

		/// <summary>
		///      Implements the OnConnection method of the IDTExtensibility2 interface.
		///      Receives notification that the Add-in is being loaded.
		/// </summary>
		/// <param term='application'>
		///      Root object of the host application.
		/// </param>
		/// <param term='connectMode'>
		///      Describes how the Add-in is being loaded.
		/// </param>
		/// <param term='addInInst'>
		///      Object representing this Add-in.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
		{
			// Get the initial Application object
			myApplicationObject = (Ol.Application) application;
			myAddInInstance = addInInst;

		}

		/// <summary>
		///     Implements the OnDisconnection method of the IDTExtensibility2 interface.
		///     Receives notification that the Add-in is being unloaded.
		/// </summary>
		/// <param term='disconnectMode'>
		///      Describes how the Add-in is being unloaded.
		/// </param>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
		{
			try
			{
				if (myInspectors != null)
				{
					// Unregister for NewInspector Event
					myInspectors.NewInspector -=new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(myInspectors_NewInspector);

					// Release Reference to COM Object
					Marshal.ReleaseComObject (myInspectors);
				}

				myAddInInstance = null;

				// Release Outlook COM Object
				if (myApplicationObject != null) Marshal.ReleaseComObject (myApplicationObject);
				
				// Perform a Garbage Collection
				GC.Collect ();
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}

		/// <summary>
		///      Implements the OnAddInsUpdate method of the IDTExtensibility2 interface.
		///      Receives notification that the collection of Add-ins has changed.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnAddInsUpdate(ref System.Array custom)
		{
		}

		/// <summary>
		///      Implements the OnStartupComplete method of the IDTExtensibility2 interface.
		///      Receives notification that the host application has completed loading.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnStartupComplete(ref System.Array custom)
		{
			try
			{
				// Create a new Hashtable Object
				myActiveItems = new Hashtable (25);

				// Get the Outlook Inspectors Collection
				myInspectors = (Ol.InspectorsClass) myApplicationObject.Inspectors ;

				// Register for the NewInspector event
				myInspectors.NewInspector +=new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(myInspectors_NewInspector);
		
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}

		/// <summary>
		///      Implements the OnBeginShutdown method of the IDTExtensibility2 interface.
		///      Receives notification that the host application is being unloaded.
		/// </summary>
		/// <param term='custom'>
		///      Array of parameters that are host application specific.
		/// </param>
		/// <seealso class='IDTExtensibility2' />
		public void OnBeginShutdown(ref System.Array custom)
		{
		}


		/// <summary>
		/// The eventhandler for the NewInspector event
		/// Called when an Item is opened
		/// </summary>
		/// <param name="Inspector"></param>
		private void myInspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
		{
			try
			{
				object Item = Inspector.CurrentItem;
			
				// Check the ItemsType
				if (Item is Ol.MailItem)
				{
					// Create a new Item wrapper Object
					XMailItem myMail = new XMailItem (Item);

					// Register for the Item Close event
					myMail.Item_Closed +=new XEventHandler(myMail_Item_Closed);
					
					// remember the Item in Collection
					myActiveItems.Add (myMail.HashCode,myMail);

				}
			}						
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}
		}

		/// <summary>
		/// Eventhandler for the Item close event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void myMail_Item_Closed(object sender, XEventArgs e)
		{
			// Remove Item from Collection
			myActiveItems.Remove (e.HashCode );
		}
	}
}
-------------------------------------------- end of Connect.cs ------------------------------------------------------------------------------------------------------------
--------------------------------------------XMailItem.cs--------------------------------------------------------------------------------------------------------------------
// ##################################################################################
//
// Sample for Wrapping Mail Inspectors and creates a CommandBar, MenuItems
// by Helmut Obertanner ( flash [at] x4u dot de)
//
// ##################################################################################
using System;
using System.Diagnostics ;
using Microsoft.Office.Core;
using System.Runtime.InteropServices;
using System.Windows.Forms; 
using Ol = Microsoft.Office.Interop.Outlook ;  
using MSO = Microsoft.Office.Core;  

namespace XConnect
{

	/// <summary>
	/// EventArgs for my event
	/// </summary>
	public class XEventArgs : EventArgs
	{
		private readonly int myHashCode = 0;

		public int HashCode
		{
			get { return myHashCode; }
		}
		
		public XEventArgs(int hashCode)
		{
			myHashCode = hashCode;
		}
	}

	/// <summary>
	/// A delegate for my events
	/// </summary>
	public delegate void XEventHandler (object sender, XEventArgs e);



	/// <summary>
	/// This is a wrapper for a MailItemObject
	/// </summary>
	public class XMailItem
	{

		/// <summary>
		/// The "DATA"
		/// </summary>
		private Ol.MailItem myMailItem;

		/// <summary>
		/// the Inspector for the Item
		/// </summary>
		private Ol.InspectorClass myInspector;

		/// <summary>
		/// Event, raised when Item is closed
		/// </summary>
		public event XEventHandler Item_Closed;

		private int myID = 0;

		private MSO.CommandBar myCommandBar = null;
		private MSO.CommandBarComboBox myComboBox = null;
		private MSO.CommandBarButton myButton = null;

		private object myMissing = System.Reflection.Missing.Value ;  

		/// <summary>
		/// Returns the Hashcode for the Item
		/// </summary>
		public int HashCode
		{
			get { return myMailItem.GetHashCode(); }
		}
		
		/// <summary>
        /// The Constructor for the XMailItem
        /// </summary>
        /// <param name="Item">The Outlook MailItem Object</param>
		public XMailItem(object Item)
		{
			// Remember the Object
			myMailItem = (Ol.MailItem ) Item;

			myID = myMailItem.GetHashCode ();

			// Register for Item Open Event
			myMailItem.Open +=new Microsoft.Office.Interop.Outlook.ItemEvents_10_OpenEventHandler(myMailItem_Open);

			
		}


		/// <summary>
		/// Eventhadler for a Mail Open event.
		/// Remember this Item in ActiveItems
		/// Create Button here and register for button click events
		/// </summary>
		/// <param name="Cancel"></param>
		private void myMailItem_Open(ref bool Cancel)
		{

			// event isn't needed anymore
			myMailItem.Open -=new Microsoft.Office.Interop.Outlook.ItemEvents_10_OpenEventHandler(myMailItem_Open);

			// get the Inspector here
			myInspector = (Ol.InspectorClass ) myMailItem.GetInspector ;
			
			// register for the Inspector events
			myInspector.InspectorEvents_Event_Close +=new Microsoft.Office.Interop.Outlook.InspectorEvents_CloseEventHandler(myInspector_InspectorEvents_Event_Close);
			
			// Create the Menu
			CreateMenu();

		}

		/// <summary>
		/// Eventhandler for the INspector close event
		/// </summary>
		private void myInspector_InspectorEvents_Event_Close()
		{
			try
			{
				// Raise event, to remove us from active items collection
				if (Item_Closed != null)
				{
					Item_Closed(this, new XEventArgs (myMailItem.GetHashCode() ));
				}			
			
				// Cleanup resources
				myInspector.InspectorEvents_Event_Close -=new Microsoft.Office.Interop.Outlook.InspectorEvents_CloseEventHandler(myInspector_InspectorEvents_Event_Close);
				Marshal.ReleaseComObject (myInspector);
		
				Marshal.ReleaseComObject (myMailItem);
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}	
		}

		/// <summary>
		/// Adds the Menu for the MailItem
		/// </summary>
		private void CreateMenu()
		{
			try 
			{
				if (myInspector == null) return ;

				// Add our Own CommandBar to MailItem
				myCommandBar = myInspector.CommandBars.Add ("XConnect", myMissing, myMissing, true);
 
				// Add my ComboBox Control
				myComboBox = (MSO.CommandBarComboBox) myCommandBar.Controls.Add (MSO.MsoControlType.msoControlComboBox , myMissing, myMissing, 1, 1);

				myComboBox.Caption = "Company: ";
				myComboBox.Width = 270;

				myComboBox.Style = MSO.MsoComboStyle.msoComboLabel;  
					
				myComboBox.Tag = myID.ToString();

				// Fill the ComboBox
				FillComboFromDB();

				myComboBox.Change +=new _CommandBarComboBoxEvents_ChangeEventHandler(myComboBox_Change);


				// Add my button
				myButton = (MSO.CommandBarButton) myCommandBar.Controls.Add (MSO.MsoControlType.msoControlButton, myMissing, myMissing, 2, 1);  
				
				myButton.Caption = "XMail";
				myButton.Tag = myID.ToString();
				myButton.Style = MSO.MsoButtonStyle.msoButtonIconAndCaption;
				// Use one off 2 zilliards Office Icons....
				myButton.FaceId = 24;

				// Register for Click event
				myButton.Click +=new _CommandBarButtonEvents_ClickEventHandler(myButton_Click);
			
				// Make Menu Visible in TOP of Menus
				myCommandBar.Visible = true;
				myCommandBar.Enabled = true;
				myCommandBar.Position = MSO.MsoBarPosition.msoBarTop;  
			
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}
		}
		
		/// <summary>
		/// This function Fills the ComboBox from DataBase
		/// </summary>
		private void FillComboFromDB()
		{
			/// Simply a Jumpstart, not a complete solution
			/// Solutions costs money ;-)
			try
			{
				myComboBox.Clear ();
				
				// Should come from DB
				myComboBox.AddItem ("Foo",1);
				myComboBox.AddItem ("Bar",2);
				myComboBox.AddItem ("X4U",3);
				myComboBox.AddItem ("Slipstick",4);
				myComboBox.AddItem ("Turtleflock",5);
				myComboBox.AddItem ("DATALOG",6);

			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}			
		}


		/// <summary>
		/// Cleans up any resources for shutdown
		/// </summary>
		private void CleanUp()
		{
			try
			{
				
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}
		}

		/// <summary>
		/// The ResetButton Click eventhandler
		/// </summary>
		/// <param name="Ctrl"></param>
		/// <param name="CancelDefault"></param>
		private void myButton_Click(CommandBarButton Ctrl, ref bool CancelDefault)
		{
			// Check, if we are in the right MailItem
			if (Ctrl.Tag != myID.ToString ()) return;

			myMailItem.Subject = "";	
		}

		/// <summary>
		/// Event comes, when Combobox has changed
		/// </summary>
		/// <param name="Ctrl"></param>
		private void myComboBox_Change(CommandBarComboBox Ctrl)
		{
			// Check, if we are in the right MailItem
			if (Ctrl.Tag != myID.ToString ()) return;

			CalculateMailSubject();
		}

		/// <summary>
		/// Creates the new Mail subject
		/// </summary>
		private void CalculateMailSubject()
		{
			try
			{
				string subject = "Learned from Company: " + myComboBox.Text + " @" + DateTime.Now.Hour + ":" + DateTime.Now.Minute ;
				
				// assign new subject to MailItem
				myMailItem.Subject = subject;
			}
			catch (System.Exception ex)
			{
				MessageBox.Show (ex.Message);
			}	
		}

	}
}
-----------------------------------------------------end of XMailItem.cs------------------------------------------------------------------------------

Free to use and modify to your requirements.

Greets, Helmut Obertanner
All 208comments
Page [ 1 2 3 4 5 6 7 8 9 10 Next >>  
  07-Mar-2005  14:08   
Jump start:
Open Visual Studio .Net
Create a new Shared AddIn with Shared AddIn Wizard for C#.
Select only Microsoft Outlook.
Check Load AddIn when HostApplication start + For all Users.
Remove Reference to Office.dll
Add Reference to COM Office11 & Outlook11 dll's.
Add Reference to System.Windows.Forms.dll.
In Project Options, Configuration Settings, Debugging set the Property "Start Application" to [PathToOutlook.exe]\Outlook.exe.
Copy & Paste the Code for Connect.cs & XMailItem.cs above.

!!! Important !!!!
change the folowing line in Connect.cs:
[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.AddIn")]

to:
[GuidAttribute("9B73D13F-0476-4E16-86EF-A3A6B54EFFA8"), ProgId("XConnect.Connect")]

or:

change the RegistryKey Name under:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Outlook\Addins\XConnect.AddIn]

to:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Outlook\Addins\XConnect.Connect]

Greets, Helmut Obertanner


 
  06-Apr-2005  08:09   
Hi Helmut,

I have copied your code as the way you have said.But when i open a new mail item for the first time i see one bar and the second time 2 bars and so on.The bars are not deleted. The eventhandlers on only one bar work fine.
Am i doing something wrong in copying the code?
Thanks and Regards,

 
  06-Apr-2005  08:55   
Hello mohit,

have a look at
// Add our Own CommandBar to MailItem
myCommandBar = myInspector.CommandBars.Add ("XConnect", myMissing, myMissing, true);

the last parameter says that you create the commandbar temporary and should be deleted when you close your mailitem.
Maybe this does not work when you use Word as Emaileditor, then you should delete your commandbar at Inspector close event.

Also you could check when creating the commandbar, if there already exists a commandbar with that name (XConnect).

This where discussed in another thread also:
see comments here:

http://www.outlookcode.com/threads.aspx?forumid=5&messageid=10480

this is the code: have a look on it

            try
            {
                // try to find the CommandBar
                foreach (MSO.CommandBar bar in myInspector.CommandBars)
                {
                    if (bar.Name == "XConnect")
                    {
                        myCommandBar = bar; // foo, eyh ?
                        break;
                    }
                }
            
                // If we found our CommandBar, we can use it
                if (myCommandBar == null)
                {
                    // if not we create one
                    myCommandBar = myInspector.CommandBars.Add ("XConnect", 0 , myMissing, false);
                }

                myCommandBar.Position = MSO.MsoBarPosition.msoBarLeft ;
                myCommandBar.Visible = true;

                // try to find my button CommandBar
                myButton = (MSO.CommandBarButton) myCommandBar.FindControl (MSO.MsoControlType.msoControlButton ,myMissing, "XMail0.1", myMissing, false);
                
                // If we found our Button, we can use it
                if (myButton == null)
                {
                    // if not we create one
                    myButton = (MSO.CommandBarButton) myCommandBar.Controls.Add (MSO.MsoControlType.msoControlButton, myMissing, myMissing,myMissing, false);
                    
                    myButton.Caption = "XMail";
                    myButton.Tag = "XMail0.1";
                }

Greets, Helmut Obertanner
[DATALOG Software AG]
  06-Apr-2005  10:36   
Hi Helmut,
this line i always giving null value
 // try to find my button CommandBar
                myButton = (MSO.CommandBarButton) myCommandBar.FindControl (MSO.MsoControlType.msoControlButton ,myMissing, "XMail0.1", myMissing, false);
Thanks and Regards
  06-Apr-2005  10:44   
this is working fine
myButton = (CommandBarButton)myInspector.CommandBars["XConnect"].Controls["XMail"];
from your other code for the explorer.
thanks a lot Helmut
Regards
  11-May-2005  07:02   
I have a problem with this sample. I don't see any CommandBar when I'm testing add-in in Outlook 2003. I don't understand why...
  11-May-2005  09:29   
Hello Josip, how did you test the AddIn ?
You should see it, when you open a new Mail Form.

Make sure you have the correct Registry Keys so that your AddIn gets loaded when Outlook starts.

Greets, Helmut

 
  14-May-2005  23:18   
Hi Helmut,

I created the sample project using the XP PIA and running OL 2002. You sample code works but I noticed that the when you clicked the Xmail command button the click event of the button will fire several times depending on the number of inspector I previously opened/closed. Is this a bug in OL 2002.

cheers

KRG
  15-May-2005  17:20   
Thnx Helmut. Now it works, but there were no problems with reg keys. I have made again new project and walk through your instructions step-by-step and it works now.

I want to give you a compliments on your articles. They are great for newbies like me. Good work.
  16-May-2005  03:41   
Hello Kenneth,

i also had some problems with XP, and i use timrstamps to resolve some multiple click events with same tag value, even from other inspectors.

Hope this helps,
Greets, Helmut Obertanner

P.S. Josip, thanks for the compliment.
Page [ 1 2 3 4 5 6 7 8 9 10 Next >>