Me: I live in Silicon Valley with my wife, child and cat. I have worked at Microsoft since I graduated from College, both in the Macintosh Business Unit on products such as Outlook Express, Entourage, IE, and Virtual PC and in Windows Live on Hotmail, Calendar and People. I am currently a Principal Lead Program Manager on the Windows Live Social Networking team. I basically manage a team of Program Managers responsible for delivering features to support our web and client applications. I've been blogging since 2001 and like to play around with .NET in my spare time working on projects such as dasBlog (the blog that powers this site) and Send to SmugMug (an application for uploading photos to SmugMug). I blog about a number of technology and productivity related topics.
Powered by: newtelligence dasBlog 2.3.9074.18820
Disclaimer The posts on this weblog are provided "AS IS" with no warranties, and confer no rights. The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
© Copyright 2010, Omar Shahine
E-mail
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
For example, say we want to use the Bold icon. You would create a bitmap like this:
And the mask would look like:
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 Go to localdrive:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Samples\Tutorials\resourcesandlocalization\reseditor Run build.bat To add items to a resource file by using the Resource Editor: 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. 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. Click Add. Type bold_mask as the name of second item to add and then click Add. Next, click File and then click Save As. . . Type IconResource.resX as the name for the project and browse to the parent directory of the sample add-in project. In the Save as type list, select ResX Files (*.resX) and then click Save to save the resource file Close the Resource Editor.
Build the Resource Editor that ships with Visual Studio
To add items to a resource file by using 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 { }
toolbarButton.Style = button.ButtonStyle;
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.