GetFormRegionIcon and GetFormRegionManifest

The Outlook FormRegionStartup interface was enhanced right before Office 2007 was released. Two new methods were added. The existing documentation doesn’t explain these methods in any detail – not even in the developer help within Office. The existing VSTO documentation does include mention of the two new methods, but doesn’t explain how to use them. It does, however, explain how to create a VSTO add-in for Outlook 2007 implementing the FormRegionStartup interface:

https://msdn2.microsoft.com/en-us/library/aa942741(VS.80).aspx

I’ll assume you can refer to that article to get the basic form region add-in built, so in this post I’ll only talk about the changes you need to make to implement the two new methods. The two new methods are:

  • GetFormRegionManifest – returns the manifest XML as a string.
  • GetFormRegionIcon – returns an icon for this custom form region’s ribbon control, either as a byte-array or an IPictureDisp object.

If you want to provide the manifest and icon in this way, you also have to register the form region differently. For example, the old registry entry specified the path to the manifest:

[HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\FormRegions\IPM.Task]

"TaskFormRegion"="%USERPROFILE%\\My Documents\\Visual Studio 2005\\Projects\\FormRegionWalkthrough\\FormRegionAddIn\\FormRegionAddIn\\Manifest.xml"

The new registry entry simply specifies an “=” followed by the ProgId of your add-in::

[HKEY_CURRENT_USER\Software\Microsoft\Office\Outlook\FormRegions\IPM.Task]

"TaskFormRegion"="=FormRegionAddIn"

Also, the form region manifest itself needs to be changed. Many of the entries are no longer required. If you provide your manifest via the GetFormRegionManifest method, then the <name>, <layoutFile> and <addin> elements are ignored. There’s also a new element <icons>, where you can specify the word “addin” for each child <icon> element if you want Outlook to call GetFormRegionIcon for that icon.

Here’s what the updated version should look like. I’ve left the unused entries in as comments so you can see the differences. I’ve also put all the possible icon entries in as comments. This is a ‘separate’ form region, and for this form region style only the page icon is used, so that’s the only icon element that is not a comment:

<?xml version="1.0" encoding="utf-8"?>

<FormRegion xmlns="https://schemas.microsoft.com/office/outlook/12/formregion.xsd">

  <!--<name>TaskFormRegion</name>

  <title>Contoso</title>-->

  <formRegionType>separate</formRegionType>

  <formRegionName>Contoso</formRegionName>

  <showInspectorCompose>true</showInspectorCompose>

  <showInspectorRead>true</showInspectorRead>

  <showReadingPane>false</showReadingPane>

  <!--<hidden>true</hidden>

  <addin>FormRegionAddIn</addin>

  <version>1.0</version>-->

  <icons>

    <!--<default>addin</default>

    <unread>addin</unread>

    <read>addin</read>

    <replied>addin</replied>

    <forwarded>addin</forwarded>

    <unsent>addin</unsent>

    <submitted>addin</submitted>

    <signed>addin</signed>

    <encrypted>addin</encrypted>

    <window>addin</window>

    <recurring>addin</recurring>-->

    <page>addin</page>

  </icons>

</FormRegion>

Next, add this manifest XML as a resource to the project. If you’re basing this on the documented walkthrough, you’ll have two resources with the same base filename (that is, the TaskFormRegion.xml and TaskFormRegion.ofs, which will be named TaskFormRegion and TaskFormRegion1). To avoid confusion, you could rename the resources, to for example TaskFormRegionXML and TaskFormRegionOFS. If you do this, you’ll need to change the GetFormRegionStorage method accordingly:

public object GetFormRegionStorage(string FormRegionName, object Item, int LCID,

    Outlook.OlFormRegionMode FormRegionMode, Outlook.OlFormRegionSize FormRegionSize)

{

    Application.DoEvents();

    switch (FormRegionName)

    {

        case "TaskFormRegion":

            return Properties.Resources.TaskFormRegionOFS;

        default:

            return null;

    }

}

Then, you can implement the GetFormRegionManifest method very simply, like so:

public object GetFormRegionManifest(string FormRegionName, int LCID)

{

    return Properties.Resources.TaskFormRegionXML;

}

Now for the icon. Choose any suitable icon file, and add it as a resource to the project. Also add a helper class to convert the Icon type to the IPictureDisp type:

internal class PictureConverter : System.Windows.Forms.AxHost

{

    private PictureConverter() : base("") { }

    static public stdole.IPictureDisp IconToPictureDisp(System.Drawing.Icon icon)

    {

        return (stdole.IPictureDisp)GetIPictureDispFromPicture(icon.ToBitmap());

    }

}

Then, you can implement the second new FormRegionStartup method, GetFormRegionIcon:

public object GetFormRegionIcon(string FormRegionName, int LCID, Outlook.OlFormRegionIcon Icon)

{

    object icon = null;

    switch (Icon)

    {

        case Outlook.OlFormRegionIcon.olFormRegionIconPage:

            icon = PictureConverter.IconToPictureDisp(Properties.Resources.page);

        break;

    }

    return icon;

}

That’s it, build and test..