2007
05.05

This article is going to carry on some ideas from earlier posts. Those posts dealt with how to customize an Outlook Contact by adding a custom tab. If you missed the earlier information, you can catch up on it here: http://www.midniteblog.com/?p=6.

Now we are going to try to something with the blank tab we added. Let’s add an Active-X control to the tab. Assume you already have an Active-X control with a Progid of “MYCONTROL.MyControlCtrl.1” and it does some super special thing that no one else in the world can do so you want to add it to your custom Outlook tab.

Easy enough. We are working with C# here, so add the following 2 reference lines at the top of your connect.cs file:

using Outlook = Microsoft.Office.Interop.Outlook;
using System.Reflection;

Add project references to Microsoft.Office.Interop.Outlook.dll and Microsoft.Vbe.Interop.Forms.dll.
Add the following 2 members to your Connect class:
Outlook.Application m_outlook;
Outlook.Inspectors m_inspectors;

Add the following to your OnConnection method:

m_outlook = application as Outlook.Application;
m_inspectors = m_outlook.Inspectors;
m_inspectors.NewInspector +=
new Microsoft.Office.Interop.Outlook.
InspectorsEvents_NewInspectorEventHandler
(Inspectors_NewInspector);

Here we are telling Outlook to notify us when a “NewInspector” event fires. This happens basically every time someone double-clicks to open up an Outlook Contact.

Add the following class method to Connect class:

public void Inspectors_NewInspector(Outlook.Inspector inspector)
{
  if (inspector != null && inspector.CurrentItem is Outlook.ContactItem)
  {
    Microsoft.Vbe.Interop.Forms.UserForm userform;
    object obTemp = ((Outlook.Pages) (inspector.ModifiedFormPages)).Add("My Page");
    userform = (Microsoft.Vbe.Interop.Forms.UserForm) obTemp;
    Microsoft.Vbe.Interop.Forms.Control mc;
    try
    {
      mc = userform.Controls._GetItemByName("myControl");
    }
    catch (Exception)
    {
      mc = null;
    }
    if (null == mc)
    {
      mc = (Microsoft.Vbe.Interop.Forms.Control) userform.Controls.Add
      ("MYCONTROL.MyControlCtrl.1", "myControl", true);
    }
    inspector.ShowFormPage("My Page");
  }
}

So in this method we are adding our custom “My Page” to the Outlook inspector window (as we did before) and now we are asking the “Controls” collection of the userform to add an Active-X control by Progid (“MYCONTROL.MyControlCtrl.1”). This will CoCreate the AX control and parent it to the Outlook custom tab ! There’s your custom control hosted in Outlook – cool.
Note that if you do not do the check for finding any existing control (e.g. if this is not a new contact) with _GetItemByName you will get an additional control created for every time you open the contact.
This seems very counterintuitive, but apparently Outlook persists the state of each contact page, and when you “Add” a page on a subsequent open of the contact, it loads any controls that were there before.

Now let’s suppose you want to tell the AX control to do something. Let’s further suppose that the control exposes a method called “ShowMyData” that takes a BSTR in param. Continuing on with the example, add the following just before the ShowFormPage call we added above:

Type ty = mc.GetType();
object[] paramList = new object[1];
paramList[0] = "My Data";
ty.InvokeMember("ShowMyData",
BindingFlags.Default | BindingFlags.InvokeMethod,
null, mc, paramList);

Here we are using reflection to bind to the control at run-time and then invoking on it. The exposed method is called “ShowMyData” and the parameter string is hardcoded here to “My Data.” When the AX control gets the string, it can do with it what it likes. Amazing that with the big push to .NET, we still have to use interop to customize Office, but if you want to host a legacy Active-X control on an Outlook custom tab, that’s the way to do it.
midniteblogger