Wednesday 3 December 2008

Dealing with email events with Outlook and Add-in s

Dealing with email events with Outlook and Add-in s

I have explained already how to place a button in the standard bar. The problem we have now, it is how to capture an evenet when we decide to open, close, send, reply... an email. Microsoft provides the InspectorsClass [Microsoft.Office.Interop.Outlook.InspectorsClass] , this class allows you to capture the "NewInspector" event [InspectorsEvents_NewInspectorEventHandler] . This event is one that is fired when we decide to mess around with one email item.

Once we enter in the event it is time to deal with the item, so basically we have to decide what to do.

I am going to paste 3 classes:
    • Connect.cs
    • OleCreateConverter.cs
    • OutlookMailItemEventArgs.cs
OutlookMailItemEventArgs contains the events that deal with Item itself. What I dod it is create a button main standard toolbar and when we open a new email I attach a button called "Send...". When you click it removes the subject of the Item.

Connect.cs

namespace WSSSaveAsOutlookAddIn
{
using System;
using Extensibility;
using System.Runtime.InteropServices;
using Microsoft.Office.Core;
using System.Reflection;
using System.Windows.Forms;
using System.Collections;



[GuidAttribute("0632A014-721A-4545-8B36-12D7CC4373B4"), ProgId("WSSSaveAsOutlookAddIn.Connect")]
public class Connect : Object, Extensibility.IDTExtensibility2
{
//private WSSSaveAsWord.SaveAs _fSaveAsForm;

private CommandBarButton _cbbToolBarButton;

//## Current email.
private Microsoft.Office.Interop.Outlook.MailItem _msgMailItem;

//## OutLook Explorer.
private Microsoft.Office.Interop.Outlook.Explorer _outlookExplorer;

//## Application
private Microsoft.Office.Interop.Outlook._Application _outlookApplication;

//## Email Item.
private Microsoft.Office.Interop.Outlook.MailItem _miMailItem;

//## InspectorsClass.
private Microsoft.Office.Interop.Outlook.InspectorsClass _insInspectors;

//## This Hashtable holds a reference to the active Inspectors
private Hashtable _ActiveItems = null;

public Connect()
{
//_fSaveAsForm.OfficeProduct = WSSSaveAsWord.SaveAs.OfficeProductType.Outlook;
//_fSaveAsForm = new WSSSaveAsWord.SaveAs();
//_fSaveAsForm.OfficeProduct = WSSSaveAsWord.SaveAs.OfficeProductType.Outlook;
}

public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
applicationObject = application;
addInInstance = addInInst;

_outlookApplication = application as Microsoft.Office.Interop.Outlook._Application;

if (connectMode != Extensibility.ext_ConnectMode.ext_cm_Startup)
{
OnStartupComplete(ref custom);
}


}

public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom)
{
if (disconnectMode != Extensibility.ext_DisconnectMode.ext_dm_HostShutdown)
{
OnBeginShutdown(ref custom);
}
applicationObject = null;

}


public void OnAddInsUpdate(ref System.Array custom)
{
}

private void Mail_Item_Closed(object sender, OutlookMailItemEventArgsConnect.OutlookMailItemEventArgs e)
{
// Remove Item from Collection
_ActiveItems.Remove(e.HashCode);
}


private void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
try
{
object Item = Inspector.CurrentItem;

//## Check the ItemsType
if (Item is Microsoft.Office.Interop.Outlook.MailItem)
{
//## Create a new Item wrapper Object
OutlookMailItemEventArgsConnect.OutlookMailItem _oiMail = new OutlookMailItemEventArgsConnect.OutlookMailItem(Item);

//## Register for the Item Close event
_oiMail.Item_Closed += new OutlookMailItemEventArgsConnect.OutlookMailItemEventHandler(Mail_Item_Closed);

//## remember the Item in Collection
_ActiveItems.Add(_oiMail.HashCode, _oiMail);
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}


public void OnStartupComplete(ref System.Array custom)
{

//## The toolbar is declared
CommandBars oCommandBars;

//## The toolbar where our button will be added is declared
CommandBar oStandardBar;

try
{
//## Selection event.
_outlookExplorer = _outlookApplication.ActiveExplorer();
_outlookExplorer.SelectionChange += new Microsoft.Office.Interop.Outlook.ExplorerEvents_10_SelectionChangeEventHandler(outlookExplorer_SelectionChange);

//### FROM HERE WE HANDLE THE ITEM EVENTS ###
//## Open Item
// Create a new Hashtable Object
_ActiveItems = new Hashtable(25);

// Get the Outlook Inspectors Collection
_insInspectors = (Microsoft.Office.Interop.Outlook.InspectorsClass)_outlookApplication.Inspectors;

// Register for the NewInspector event
_insInspectors.NewInspector += new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
//############################################
}
catch(Exception)
{

}

try
{
//## We try to get the bar,
oCommandBars = (CommandBars)applicationObject.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, applicationObject, null);
}
catch (Exception)
{
oCommandBars = (CommandBars)_outlookApplication.ActiveExplorer();

//## Outlook has the CommandBars collection on the Explorer object.
object oActiveExplorer;
oActiveExplorer = applicationObject.GetType().InvokeMember("ActiveExplorer", BindingFlags.GetProperty, null, applicationObject, null);
oCommandBars = (CommandBars)oActiveExplorer.GetType().InvokeMember("CommandBars", BindingFlags.GetProperty, null, oActiveExplorer, null);
}

//## Set up a custom button on the "Standard" commandbar.
try
{
//## Its main toolbar Standard.
oStandardBar = oCommandBars["Standard"];
}
catch (Exception)
{
//## Access names its main toolbar Database.
oStandardBar = oCommandBars["Database"];
}

//## In case the button was not deleted, use the exiting one.
try
{
_cbbToolBarButton = (CommandBarButton)oStandardBar.Controls["Sharepoint Save"];
}
catch (Exception)
{
object omissing = System.Reflection.Missing.Value;

//## The command bar is added into the standar bar.
_cbbToolBarButton = (CommandBarButton)oStandardBar.Controls.Add(1, omissing, omissing, omissing, omissing);

//## The caption is set
_cbbToolBarButton.Caption = "Sharepoint Save";

//## We set the style...We want text and one icon!
_cbbToolBarButton.Style = MsoButtonStyle.msoButtonIconAndCaption;
}

// The following items are optional, but recommended.
//The Tag property lets you quickly find the control
//and helps MSO keep track of it when more than
//one application window is visible. The property is required
//by some Office applications and should be provided.
_cbbToolBarButton.Tag = "Sharepoint Save";

// The OnAction property is optional but recommended.
//It should be set to the ProgID of the add-in, so that if
//the add-in is not loaded when a user presses the button,
//MSO loads the add-in automatically and then raises
//the Click event for the add-in to handle.
_cbbToolBarButton.OnAction = "!";

//## We grab the image from our resources
System.Drawing.Image _imgToolBarImage =Properties.Resources.ToolBarIcon;

//## We make our button visible.
_cbbToolBarButton.Visible = true;

//## We convert from image to IPictureDisp
_cbbToolBarButton.Picture = OleCreateConverter.ImageToPictureDisp(_imgToolBarImage);

//## We set the event
_cbbToolBarButton.Click += new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler(this._cbbToolBarButton_Click);

object oName = applicationObject.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, applicationObject, null);

// Display a simple message to show which application you started in.
// System.Windows.Forms.MessageBox.Show("This Addin is loaded by " + oName.ToString(), "MyCOMAddin");
oStandardBar = null;
oCommandBars = null;

}


public void OnBeginShutdown(ref System.Array custom)
{
//## Unloading our stuff...
object omissing = System.Reflection.Missing.Value;
_cbbToolBarButton.Delete(omissing);
_cbbToolBarButton = null;

}

private void _cbbToolBarButton_Click(CommandBarButton cmdBarbutton, ref bool cancel)
{
if (this._msgMailItem!=null)
{
//_fSaveAsForm.msgMail = this._msgMailItem;

//_fSaveAsForm.Show();
}

//## Button Clicked
System.Windows.Forms.MessageBox.Show("_cbbToolBarButton was Clicked");
}

private void outlookExplorer_SelectionChange()
{
//## Getting a spare temp file name.
string _sTempFileName = System.IO.Path.GetTempFileName();

//## We check if we have select anything.
if (_outlookExplorer.Selection.Count != 0)
{
try
{
//## Getting the selected email.
Microsoft.Office.Interop.Outlook.MailItem mailItem = _outlookExplorer.Selection[1] as Microsoft.Office.Interop.Outlook.MailItem;

//## It is time to save our stuff...
_msgMailItem = mailItem;
}
catch (Exception ex)
{

}
}
}

private object applicationObject;
private object addInInstance;
}
}

OleCreateConverter.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;

namespace WSSSaveAsOutlookAddIn
{
internal class OleCreateConverter
{

[DllImport("oleaut32.dll", EntryPoint = "OleCreatePictureIndirect",CharSet = CharSet.Ansi, ExactSpelling = true, PreserveSig = true)]
private static extern int OleCreatePictureIndirect([In] PictDescBitmap pictdesc, ref Guid iid, bool fOwn,[MarshalAs(UnmanagedType.Interface)] out object ppVoid);

const short _PictureTypeBitmap = 1;

[StructLayout(LayoutKind.Sequential)]
internal class PictDescBitmap
{
internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PictDescBitmap));
internal int pictureType = _PictureTypeBitmap;
internal IntPtr hBitmap = IntPtr.Zero;
internal IntPtr hPalette = IntPtr.Zero;
internal int unused = 0;

internal PictDescBitmap(Bitmap bitmap)
{
this.hBitmap = bitmap.GetHbitmap();
}
}

public static stdole.IPictureDisp ImageToPictureDisp(Image image)
{
if (image == null || !(image is Bitmap))
{
return null;
}

PictDescBitmap pictDescBitmap = new PictDescBitmap((Bitmap)image);
object ppVoid = null;
Guid iPictureDispGuid = typeof(stdole.IPictureDisp).GUID;
OleCreatePictureIndirect(pictDescBitmap, ref iPictureDispGuid, true, out ppVoid);
stdole.IPictureDisp picture = (stdole.IPictureDisp)ppVoid;
return picture;
}


public static Image PictureDispToImage(stdole.IPictureDisp pictureDisp)
{
Image image = null;
if (pictureDisp != null && pictureDisp.Type == _PictureTypeBitmap)
{
IntPtr paletteHandle = new IntPtr(pictureDisp.hPal);
IntPtr bitmapHandle = new IntPtr(pictureDisp.Handle);
image = Image.FromHbitmap(bitmapHandle, paletteHandle);
}
return image;
}

}
}
OutlookMailItemEventArgsConnect.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Office.Core;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace OutlookMailItemEventArgsConnect
{

///
/// EventArgs for my event
///

public class OutlookMailItemEventArgs : EventArgs
{
private readonly int _iHashCode = 0;

public int HashCode
{
get { return _iHashCode; }
}

public OutlookMailItemEventArgs(int _iOutlookMailItemEventArgsHashCode)
{
_iHashCode = _iOutlookMailItemEventArgsHashCode;
}
}

///
/// A delegate for my events
///

public delegate void OutlookMailItemEventHandler(object sender, OutlookMailItemEventArgs e);
///
/// This is a wrapper for a MailItemObject
///

public class OutlookMailItem
{

///
/// The "DATA"
///

private Microsoft.Office.Interop.Outlook.MailItem _oiMailItem;

///
/// the Inspector for the Item
///

private Microsoft.Office.Interop.Outlook.InspectorClass _oinsInspector;

///
/// Event, raised when Item is closed
///

public event OutlookMailItemEventHandler Item_Closed;

private int _iID = 0;

///
/// Controls to be modified...
///

private Microsoft.Office.Core.CommandBar _cbarCommandBar = null;
private Microsoft.Office.Core.CommandBarButton _cbarcmdButton = null;

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

///
/// Returns the Hashcode for the Item
///

public int HashCode
{
get {
return _oiMailItem.GetHashCode();
}
}
///
/// The Constructor for the OutlookMailItem
///

public OutlookMailItem(object Item)
{
//## Remember the Object
_oiMailItem = (Microsoft.Office.Interop.Outlook.MailItem)Item;

_iID = _oiMailItem.GetHashCode();

//## Register for Item Open Event
_oiMailItem.Open += new Microsoft.Office.Interop.Outlook.ItemEvents_10_OpenEventHandler(_oiMailItem_Open);


}
///
/// Eventhadler for a Mail Open event.
/// Remember this Item in ActiveItems
/// Create Button here and register for button click events
///

private void _oiMailItem_Open(ref bool Cancel)
{

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

// get the Inspector here
_oinsInspector = (Microsoft.Office.Interop.Outlook.InspectorClass)_oiMailItem.GetInspector;

// register for the Inspector events
_oinsInspector.InspectorEvents_Event_Close += new Microsoft.Office.Interop.Outlook.InspectorEvents_CloseEventHandler(_oinsInspector_InspectorEvents_Event_Close);

// Create the Menu
CreateMenu();

}

///
/// Eventhandler for the INspector close event
///

private void _oinsInspector_InspectorEvents_Event_Close()
{
try
{
// Raise event, to remove us from active items collection
if (Item_Closed != null)
{
Item_Closed(this, new OutlookMailItemEventArgs(_oiMailItem.GetHashCode()));
}

// Cleanup resources
_oinsInspector.InspectorEvents_Event_Close -= new Microsoft.Office.Interop.Outlook.InspectorEvents_CloseEventHandler(_oinsInspector_InspectorEvents_Event_Close);
Marshal.ReleaseComObject(_oinsInspector);

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

///
/// Adds the Menu for the MailItem
///

private void CreateMenu()
{
try
{
if (_oinsInspector == null) return;

//## Add our Own CommandBar to MailItem
_cbarCommandBar = (Microsoft.Office.Core.CommandBar)_oinsInspector.CommandBars.Add("OutlookMailItemEventArgsConnect", _oMissing, _oMissing, true);


//## Add my button
_cbarcmdButton = (Microsoft.Office.Core.CommandBarButton)_cbarCommandBar.Controls.Add(Microsoft.Office.Core.MsoControlType.msoControlButton, _oMissing, _oMissing, 1, 1);

_cbarcmdButton.Caption = "Send...";
_cbarcmdButton.Tag = _iID.ToString();
_cbarcmdButton.Style = Microsoft.Office.Core.MsoButtonStyle.msoButtonIconAndCaption;
//## Use one off 2 zilliards Office Icons....
_cbarcmdButton.FaceId = 24;

//## Register for Click event
_cbarcmdButton.Click += new _CommandBarButtonEvents_ClickEventHandler(_cbarcmdButton_Click);

//## Make Menu Visible in TOP of Menus
_cbarCommandBar.Visible = true;
_cbarCommandBar.Enabled = true;

//## Setting the position...
_cbarCommandBar.Position = Microsoft.Office.Core.MsoBarPosition.msoBarTop;

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

///
/// Cleans up any resources for shutdown
///

private void CleanUp()
{
try
{

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

///
/// The ResetButton Click eventhandler
///

private void _cbarcmdButton_Click(CommandBarButton Ctrl, ref bool CancelDefault)
{
// Check, if we are in the right MailItem
if (Ctrl.Tag != _iID.ToString()) return;

_oiMailItem.Subject = "";
}
}
}

No comments: