Image Service and Catalog

Visual Studio 2015
 

The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.

The latest version of this topic can be found at Image Service and Catalog.

This cookbook contains guidance and best practices for adopting the Visual Studio Image Service and Image Catalog introduced in Visual Studio 2015.

The image service introduced in Visual Studio 2015 lets developers get the best images for the device and the user’s chosen theme to display the image, including correct theming for the context in which they are displayed. Adopting the image service will help eliminate major pain points related to asset maintenance, HDPI scaling, and theming.

Problems todaySolutions
Background color blendingBuilt-in alpha blending
Theming (some) imagesTheme metadata
High Contrast modeAlternate High Contrast resources
Need multiple resources for different DPI modesSelectable resources with vector-based fallback
Duplicate imagesOne identifier per image concept

Why adopt the image service?

  • Always get the latest “pixel-perfect” image from Visual Studio

  • You can submit and use your own images

  • No need to test your images out when Windows adds new DPI scaling

  • Address old architectural hurdles in your implementations

The Visual Studio shell toolbar before and after using the image service:

Image Service Before and After

The image service can supply a bitmapped image suitable for any supported UI framework:

  • WPF: BitmapSource

  • WinForms: System.Drawing.Bitmap

  • Win32: HBITMAP

Image service flow diagram

Image Service Flow Diagram

Image monikers

An image moniker (or moniker for short) is a GUID/ID pair that uniquely identifies an image asset or image list asset in the image library.

Known monikers

The set of image monikers contained in the Visual Studio Image Catalog and publicly consumable by any Visual Studio component or extension.

Image manifest files

Image manifest (.imagemanifest) files are XML files that define a set of image assets, the monikers that represent those assets, and the real image or images that represent each asset. Image manifests can define standalone images or image lists for legacy UI support. Additionally, there are attributes that can be set either on the asset or on the individual images behind each asset to change when and how those assets are displayed.

Image manifest schema

A complete image manifest looks like this:

<ImageManifest>  
      <!-- zero or one Symbols elements -->  
      <Symbols>  
        <!-- zero or more Import, Guid, ID, or String elements -->  
      </Symbols>  
      <!-- zero or one Images elements -->  
      <Images>  
        <!-- zero or more Image elements -->  
      </Images>  
      <!-- zero or one ImageLists elements -->  
      <ImageLists>  
        <!-- zero or more ImageList elements -->  
      </ImageLists>  
</ImageManifest>  

Symbols

As a readability and maintenance aid, the image manifest can use symbols for attribute values. Symbols are defined like this:

<Symbols>  
      <Import Manifest="manifest" />  
      <Guid Name="ShellCommandGuid" Value="8ee4f65d-bab4-4cde-b8e7-ac412abbda8a" />  
      <ID Name="cmdidSaveAll" Value="1000" />  
      <String Name="AssemblyName" Value="Microsoft.VisualStudio.Shell.UI.Internal" />  
</Symbols>  

SubelementDefinition
ImportImports the symbols of the given manifest file for use in the current manifest
GuidThe symbol represents a GUID and must match GUID formatting
IDThe symbol represents an ID and must be a nonnegative integer
StringThe symbol represents an arbitrary string value

Symbols are case-sensitive, and referenced using $(symbol-name) syntax:

<Image Guid="$(ShellCommandGuid)" ID="$(cmdidSaveAll)" >  
      <Source Uri="/$(AssemblyName);Component/Resources/image.xaml" />  
</Image>  

Some symbols are predefined for all manifests. These can be used in the Uri attribute of the <Source> or <Import> element to reference paths on the local machine.

SymbolDescription
CommonProgramFilesThe value of the %CommonProgramFiles% environment variable
LocalAppDataThe value of the %LocalAppData% environment variable
ManifestFolderThe folder containing the manifest file
MyDocumentsThe full path of the My Documents folder of the current user
ProgramFilesThe value of the %ProgramFiles% environment variable
SystemThe Windows\System32 folder
WinDirThe value of the %WinDir% environment variable

Image

The <Image> element defines an image that can be referenced by a moniker. The GUID and ID taken together form the image moniker. The moniker for the image must be unique across the entire image library. If more than one image has a given moniker, the first one encountered while building the library is the one that is retained.

It must contain at least one source. Size-neutral sources will give the best results across a broad range of sizes, but they are not required. If the service is asked for an image of a size not defined in the <Image> element and there is no size-neutral source, the service will choose the best size-specific source and scale it to the requested size.

<Image Guid="guid" ID="int" AllowColorInversion="true/false">  
      <Source ... />  
      <!-- optional additional Source elements -->  
</Image>  

AttributeDefinition
Guid[Required] The GUID portion of the image moniker
ID[Required] The ID portion of the image moniker
AllowColorInversion[Optional, default true] Indicates whether the image can have its colors programmatically inverted when used on a dark background.

Source

The <Source> element defines a single image source asset (XAML and PNG).

<Source Uri="uri" Background="background">  
      <!-- optional NativeResource element -->  
 </Source>  

AttributeDefinition
Uri[Required] A URI that defines where the image can be loaded from. It can be one of the following:

- A Pack URI using the application:/// authority
- An absolute component resource reference
- A path to a file containing a native resource
Background[Optional] Indicates what on kind of background the source is intended to be used.

It can be one of the following:

 Light: The source can be used on a light background.

 Dark:The source can be used on a dark background.

 HighContrast: The source can be used on any background in High Contrast mode.

 HighContrastLight: The source can be used on a light background in High Contrast mode.

 HighContrastDark: The source can be used on a dark background in High Contrast mode.

If the Background attribute is omitted, the source can be used on any background.

If Background is Light, Dark, HighContrastLight, or HighContrastDark, the source’s colors are never inverted. If Background is omitted or set to HighContrast, the inversion of the source’s colors is controlled by the image’s AllowColorInversion attribute.

A <Source> element can have exactly one of the following optional subelements:

ElementAttributes (all required)Definition
<Size>ValueThe source will be used for images of the given size (in device units). The image will be square.
<SizeRange>MinSize, MaxSizeThe source will be used for images from MinSize to MaxSize (in device units) inclusively. The image will be square.
<Dimensions>Width, HeightThe source will be used for images of the given width and height (in device units).
<DimensionRange>MinWidth, MinHeight,

MaxWidth, MaxHeight
The source will be used for images from the minimum width/height to the maximum width/height (in device units) inclusively.

A <Source> element can also have an optional <NativeResource> subelement, which defines a <Source> that is loaded from a native assembly rather than a managed assembly.

<NativeResource Type="type" ID="int" />  

AttributeDefinition
Type[Required] The type of the native resource, either XAML or PNG
ID[Required] The integer ID portion of the native resource

ImageList

The <ImageList> element defines a collection of images that can be returned in a single strip. The strip is built on demand, as needed.

<ImageList>  
      <ContainedImage Guid="guid" ID="int" External="true/false" />  
      <!-- optional additional ContainedImage elements -->  
 </ImageList>  

AttributeDefinition
Guid[Required] The GUID portion of the image moniker
ID[Required] The ID portion of the image moniker
External[Optional, default false] Indicates whether the image moniker references an image in the current manifest.

The moniker for the contained image does not have to reference an image defined in the current manifest. If the contained image cannot be found in the image library, a blank placeholder image will be used in its place.

First steps (managed)

To use the image service, you need to add references to some or all of the following assemblies to your project:

  • Microsoft.VisualStudio.ImageCatalog.dll

    • Required if you use the built-in image catalog KnownMonikers
  • Microsoft.VisualStudio.Imaging.dll

    • Required if you use CrispImage and ImageThemingUtilities in your WPF UI
  • Microsoft.VisualStudio.Imaging.Interop.14.0.DesignTime.dll

    • Required if you use the ImageMoniker and ImageAttributes types

    • EmbedInteropTypes should be set to true

  • Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime

    • Required if you use the IVsImageService2 type

    • EmbedInteropTypes should be set to true

  • Microsoft.VisualStudio.Utilities.dll

    • Required if you use the BrushToColorConverter for the ImageThemingUtilities.ImageBackgroundColor in your WPF UI
  • Microsoft.VisualStudio.Shell.<VSVersion>.0

    • Required if you use the IVsUIObject type
  • Microsoft.VisualStudio.Shell.Interop.10.0.dll

    • Required if you use the WinForms-related UI helpers

    • EmbedInteropTypes should be set to true

First steps (native)

To use the image service, you need to include some or all of the following headers to your project:

  • KnownImageIds.h

    • Required if you use the built-in image catalog KnownMonikers, but cannot use the ImageMoniker type, such as when returning values from IVsHierarchy GetGuidProperty or GetProperty calls.
  • KnownMonikers.h

    • Required if you use the built-in image catalog KnownMonikers.
  • ImageParameters140.h

    • Required if you use the ImageMoniker and ImageAttributes types.
  • VSShell140.h

    • Required if you use the IVsImageService2 type.
  • ImageThemingUtilities.h

    • Required if you are unable to let the image service handle theming for you.

    • Do not use this header if the image service can handle your image theming.

  • VSUIDPIHelper.h

    • Required if you use the DPI helpers to get the current DPI.
  1. Start by adding the assembly references required in the above first steps section to your project. You don’t need to add all of them, so add just the references you need. (Note: if you are using or have access to Colors instead of Brushes, then you can skip the reference to Utilities, since you won’t need the converter.)

  2. Select the desired image and get its moniker. Use a KnownMoniker, or use your own if you have your own custom images and monikers.

  3. Add CrispImages to your XAML. (See below example.)

  4. Set the ImageThemingUtilities.ImageBackgroundColor property in your UI hierarchy. (This should be set at the location where the background color is known, not necessarily on the CrispImage.) (See below example.)

<Window  
  x:Class="WpfApplication.MainWindow"  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging"  
  xmlns:theming="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Imaging"  
  xmlns:utilities="clr-namespace:Microsoft.Internal.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging"  
  xmlns:catalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog"  
  Title="MainWindow" Height="350" Width="525" UseLayoutRounding="True">  
  <Window.Resources>  
    <utilities:BrushToColorConverter x:Key="BrushToColorConverter"/>  
  </Window.Resources>  
  <StackPanel Background="White" VerticalAlignment="Center"   
    theming:ImageThemingUtilities.ImageBackgroundColor="{Binding Background, RelativeSource={RelativeSource Self}, Converter={StaticResource BrushToColorConverter}}">  
    <imaging:CrispImage Width="16" Height="16" Moniker="{x:Static catalog:KnownMonikers.MoveUp}" />  
  </StackPanel>  
</Window>  

How do I update existing WPF UI?

Updating existing WPF UI is a relatively simple process that consists of three basic steps:

  1. Replace all <Image> elements in your UI with <CrispImage> elements

  2. Change all the Source attributes to Moniker attributes

    • If the image never changes and you are using KnownMonikers, then statically bind that property to the KnownMoniker. (See the above example.)

    • If the image never changes and you are using your own custom image, then statically bind to your own moniker.

    • If the image can change, bind the Moniker attribute to a code property that notifies on property changes.

  3. Somewhere in the UI hierarchy, set ImageThemingUtilities.ImageBackgroundColor to make sure color inversion works correctly.

    • This might require the use of the BrushToColorConverter class. (See the above example.)

Add the following to your code wherever appropriate to replace the raw loading of images. Switch values for returning HBITMAPs versus HICONs versus HIMAGELIST as needed.

Get the image service

CComPtr<IVsImageService2> spImgSvc;  
CGlobalServiceProvider::HrQueryService(SID_SVsImageService, &spImgSvc);  

Requesting the image

ImageAttributes attr = { 0 };  
attr.StructSize      = sizeof(attributes);  
attr.Format          = DF_Win32;  
// IT_Bitmap for HBITMAP, IT_Icon for HICON, IT_ImageList for HIMAGELIST  
attr.ImageType       = IT_Bitmap;  
attr.LogicalWidth    = 16;  
attr.LogicalHeight   = 16;  
attr.Dpi             = VsUI::DpiHelper::GetDeviceDpiX();  
attr.Background      = 0xFFFFFFFF;  
// Desired RGBA color, if you don't use this, don't set IAF_Background below  
attr.Flags           = IAF_RequiredFlags | IAF_Background;  
  
CComPtr<IVsUIObject> spImg;  
// Replace this KnownMoniker with your desired ImageMoniker  
spImgSvc->GetImage(KnownMonikers::Blank, attributes, &spImg);  
  

Add the following to your code wherever appropriate to replace the raw loading of images. Switch values for returning Bitmaps versus Icons as needed.

Helpful using statement

using GelUtilities = Microsoft.Internal.VisualStudio.PlatformUI.Utilities;  

Get the image service

// This or your preferred way of querying for Visual Studio services  
IVsImageService2 imageService = (IVsImageService2)Package.GetGlobalService(typeof(SVsImageService));  
  

Request the image

ImageAttributes attributes = new ImageAttributes  
{  
    StructSize    = Marshal.SizeOf(typeof(ImageAttributes)),  
    // IT_Bitmap for Bitmap, IT_Icon for Icon  
    ImageType     = (uint)_UIImageType.IT_Bitmap,  
    Format        = (uint)_UIDataFormat.DF_WinForms,  
    LogicalWidth  = 16,  
    LogicalHeight = 16,  
    // Desired RGBA color, if you don't use this, don't set IAF_Background below  
    Background    = 0xFFFFFFFF,  
    Flags = (uint)_ImageAttributesFlags.IAF_RequiredFlags | _ImageAttributesFlags.IAF_Background,  
};  
  
// Replace this KnownMoniker with your desired ImageMoniker  
IVsUIObject uIObj = imageService.GetImage(KnownMonikers.Blank, attributes);  
  
Bitmap bitmap = (Bitmap)GelUtilities.GetObjectData(uiObj); // Use this if you need a bitmap  
// Icon icon = (Icon)GelUtilities.GetObjectData(uiObj); // Use this if you need an icon  
  

The VSIX package project template was updated for Visual Studio 2015. To create a new tool window, right-click on the VSIX project and select “Add New Item…” (Ctrl+Shift+A). Under the Extensibility node for the project language, select “Custom Tool Window,” give the tool window a name, and press the “Add” button.

These are the key places to use monikers in a tool window. Follow the instructions for each:

  1. The tool window tab when the tabs get small enough (also used in the Ctrl+Tab window switcher).

    Add this line to the constructor for the class that derives from the ToolWindowPane type:

    // Replace this KnownMoniker with your desired ImageMoniker  
    this.BitmapImageMoniker = KnownMonikers.Blank;  
    
    
  2. The command to open the tool window.

    In the .vsct file for the package, edit the tool window’s command button:

    <Button guid="guidPackageCmdSet" id="CommandId" priority="0x0100" type="Button">  
      <Parent guid="guidSHLMainMenu" id="IDG_VS_WNDO_OTRWNDWS1"/>  
      <!-- Replace this KnownMoniker with your desired ImageMoniker -->  
      <Icon guid="ImageCatalogGuid" id="Blank" />  
      <!-- Add this -->  
      <CommandFlag>IconIsMoniker</CommandFlag>  
      <Strings>  
        <ButtonText>MyToolWindow</ButtonText>  
      </Strings>  
    </Button>  
    
    

How do I use image monikers in an existing tool window?

Updating an existing tool window to use image monikers is similar to the steps for creating a new tool window.

These are the key places to use monikers in a tool window. Follow the instructions for each:

  1. The tool window tab when the tabs get small enough (also used in the Ctrl+Tab window switcher).

    1. Remove these lines (if they exist) in the constructor for the class that derives from the ToolWindowPane type:

      this.BitmapResourceID = <Value>;  
      this.BitmapIndex = <Value>;  
      
      
    2. See step #1 of the “How Do I Use Image Monikers in a New Tool Window?” section above.

  2. The command to open the tool window.

    • See step #2 of the “How Do I Use Image Monikers in a New Tool Window?” section above.

Update your .vsct file as indicated by the commented lines below:

<?xml version="1.0" encoding="utf-8"?>  
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">  
  <!--  Include the definitions for images included in the VS image catalog -->  
  <Include href="KnownImageIds.vsct"/>  
  <Commands package="guidMyPackage">  
    <Buttons>  
      <Button guid="guidMyCommandSet" id="cmdidMyCommand" priority="0x0000" type="Button">  
        <!-- Add an Icon element, changing the attributes to match the image moniker you want to use.  
             In this case, we’re using the Guid for the VS image catalog.  
             Change the id attribute to be the ID of the desired image moniker. -->  
        <Icon guid="ImageCatalogGuid" id="OpenFolder" />  
        <CommandFlag>DynamicVisibility</CommandFlag>  
        <CommandFlag>DefaultInvisible</CommandFlag>  
        <CommandFlag>DefaultDisabled</CommandFlag>  
        <CommandFlag>CommandWellOnly</CommandFlag>  
        <CommandFlag>IconAndText</CommandFlag>  
        <!-- Add the IconIsMoniker CommandFlag -->  
        <CommandFlag>IconIsMoniker</CommandFlag>  
        <Strings>  
          <ButtonText>Quick Fixes...</ButtonText>  
          <CommandName>Show Quick Fixes</CommandName>  
          <CanonicalName>ShowQuickFixes</CanonicalName>  
          <LocCanonicalName>ShowQuickFixes</LocCanonicalName>  
        </Strings>  
      </Button>  
    </Buttons>  
  </Commands>  
  <!-- It is recommended that you remove <Bitmap> elements that are no longer used in the vsct file -->  
  <Symbols>  
    <GuidSymbol name="guidMyPackage"    value="{1491e936-6ffe-474e-8371-30e5920d8fdd}" />  
    <GuidSymbol name="guidMyCommandSet" value="{10347de4-69a9-47f4-a950-d3301f6d2bc7}">  
      <IDSymbol name="cmdidMyCommand" value="0x9437" />  
    </GuidSymbol>  
  </Symbols>  
</CommandTable>  

What if my .vsct file also needs to be read by older versions of Visual Studio?

Older versions of Visual Studio do not recognize the IconIsMoniker command flag. You can use images from the image service on versions of Visual Studio that support it, but continue to use old-style images on older versions of Visual Studio. To do this, you’d leave the .vsct file unchanged (and therefore compatible with older versions of Visual Studio), and create a CSV (comma-separated values) file that maps from GUID/ID pairs defined in a .vsct file’s <Bitmaps> element to image moniker GUID/ID pairs.

The format of the mapping CSV file is:

Icon guid, Icon id, Moniker guid, Moniker id  
b714fcf7-855e-4e4c-802a-1fd87144ccad,1,fda30684-682d-421c-8be4-650a2967058e,100  
b714fcf7-855e-4e4c-802a-1fd87144ccad,2,fda30684-682d-421c-8be4-650a2967058e,200  

The CSV file is deployed with the package and its location is specified by the IconMappingFilename property of the ProvideMenuResource package attribute:

[ProvideMenuResource("MyPackage.ctmenu", 1, IconMappingFilename="IconMappings.csv")]  

The IconMappingFilename is either a relative path implicitly rooted at $PackageFolder$ (as in the example above), or an absolute path explicitly rooted at a directory defined by an environment variable, such as @"%UserProfile%\dir1\dir2\MyMappingFile.csv".

How to supply ImageMonikers for a project

  1. Implement VSHPROPID_SupportsIconMonikers on the project’s IVsHierarchy, and return true.

  2. Implement either VSHPROPID_IconMonikerImageList (if the original project used VSHPROPID_IconImgList) or VSHPROPID_IconMonikerGuid, VSHPROPID_IconMonikerId, VSHPROPID_OpenFolderIconMonikerGuid, VSHPROPID_OpenFolderIconMonikerId (if the original project used VSHPROPID_IconHandle and VSHPROPID_OpenFolderIconHandle).

  3. Change the implementation of the original VSHPROPIDs for icons to create “legacy” versions of the icons if extension points request them. IVsImageService2 provides functionality necessary to get those icons

Extra requirements for VB/C# project flavors

Only implement VSHPROPID_SupportsIconMonikers if you detect that your project is the outermost flavor. Otherwise, the actual outermost flavor may not support image monikers in reality, and your base flavor might effectively “hide” customized images.

How do I use image monikers in CPS?

Setting custom images in CPS (Common Project System) can be done manually or via an item template that comes with the Project System Extensibility SDK.

Using the Project System Extensibility SDK

Follow the instructions at Provide custom icons for the Project Type/Item type to customize your CPS images. More information about CPS can be found at Visual Studio Project System Extensibility Documentation

Manually use ImageMonikers

  1. Implement and export the IProjectTreeModifier interface in your project system.

  2. Determine which KnownMoniker or custom image moniker you want to use.

  3. In the ApplyModifications method, do the following somewhere in the method before returning the new tree, similar to the below example:

    // Replace this KnownMoniker with your desired ImageMoniker  
    tree = tree.SetIcon(KnownMonikers.Blank.ToProjectSystemType());  
    
    
  4. If you are creating a new tree, you can set the custom images by passing in the desired monikers into the NewTree method, similar to the below example:

    // Replace this KnownMoniker with your desired ImageMoniker  
    ProjectImageMoniker icon         = KnownMonikers.FolderClosed.ToProjectSystemType();  
    ProjectImageMoniker expandedIcon = KnownMonikers.FolderOpened.ToProjectSystemType();  
    
    return this.ProjectTreeFactory.Value.NewTree(/*caption*/<value>,  
                                                 /*filePath*/<value>,  
                                                 /*browseObjectProperties*/<value>,  
                                                 icon,  
                                                 expandedIcon);  
    
    

I need to support HIMAGELISTs

If there is an already existing image strip for your code that you want to update to use the image service, but you are constrained by APIs that require passing around image lists, you can still get the benefits of the image service. To create a moniker-based image strip, follow the steps below to create a manifest from existing monikers.

  1. Run the ManifestFromResources tool, passing it the image strip. This will generate a manifest for the strip.

    • Recommended: provide a non default name for the manifest to suit its usage.
  2. If you are using only KnownMonikers, then do the following:

    • Replace the <Images> section of the manifest with <Images/>.

    • Remove all the subimage IDs (anything with <imagestrip name>_##).

    • Recommended: rename the AssetsGuid symbol and image strip symbol to suit its usage.

    • Replace each ContainedImage’s GUID with $(ImageCatalogGuid), replace each ContainedImage’s ID with $(<moniker>), and add the External=”true” attribute to each ContainedImage

      • <moniker> should be replaced with the KnownMoniker that matches the image but with the “KnownMonikers.” removed from the name.
    • Add <Import Manifest="$(ManifestFolder)\<Relative install dir path to>\Microsoft.VisualStudio.ImageCatalog.imagemanifest" /> to the top of the <Symbols> section.

      • The relative path is determined by the deployment location defined in the setup authoring for the manifest.
  3. Run the ManifestToCode tool to generate wrappers so that the existing code has a moniker it can use to query the image service for the image strip.

    • Recommended: provide nondefault names for the wrappers and namespaces to suit their usage.
  4. Do all the adds, setup authoring/deployment, and other code changes to work with the image service and the new files.

Sample manifest including both internal and external images to see what it should look like:

<?xml version="1.0"?>  
<ImageManifest  
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
  xmlns="http://schemas.microsoft.com/VisualStudio/ImageManifestSchema/2014">  
  
  <Symbols>  
    <!-- This needs to be the relative path from your manifest to the ImageCatalog's manifest  
         where $(ManifestFolder) is the deployed location of this manifest. -->  
    <Import Manifest="$(ManifestFolder)\<RelPath>\Microsoft.VisualStudio.ImageCatalog.imagemanifest" />  
  
    <String Name="Resources" Value="/My.Assembly.Name;Component/Resources/ImageStrip" />  
    <Guid Name="ImageGuid" Value="{fb41b7ef-6587-480c-aa27-5b559d42cfc9}" />  
    <Guid Name="ImageStripGuid" Value="{9c84a570-d9a7-4052-a340-188fb276f973}" />  
    <ID Name="MyImage_0" Value="100" />  
    <ID Name="MyImage_1" Value="101" />  
    <ID Name="InternalList" Value="1001" />  
    <ID Name="ExternalList" Value="1002" />  
  </Symbols>  
  
  <Images>  
    <Image Guid="$(ImageGuid)" ID="$(MyImage_0)">  
      <Source Uri="$(Resources)/MyImage_0.png">  
        <Size Value="16" />  
      </Source>  
    </Image>  
    <Image Guid="$(ImageGuid)" ID="$(MyImage_1)">  
      <Source Uri="$(Resources)/MyImage_1.png">  
        <Size Value="16" />  
      </Source>  
    </Image>  
  </Images>  
  
  <ImageLists>  
    <ImageList Guid="$(ImageStripGuid)" ID="$(InternalList)">  
      <ContainedImage Guid="$(ImageGuid)" ID="$(MyImage_0)" />  
      <ContainedImage Guid="$(ImageGuid)" ID="$(MyImage_1)" />  
    </ImageList>  
    <ImageList Guid="$(ImageStripGuid)" ID="$(ExternalList)">  
      <ContainedImage Guid="$(ImageCatalogGuid)" ID="$(StatusError)" External="true" />  
      <ContainedImage Guid="$(ImageCatalogGuid)" ID="$(StatusWarning)" External="true" />  
      <ContainedImage Guid="$(ImageCatalogGuid)" ID="$(StatusInformation)" External="true" />  
    </ImageList>  
  </ImageLists>  
  
</ImageManifest>  

I don’t need to support HIMAGELISTs

  1. Determine the set of KnownMonikers that match the images in your image strip, or create your own monikers for the images in your image strip.

  2. Update whatever mapping you used to get the image at the required index in the image strip to use the monikers instead.

  3. Update your code to use the image service to request monikers via the updated mapping. (This might mean updating to CrispImages for managed code, or requesting HBITMAPs or HICONs from the image service and passing them around for native code.)

You can use the Image Library Viewer tool to test your image manifests to make sure everything is authored correctly. You can find the tool in the Visual Studio 2015 SDK. Documentation for this tool and others can be found here.

Samples

Several of the Visual Studio samples on GitHub have been updated to show how to use the image service as part of various Visual Studio extensibility points.

Check http://github.com/Microsoft/VSSDK-Extensibility-Samples for the latest samples.

Tooling

A set of support tools for the Image Service was created to aid in creating/updating UI that works with the Image Service. For more information about each tool, check the documentation that comes with the tools. The tools are included as part of the Visual Studio 2015 SDK.

ManifestFromResources

The Manifest from Resources Tool takes a list of image resources (PNG or XAML) and generates an image manifest file for using those images with the image service.

ManifestToCode

The Manifest to Code Tool takes an image manifest file and generates a wrapper file for referencing the manifest values in code (C++, C#, or VB) or .vsct files.

ImageLibraryViewer

The Image Library Viewer Tool can load image manifests and allows the user to manipulate them in the same way Visual Studio would to make sure the manifest is authored correctly. The user can alter background, sizes, DPI setting, High Contrast, and other settings. It also displays loading information to find errors in the manifests and displays source information for each image in the manifest.

  • Are there any dependencies that you must include when loading <Reference Include="Microsoft.VisualStudio.*.Interop.14.0.DesignTime" />?

    • Set EmbedInteropTypes="true" on all interop DLLs.
  • How do I deploy an image manifest with my extension?

    • Add the .imagemanifest file to your project.

    • Set “Include in VSIX” to True.

  • I am updating my CPS Project System. What happened to ImageName and StockIconService?

    • o These were removed when CPS was updated to use monikers. You no longer need to call the StockIconService, just pass the desired KnownMoniker to the method or property using the ToProjectSystemType() extension method in the CPS utilities. You can find a mapping from ImageName to KnownMonikers below:

      ImageNameKnownMoniker
      ImageName.OfflineWebAppKnownImageIds.Web
      ImageName.WebReferencesFolderKnownImageIds.Web
      ImageName.OpenReferenceFolderKnownImageIds.FolderOpened
      ImageName.ReferenceFolderKnownImageIds.Reference
      ImageName.ReferenceKnownImageIds.Reference
      ImageName.SdlWebReferenceKnownImageIds.WebReferenceFolder
      ImageName.DiscoWebReferenceKnownImageIds.DynamicDiscoveryDocument
      ImageName.FolderKnownImageIds.FolderClosed
      ImageName.OpenFolderKnownImageIds.FolderOpened
      ImageName.ExcludedFolderKnownImageIds.HiddenFolderClosed
      ImageName.OpenExcludedFolderKnownImageIds.HiddenFolderOpened
      ImageName.ExcludedFileKnownImageIds.HiddenFile
      ImageName.DependentFileKnownImageIds.GenerateFile
      ImageName.MissingFileKnownImageIds.DocumentWarning
      ImageName.WindowsFormKnownImageIds.WindowsForm
      ImageName.WindowsUserControlKnownImageIds.UserControl
      ImageName.WindowsComponentKnownImageIds.ComponentFile
      ImageName.XmlSchemaKnownImageIds.XMLSchema
      ImageName.XmlFileKnownImageIds.XMLFile
      ImageName.WebFormKnownImageIds.Web
      ImageName.WebServiceKnownImageIds.WebService
      ImageName.WebUserControlKnownImageIds.WebUserControl
      ImageName.WebCustomUserControlKnownImageIds.WebCustomControl
      ImageName.AspPageKnownImageIds.ASPFile
      ImageName.GlobalApplicationClassKnownImageIds.SettingsFile
      ImageName.WebConfigKnownImageIds.ConfigurationFile
      ImageName.HtmlPageKnownImageIds.HTMLFile
      ImageName.StyleSheetKnownImageIds.StyleSheet
      ImageName.ScriptFileKnownImageIds.JSScript
      ImageName.TextFileKnownImageIds.Document
      ImageName.SettingsFileKnownImageIds.Settings
      ImageName.ResourcesKnownImageIds.DocumentGroup
      ImageName.BitmapKnownImageIds.Image
      ImageName.IconKnownImageIds.IconFile
      ImageName.ImageKnownImageIds.Image
      ImageName.ImageMapKnownImageIds.ImageMapFile
      ImageName.XWorldKnownImageIds.XWorldFile
      ImageName.AudioKnownImageIds.Sound
      ImageName.VideoKnownImageIds.Media
      ImageName.CabKnownImageIds.CABProject
      ImageName.JarKnownImageIds.JARFile
      ImageName.DataEnvironmentKnownImageIds.DataTable
      ImageName.PreviewFileKnownImageIds.Report
      ImageName.DanglingReferenceKnownImageIds.ReferenceWarning
      ImageName.XsltFileKnownImageIds.XSLTransform
      ImageName.CursorKnownImageIds.CursorFile
      ImageName.AppDesignerFolderKnownImageIds.Property
      ImageName.DataKnownImageIds.Database
      ImageName.ApplicationKnownImageIds.Application
      ImageName.DataSetKnownImageIds.DatabaseGroup
      ImageName.PfxKnownImageIds.Certificate
      ImageName.SnkKnownImageIds.Rule
      ImageName.VisualBasicProjectKnownImageIds.VBProjectNode
      ImageName.CSharpProjectKnownImageIds.CSProjectNode
      ImageName.EmptyKnownImageIds.Blank
      ImageName.MissingFolderKnownImageIds.FolderOffline
      ImageName.SharedImportReferenceKnownImageIds.SharedProject
      ImageName.SharedProjectCsKnownImageIds.CSSharedProject
      ImageName.SharedProjectVcKnownImageIds.CPPSharedProject
      ImageName.SharedProjectJsKnownImageIds.JSSharedProject
      ImageName.CSharpCodeFileKnownImageIds.CSFileNode
      ImageName.VisualBasicCodeFileKnownImageIds.VBFileNode
    • I am updating my completion list provider. What KnownMonikers match to the old StandardGlyphGroup and StandardGlyph values?

      GlyphGroupClassGlyphItemPublicClassPublic
      GlyphGroupClassGlyphItemInternalClassInternal
      GlyphGroupClassGlyphItemFriendClassInternal
      GlyphGroupClassGlyphItemProtectedClassProtected
      GlyphGroupClassGlyphItemPrivateClassPrivate
      GlyphGroupClassGlyphItemShortcutClassShortcut
      GlyphGroupConstantGlyphItemPublicClassPublic
      GlyphGroupConstantGlyphItemInternalClassInternal
      GlyphGroupConstantGlyphItemFriendClassInternal
      GlyphGroupConstantGlyphItemProtectedClassProtected
      GlyphGroupConstantGlyphItemPrivateClassPrivate
      GlyphGroupConstantGlyphItemShortcutClassShortcut
      GlyphGroupDelegateGlyphItemPublicDelegatePublic
      GlyphGroupDelegateGlyphItemInternalDelegateInternal
      GlyphGroupDelegateGlyphItemFriendDelegateInternal
      GlyphGroupDelegateGlyphItemProtectedDelegateProtected
      GlyphGroupDelegateGlyphItemPrivateDelegatePrivate
      GlyphGroupDelegateGlyphItemShortcutDelegateShortcut
      GlyphGroupEnumGlyphItemPublicEnumerationPublic
      GlyphGroupEnumGlyphItemInternalEnumerationInternal
      GlyphGroupEnumGlyphItemFriendEnumerationInternal
      GlyphGroupEnumGlyphItemProtectedEnumerationProtected
      GlyphGroupEnumGlyphItemPrivateEnumerationPrivate
      GlyphGroupEnumGlyphItemShortcutEnumerationShortcut
      GlyphGroupEnumMemberGlyphItemPublicEnumerationMemberPublic
      GlyphGroupEnumMemberGlyphItemInternalEnumerationMemberInternal
      GlyphGroupEnumMemberGlyphItemFriendEnumerationMemberInternal
      GlyphGroupEnumMemberGlyphItemProtectedEnumerationMemberProtected
      GlyphGroupEnumMemberGlyphItemPrivateEnumerationMemberPrivate
      GlyphGroupEnumMemberGlyphItemShortcutEnumerationMemberShortcut
      GlyphGroupEventGlyphItemPublicEventPublic
      GlyphGroupEventGlyphItemInternalEventInternal
      GlyphGroupEventGlyphItemFriendEventInternal
      GlyphGroupEventGlyphItemProtectedEventProtected
      GlyphGroupEventGlyphItemPrivateEventPrivate
      GlyphGroupEventGlyphItemShortcutEventShortcut
      GlyphGroupExceptionGlyphItemPublicExceptionPublic
      GlyphGroupExceptionGlyphItemInternalExceptionInternal
      GlyphGroupExceptionGlyphItemFriendExceptionInternal
      GlyphGroupExceptionGlyphItemProtectedExceptionProtected
      GlyphGroupExceptionGlyphItemPrivateExceptionPrivate
      GlyphGroupExceptionGlyphItemShortcutExceptionShortcut
      GlyphGroupFieldGlyphItemPublicFieldPublic
      GlyphGroupFieldGlyphItemInternalFieldInternal
      GlyphGroupFieldGlyphItemFriendFieldInternal
      GlyphGroupFieldGlyphItemProtectedFieldProtected
      GlyphGroupFieldGlyphItemPrivateFieldPrivate
      GlyphGroupFieldGlyphItemShortcutFieldShortcut
      GlyphGroupInterfaceGlyphItemPublicInterfacePublic
      GlyphGroupInterfaceGlyphItemInternalInterfaceInternal
      GlyphGroupInterfaceGlyphItemFriendInterfaceInternal
      GlyphGroupInterfaceGlyphItemProtectedInterfaceProtected
      GlyphGroupInterfaceGlyphItemPrivateInterfacePrivate
      GlyphGroupInterfaceGlyphItemShortcutInterfaceShortcut
      GlyphGroupMacroGlyphItemPublicMacroPublic
      GlyphGroupMacroGlyphItemInternalMacroInternal
      GlyphGroupMacroGlyphItemFriendMacroInternal
      GlyphGroupMacroGlyphItemProtectedMacroProtected
      GlyphGroupMacroGlyphItemPrivateMacroPrivate
      GlyphGroupMacroGlyphItemShortcutMacroShortcut
      GlyphGroupMapGlyphItemPublicMapPublic
      GlyphGroupMapGlyphItemInternalMapInternal
      GlyphGroupMapGlyphItemFriendMapInternal
      GlyphGroupMapGlyphItemProtectedMapProtected
      GlyphGroupMapGlyphItemPrivateMapPrivate
      GlyphGroupMapGlyphItemShortcutMapShortcut
      GlyphGroupMapItemGlyphItemPublicMapItemPublic
      GlyphGroupMapItemGlyphItemInternalMapItemInternal
      GlyphGroupMapItemGlyphItemFriendMapItemInternal
      GlyphGroupMapItemGlyphItemProtectedMapItemProtected
      GlyphGroupMapItemGlyphItemPrivateMapItemPrivate
      GlyphGroupMapItemGlyphItemShortcutMapItemShortcut
      GlyphGroupMethodGlyphItemPublicMethodPublic
      GlyphGroupMethodGlyphItemInternalMethodInternal
      GlyphGroupMethodGlyphItemFriendMethodInternal
      GlyphGroupMethodGlyphItemProtectedMethodProtected
      GlyphGroupMethodGlyphItemPrivateMethodPrivate
      GlyphGroupMethodGlyphItemShortcutMethodShortcut
      GlyphGroupOverloadGlyphItemPublicMethodPublic
      GlyphGroupOverloadGlyphItemInternalMethodInternal
      GlyphGroupOverloadGlyphItemFriendMethodInternal
      GlyphGroupOverloadGlyphItemProtectedMethodProtected
      GlyphGroupOverloadGlyphItemPrivateMethodPrivate
      GlyphGroupOverloadGlyphItemShortcutMethodShortcut
      GlyphGroupModuleGlyphItemPublicModulePublic
      GlyphGroupModuleGlyphItemInternalModuleInternal
      GlyphGroupModuleGlyphItemFriendModuleInternal
      GlyphGroupModuleGlyphItemProtectedModuleProtected
      GlyphGroupModuleGlyphItemPrivateModulePrivate
      GlyphGroupModuleGlyphItemShortcutModuleShortcut
      GlyphGroupNamespaceGlyphItemPublicNamespacePublic
      GlyphGroupNamespaceGlyphItemInternalNamespaceInternal
      GlyphGroupNamespaceGlyphItemFriendNamespaceInternal
      GlyphGroupNamespaceGlyphItemProtectedNamespaceProtected
      GlyphGroupNamespaceGlyphItemPrivateNamespacePrivate
      GlyphGroupNamespaceGlyphItemShortcutNamespaceShortcut
      GlyphGroupOperatorGlyphItemPublicOperatorPublic
      GlyphGroupOperatorGlyphItemInternalOperatorInternal
      GlyphGroupOperatorGlyphItemFriendOperatorInternal
      GlyphGroupOperatorGlyphItemProtectedOperatorProtected
      GlyphGroupOperatorGlyphItemPrivateOperatorPrivate
      GlyphGroupOperatorGlyphItemShortcutOperatorShortcut
      GlyphGroupPropertyGlyphItemPublicPropertyPublic
      GlyphGroupPropertyGlyphItemInternalPropertyInternal
      GlyphGroupPropertyGlyphItemFriendPropertyInternal
      GlyphGroupPropertyGlyphItemProtectedPropertyProtected
      GlyphGroupPropertyGlyphItemPrivatePropertyPrivate
      GlyphGroupPropertyGlyphItemShortcutPropertyShortcut
      GlyphGroupStructGlyphItemPublicStructurePublic
      GlyphGroupStructGlyphItemInternalStructureInternal
      GlyphGroupStructGlyphItemFriendStructureInternal
      GlyphGroupStructGlyphItemProtectedStructureProtected
      GlyphGroupStructGlyphItemPrivateStructurePrivate
      GlyphGroupStructGlyphItemShortcutStructureShortcut
      GlyphGroupTemplateGlyphItemPublicTemplatePublic
      GlyphGroupTemplateGlyphItemInternalTemplateInternal
      GlyphGroupTemplateGlyphItemFriendTemplateInternal
      GlyphGroupTemplateGlyphItemProtectedTemplateProtected
      GlyphGroupTemplateGlyphItemPrivateTemplatePrivate
      GlyphGroupTemplateGlyphItemShortcutTemplateShortcut
      GlyphGroupTypedefGlyphItemPublicTypeDefinitionPublic
      GlyphGroupTypedefGlyphItemInternalTypeDefinitionInternal
      GlyphGroupTypedefGlyphItemFriendTypeDefinitionInternal
      GlyphGroupTypedefGlyphItemProtectedTypeDefinitionProtected
      GlyphGroupTypedefGlyphItemPrivateTypeDefinitionPrivate
      GlyphGroupTypedefGlyphItemShortcutTypeDefinitionShortcut
      GlyphGroupTypeGlyphItemPublicTypePublic
      GlyphGroupTypeGlyphItemInternalTypeInternal
      GlyphGroupTypeGlyphItemFriendTypeInternal
      GlyphGroupTypeGlyphItemProtectedTypeProtected
      GlyphGroupTypeGlyphItemPrivateTypePrivate
      GlyphGroupTypeGlyphItemShortcutTypeShortcut
      GlyphGroupUnionGlyphItemPublicUnionPublic
      GlyphGroupUnionGlyphItemInternalUnionInternal
      GlyphGroupUnionGlyphItemFriendUnionInternal
      GlyphGroupUnionGlyphItemProtectedUnionProtected
      GlyphGroupUnionGlyphItemPrivateUnionPrivate
      GlyphGroupUnionGlyphItemShortcutUnionShortcut
      GlyphGroupVariableGlyphItemPublicFieldPublic
      GlyphGroupVariableGlyphItemInternalFieldInternal
      GlyphGroupVariableGlyphItemFriendFieldInternal
      GlyphGroupVariableGlyphItemProtectedFieldProtected
      GlyphGroupVariableGlyphItemPrivateFieldPrivate
      GlyphGroupVariableGlyphItemShortcutFieldShortcut
      GlyphGroupValueTypeGlyphItemPublicValueTypePublic
      GlyphGroupValueTypeGlyphItemInternalValueTypeInternal
      GlyphGroupValueTypeGlyphItemFriendValueTypeInternal
      GlyphGroupValueTypeGlyphItemProtectedValueTypeProtected
      GlyphGroupValueTypeGlyphItemPrivateValueTypePrivate
      GlyphGroupValueTypeGlyphItemShortcutValueTypeShortcut
      GlyphGroupIntrinsicGlyphItemPublicObjectPublic
      GlyphGroupIntrinsicGlyphItemInternalObjectInternal
      GlyphGroupIntrinsicGlyphItemFriendObjectInternal
      GlyphGroupIntrinsicGlyphItemProtectedObjectProtected
      GlyphGroupIntrinsicGlyphItemPrivateObjectPrivate
      GlyphGroupIntrinsicGlyphItemShortcutObjectShortcut
      GlyphGroupJSharpMethodGlyphItemPublicMethodPublic
      GlyphGroupJSharpMethodGlyphItemInternalMethodInternal
      GlyphGroupJSharpMethodGlyphItemFriendMethodInternal
      GlyphGroupJSharpMethodGlyphItemProtectedMethodProtected
      GlyphGroupJSharpMethodGlyphItemPrivateMethodPrivate
      GlyphGroupJSharpMethodGlyphItemShortcutMethodShortcut
      GlyphGroupJSharpFieldGlyphItemPublicFieldPublic
      GlyphGroupJSharpFieldGlyphItemInternalFieldInternal
      GlyphGroupJSharpFieldGlyphItemFriendFieldInternal
      GlyphGroupJSharpFieldGlyphItemProtectedFieldProtected
      GlyphGroupJSharpFieldGlyphItemPrivateFieldPrivate
      GlyphGroupJSharpFieldGlyphItemShortcutFieldShortcut
      GlyphGroupJSharpClassGlyphItemPublicClassPublic
      GlyphGroupJSharpClassGlyphItemInternalClassInternal
      GlyphGroupJSharpClassGlyphItemFriendClassInternal
      GlyphGroupJSharpClassGlyphItemProtectedClassProtected
      GlyphGroupJSharpClassGlyphItemPrivateClassPrivate
      GlyphGroupJSharpClassGlyphItemShortcutClassShortcut
      GlyphGroupJSharpNamespaceGlyphItemPublicNamespacePublic
      GlyphGroupJSharpNamespaceGlyphItemInternalNamespaceInternal
      GlyphGroupJSharpNamespaceGlyphItemFriendNamespaceInternal
      GlyphGroupJSharpNamespaceGlyphItemProtectedNamespaceProtected
      GlyphGroupJSharpNamespaceGlyphItemPrivateNamespacePrivate
      GlyphGroupJSharpNamespaceGlyphItemShortcutNamespaceShortcut
      GlyphGroupJSharpInterfaceGlyphItemPublicInterfacePublic
      GlyphGroupJSharpInterfaceGlyphItemInternalInterfaceInternal
      GlyphGroupJSharpInterfaceGlyphItemFriendInterfaceInternal
      GlyphGroupJSharpInterfaceGlyphItemProtectedInterfaceProtected
      GlyphGroupJSharpInterfaceGlyphItemPrivateInterfacePrivate
      GlyphGroupJSharpInterfaceGlyphItemShortcutInterfaceShortcut
      GlyphGroupErrorStatusError
      GlyphBscFileClassFile
      GlyphAssemblyReference
      GlyphLibraryLibrary
      GlyphVBProjectVBProjectNode
      GlyphCoolProjectCSProjectNode
      GlyphCppProjectCPPProjectNode
      GlyphDialogIdDialog
      GlyphOpenFolderFolderOpened
      GlyphClosedFolderFolderClosed
      GlyphArrowGoToNext
      GlyphCSharpFileCSFileNode
      GlyphCSharpExpansionSnippet
      GlyphKeywordIntellisenseKeyword
      GlyphInformationStatusInformation
      GlyphReferenceClassMethodReference
      GlyphRecursionRecursion
      GlyphXmlItemTag
      GlyphJSharpProjectDocumentCollection
      GlyphJSharpDocumentDocument
      GlyphForwardTypeGoToNext
      GlyphCallersGraphCallTo
      GlyphCallGraphCallFrom
      GlyphWarningStatusWarning
      GlyphMaybeReferenceQuestionMark
      GlyphMaybeCallerCallTo
      GlyphMaybeCallCallFrom
      GlyphExtensionMethodExtensionMethod
      GlyphExtensionMethodInternalExtensionMethod
      GlyphExtensionMethodFriendExtensionMethod
      GlyphExtensionMethodProtectedExtensionMethod
      GlyphExtensionMethodPrivateExtensionMethod
      GlyphExtensionMethodShortcutExtensionMethod
      GlyphXmlAttributeXmlAttribute
      GlyphXmlChildXmlElement
      GlyphXmlDescendantXmlDescendant
      GlyphXmlNamespaceXmlNamespace
      GlyphXmlAttributeQuestionXmlAttributeLowConfidence
      GlyphXmlAttributeCheckXmlAttributeHighConfidence
      GlyphXmlChildQuestionXmlElementLowConfidence
      GlyphXmlChildCheckXmlElementHighConfidence
      GlyphXmlDescendantQuestionXmlDescendantLowConfidence
      GlyphXmlDescendantCheckXmlDescendantHighConfidence
      GlyphCompletionWarningIntellisenseWarning
Show: