shahine.com/omar/

homepage | Send mail to the author(s) contact

yet another Microsoft blogger

# Friday, April 16, 2004

Creating Managed Outlook Buttons with Icons

I've been working on an Outlook Add-in in C# using the Visual Studio Shared Add-in project. I referenced this article on how to create a custom icon for your button: Custom Button Faces in a Managed Code Add-in for the Microsoft Office System

In addition to this article, most of the information I've seen on the internet and msdn discusses how to set the icon of a button (CustomFace) using the clipboard and calling CommandBarButton.PaseFace(). How ugly. Furthermore, if you do this then you cannot avoid the problems of the mask not getting applied (which looks really ugly, see the screenshot from the MSDN article).

You also  have to deal with issues such as saving and restoring the clipboard contents so that the user does not lose data.

If you are using Outlook 2003 there is a much better way. Here is how you do it:

Create Project

This article assumes you've created a Shared Add-in project already. For a good overview of this see http://blogs.msdn.com/dancre/archive/2004/03/21/93712.aspx

Create Bitmaps of Icons

  1. Using your favorite bitmap editor (I just use mspaint.exe) create a bitmap that is 16x16 px and paste in the icon you wish to use.
  2. Again, using the same bitmap editor create a second bitmap for the mask. This bitmap should contain white for any region that you want to appear transparent, and use RGB (0,255,0) for any area that you want to appear in the CommandBarButton.

    For example, say we want to use the Bold icon. You would create a bitmap like this:

    And the mask would look like:

     

  3. Save both the bitmap as "bold.bmp" and "bold_mask.bmp".

Create Resource Files

Now we want to add these two bitmaps to a resource file that we can embed in our assembly. I used the instructions on Custom Button Faces in a Managed Code Add-in for the Microsoft Office System with some modifications.

Build the Resource Editor that ships with Visual Studio

  1. Go to localdrive:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Samples\Tutorials\resourcesandlocalization\reseditor
  2. Run build.bat

To add items to a resource file by using the Resource Editor:

  1. In the Resource Editor, in the Add section, select System.Drawing.Bitmap as the type of item to add to the resource file from the drop-down list.
  2. In the text box to the right of the Add section, type bold as the name of the first item to add. This enables the Add button.
  3. Click Add.
  4. Type bold_mask as the name of second item to add and then click Add.
  5. Next, click File and then click Save As. . .
  6. Type IconResource.resX as the name for the project and browse to the parent directory of the sample add-in project.
  7. In the Save as type list, select ResX Files (*.resX) and then click Save to save the resource file
  8. Close the Resource Editor.

Add the resource file to your project, and set the Build Action to Embedded Resource.

Create the Buttons and set the Picture and Mask properties

Now we can create the buttons and set the Picture and Mask properties of the CommandBar. However, you cannot just use this code:

object missing = Missing.Value;
 
CommandBarButton outlookButton = (
CommandBarButton)commandBars["Standard"].Controls.Add(
MsoControlType.msoControlButton, missing, missing, missing, true);

toolbarButton.Style = button.ButtonStyle; try { ResourceManager rm = new ResourceManager( this.GetType().Namespace + ".IconResource", this.GetType().Assembly); using (Bitmap bmp = (Bitmap)rm.GetObject("bold")) { if (bmp != null) outlookButton.Picture = bmp; } using (Bitmap bmp = (Bitmap)rm.GetObject("bold_mask")) { if (bmp != null) outlookButton.Mask= bmp; } } catch { }

You see CommandBar.Picture and CommandBar.Mask do not accept bitmaps, but an instance of stdole.IPictureDisp. Great, so how does one create such an object? Not so easy. Thanks to this article though there is a solution. First you need to create this class:

using System;
using System.Drawing;
using System.Windows.Forms;
using stdole;
public class AxHost2 : AxHost
{
    public AxHost2() : base(null)
    {
    }
    public new static IPictureDisp GetIPictureDispFromPicture(Image image)
    {
        return (IPictureDisp)AxHost.GetIPictureDispFromPicture(image);
    }
}

This class inherits from System.Windows.Forms.AxHost which has a protected member GetIPictureDispFromPicture which will return an IPictureDisp  from an Image. So now that we have this class, we can modify the code above to read like so:

using (Bitmap bmp = (Bitmap)rm.GetObject("bold"))
{
    if (bmp != null) outlookButton.Picture = 
     (IPictureDisp)AxHost2.GetIPictureDispFromPicture(bmp);
}
using (Bitmap bmp = (Bitmap)rm.GetObject("bold_mask"))
{
    if (bmp != null) outlookButton.Mask= 
     (IPictureDisp)AxHost2.GetIPictureDispFromPicture(bmp);
}

And that's it. Now you don't have to use the Cliboard and PasteFace to create your icons.

 

Saturday, April 17, 2004 6:12:00 PM (Pacific Daylight Time, UTC-07:00)
Oh, is that *all*?

When I want a button to show a particular pair of images for its active and idle states, I just drop the images into the interface builder "images" tab, and then drag the image to the button.

Frankly, as a Cocoa developer I'm rather astounded by the idea of having to write code to implement a button. Is this considered a tolerable situation among .net developers?

-jcr

John Randolph
Tuesday, April 20, 2004 11:05:24 PM (Pacific Daylight Time, UTC-07:00)
Sadly, only for creating Office 2003 buttons cause Office doesn't have a managed interface yet (well a real one).

Doing this in Windows Forms development (regular .net stuff) there is no code necessary as it can all be done in the designer (you add your image to an imageList and set the picture value to it). It accepts 32 bit PNGs as well.
Wednesday, May 26, 2004 4:00:29 PM (Pacific Daylight Time, UTC-07:00)
I tried this and found a couple problems...

1) The way you created the resource manager caused exceptions when calling GetObject() so I had to do this:

ResourceManager rm = new ResourceManager("Addin.IconResource",
Assembly.GetExecutingAssembly());

2) My button now looks even worse! It placed a white square around a faded icon on the toolbar.
BBK
Wednesday, May 26, 2004 11:16:49 PM (Pacific Daylight Time, UTC-07:00)
Are you using a bitmap for the mask and icon?
Thursday, May 27, 2004 8:16:42 AM (Pacific Daylight Time, UTC-07:00)
Yes. I sent you an e-mail with the source images and resultant image.
BBK
Monday, September 20, 2004 7:27:07 PM (Pacific Daylight Time, UTC-07:00)
I'm wondering how to add an image onto Microsoft.Office.Interop.Outlook.AppointmentItem object.
thanks
Mike
Thursday, February 17, 2005 7:23:52 AM (Pacific Standard Time, UTC-08:00)
I tried it, and here goes my experience:
After using some time to figure out the right using statements to use, I finally got through ... But only an empty square was displayed. :'-(

So I ploughed through John R. Durant's article, and got that to work. (Wondrering why the, else detailed, instruction of using the resource editor do not include adding the actual files!)

Returning back to the code from here. This time I got something more to happen due to that I used a statement from John R. Durant's code to set the Style attribute:

outlookButton.Style = MsoButtonStyle.msoButtonIcon;

But however this something more that happende was now a white area with a "see through hole" in the middle!

So I swapped green and white in the mask ... And there the icon was, nice, with no white around it!
Lars Ole Dahl
Saturday, October 01, 2005 10:40:27 AM (Pacific Daylight Time, UTC-07:00)
Hi! I wanted to thank, because I've succeded with your guide in inserting icons for my plugin (as you can see here:
https://sourceforge.net/project/screenshots.php?group_id=144247)

I wanted to ask you about a little problem in developing a plugin for Outlook: before inserting pictures, I used quite long names, and in this way buttons where esalily to find...I'd like also to add a separator between the Help button of Outlook (I didn't create a new toolbar) and my buttons, but I cannot find anything that would help me...Have you got some hint? :)
Comments are closed.