HOWTO: Creating custom pictures for Visual Studio .NET add-ins commands, buttons and toolwindows.

Article translations Article translations
Article ID: 555417 - View products that this article applies to.
Author: Carlos Quintero MVP
Expand all | Collapse all

SUMMARY

This article describes how to create custom pictures for .NET add-ins commands, buttons and toolwindows.

SYMPTOMS

This article describes how to create custom pictures for .NET add-ins commands, buttons and toolwindows.

MORE INFORMATION

There are at least three cases in which you will need to create custom, transparent, pictures for your Visual Studio .NET add-in features. This article explains how to do it in each case:
 
A) Custom pictures for add-ins commands
 
When you call the Commands.AddNamedCommand function to create a command, if you pass the False value in the MSOButton parameter (the 5th), then the command will use a custom picture instead of a picture taken from Microsoft Office. The custom picture is specified through the Bitmap parameter (the 6th) which is an integer, and it indicates the resource ID of the bitmap in a satellite DLL that you must create using Visual C++ (VS 2005 supports managed satellite DLLs, but for Visual Studio .NET 2002/2003 you need to use a Win32 C++ project).
 
The steps are the following:
 
- Add a new project to your solution selecting Visual C++ projects, Win32 project and give it a name, such as <MyAddinName>UI.vcproj (UI stands for user interface).
 
- In the wizard that is shown, select Application Settings, select the DLL radiobutton and click the Finish button. The new project is added to the solution.
 
- Right-click the Resources folder node of this new project and select "Add", "Add Resource…". A file named "<MyAddinName>.rc" file is added to the node and an "Add Resource" dialog appears. Select Bitmap from the list and click the "New" button.
 
- Change the dimensions of the bitmap using the Properties window and setting the Height and Width properties to 16.
 
- Change the ID of the bitmap in the Properties window to the value 1 (for example).
 
- Draw or paste an image for your bitmap.
 
- To use transparency you need to use a special color: select the lime green color in the Colors toolwindow, click the "Image", "Adjust Colors…" menu and in the shown dialog enter the values Red=0, Green=254 (not 255!) and Blue=0. You can use now this color to fill the transparent areas.
 
- Once you have finished your bitmap, you need to change the call to the Commands.AddNamedCommand function: pass the False value in the MSOButton parameter (the 5th) and pass the ID of the bitmap (1, in our example) in the Bitmap parameter (the 6th).
 
- Build the Dll and put it in a subfolder of your add-in folder naming the subfolder with the locale of Visual Studio. For the English version, the locale is 1033.
 
- At this point you only need to inform Visual Studio .NET that your add-in uses a satellite DLL. In the registry entry HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.0\Addins\<MyAddinName>.Connect (use 7.0 for VS.NET 2002 and 7.1 for VS.NET 2003) add two alphanumeric values:
 
"SatelliteDLLName": the name of your satellite dll, such as <MyAddinName>UI.dll
"SatelliteDLLPath": the path your satellite dll, excluding the locale (so it is really the path to the add-in, not to the satellite Dll).
 
After all this, your commands will be created with a custom, transparent picture. If you need to reset your commands so they are created again, you can open a Visual Studio .NET Command Prompt and type devenv.exe /setup.
 
B) Custom pictures for add-ins buttons without a command
 
In the previous case we have seen how to create a command with a custom picture. CommandBarButtons created from this command (using the Command.AddControl method) will show that custom picture too, but sometimes you may need to create buttons that don´t have a command behind, using the CommandBar.Controls.Add method instead. In this case, to set a custom, transparent, picture for the CommandBarControl created, you need to cast it to CommandBarButton and then set its Picture and Mask properties (in this order):
 
- The Picture property is used to specify an Stdole.IPictureDisp object (an unmanaged COM picture) with your bitmap.
- The Mask property is used to specify an Stdole.IPictureDisp object with a 16-color bitmap (not a 2-color bitmap) which uses the white color to set the transparent areas of the picture, and the black color to set the non-transparent areas.
 
You can get an Stdole.IPictureDisp object from a managed System.Drawing.Image object using this class:
 
Public Class ImageToPictureDispConverter
   Inherits System.Windows.Forms.AxHost
   
   Public Sub New()
      MyBase.New("{63109182-966B-4e3c-A8B2-8BC4A88D221C}")
   End Sub
   
   Public Function GetIPictureDispFromImage(ByVal objImage As System.Drawing.Image) As stdole.IPictureDisp
   
      Dim objPicture As stdole.IPictureDisp
   
      objPicture = CType(MyBase.GetIPictureDispFromPicture(objImage), stdole.IPictureDisp)
 
      Return objPicture
    
   End Function
 
End Class

You use this class as follows:
 
Dim objImageToPictureDispConverter As ImageToPictureDispConverter
Dim objImage As System.Drawing.Image
Dim objIPictureDisp As stdole.IPictureDisp
 
objImage = (get the managed image from somewhere)
objImageToPictureDispConverter = New ImageToPictureDispConverter()
objIPictureDisp=objImageToPictureDispConverter.GetIPictureDispFromImage(objImage)
objImageToPictureDispConverter.Dispose()

Other ways of creating an Stdole.IPictureDisp instead of using a managed image is using a file on disk or a bitmap resource from a satellite DLL. In the former case you would use this function exported by oleaut32.dll:
 
<DllImport("oleaut32.dll", =CharSet.Unicode, =True, ="OleLoadPictureFile")> _
Public Shared Sub OleLoadPictureFile(ByVal varFileName As Object,_
  <MarshalAs(UnmanagedType.IDispatch)> ByRef lpIPictureDisp As Object)
End Sub
 
As you can see, the function receives a file name as first parameter, and it returns an IPictureDisp in the second parameter.
 
In the later case you can get a bitmap handle from a resource DLL handle using this function:
 
<DllImport("user32.dll", ="LoadBitmapA")> _
Public Shared Function LoadBitmap(ByVal hDLLInstance As IntPtr, ByVal iBitmapIndex As Integer) As Integer
End Function

and then you would use the OleCreatePictureIndirect function to get an IPictureDisp object from the bitmap handle:
 
Public Structure PICTDESC
   Friend SizeOfStruct As Integer
   Friend PicType As Integer
   Friend Hbitmap As IntPtr
   Friend Hpal As IntPtr
   Friend Padding As Integer
   Friend Sub New(ByVal hBmp As IntPtr)
      Me.SizeOfStruct = Marshal.SizeOf(Me.GetType)
      Me.PicType = 1
      Me.Hbitmap = hBmp
      Me.Hpal = IntPtr.Zero
      Me.Padding = 0
   End Sub
End Structure
 
<DllImport("olepro32.dll", ="OleCreatePictureIndirect")> _
Public Shared Function OleCreatePictureIndirect(ByRef pPictDesc As PICTDESC, ByRef riid As Guid, _
   ByVal fOwn As Integer, <MarshalAs(UnmanagedType.IDispatch)> ByRef ppvObj As Object) As Integer
End Function

That function is used as follows:
 
Public Function GetIPictureDispFromBitmapHandle(ByVal hBitmapHandle As IntPtr) As stdole.IPictureDisp
 
   Dim objPicture As Object
   Dim objGuid As New Guid("00020400-0000-0000-C000-000000000046")
   Dim iResult As Integer
   Dim tPICTDESC As New PICTDESC(hBitmapHandle)
 
   iResult = OleCreatePictureIndirect(tPICTDESC, objGuid, 1, objPicture)
 
   Return CType(objPicture, stdole.IPictureDisp)
 
End Function

 
C) Custom pictures for toolwindows
 
When you create a toolwindow using the Windows.CreateToolWindow method and the window is linked together with other toolwindows, its tab shows a picture. If you have not specified a picture, by default a Visual Studio picture logo is shown. You can specify a custom picture using the Window.SetTabPicture method, which receives an StdOle.IPictureDisp object, which you can get with any method explained above. You must call the SetTabPicture method before making the window visible calling Window.Visible = True. The transparent areas of the picture must use the RGB value 0, 254, 0, as it was explained before.

Properties

Article ID: 555417 - Last Review: August 17, 2005 - Revision: 1.0
APPLIES TO
  • Microsoft Visual Studio .NET 2002 Enterprise Developer
  • Microsoft Visual Studio .NET 2002 Professional Edition
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Enterprise Developer
  • Microsoft Visual Studio .NET 2003 Professional Edition
Keywords: 
kbpubmvp kbpubtypecca kbhowto KB555417
COMMUNITY SOLUTIONS CONTENT DISCLAIMER
MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com