StockIcons for Windows Presentation Framework?
Windows Vista introduces a new native API that allows you to retrieve system-defined Shell icons: SHGetStockIconInfo. Those icons are stored in %SystemRoot%\System32\ImageRes.dll.
To understand that API documentation, I read About Icons again: last time was 15+ years ago (thank you Charles Petzold). Now, armed with that knowledge and the help of numerous knowledgeable people, I worked on a managed wrapper for WPF.
Once improved (i.e. caching), this should eventually make it into the VistaBridge samples (expand CrossTechnologySamples.zip, typically under %ProgramFiles%\Microsoft SDKs\Windows\v6.0\Samples).
The icon identifier values below should be the correct ones once we release the Windows SDK. (See ShellApi.h)
Let me thank, in no particular order, these fellow Microsoft employees: Jeff Chrisope (time to update that blog Jeff!), Robert Wlodarczyk, Rusty Deschenes, Kerem Karatal, Ahsan Kabir, Anthony Hodsdon, Eric Stollnitz, Adam Smith, Rob Relyea, Peter Koen.
An example to start:
<Window x:Class="WPFTest.Window1" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vb="clr-namespace:VistaBridge.UI;assembly=StockIcons"
Title="Stock Icons test under Windows Presentation Framework" Height="300" Width="300">
<Grid Name="TheGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Image Grid.Row="0" Grid.Column="0" Stretch="None"
Source="{x:Static vb:StockIcons.Shield}"/>
<Image Grid.Row="0" Grid.Column="1" Stretch="None"
Source="{x:Static vb:StockIcons.DocumentNotAssociated}"/>
<Image Grid.Row="0" Grid.Column="2" Stretch="None"
Source="{x:Static vb:StockIcons.DocumentAssociated}"/>
<Image Grid.Row="0" Grid.Column="3" Stretch="None"
Source="{x:Static vb:StockIcons.Application}"/>
<Image Grid.Row="1" Grid.Column="0" Stretch="None"
Source="{x:Static vb:StockIcons.Folder}"/>
<Image Grid.Row="1" Grid.Column="1" Stretch="None"
Source="{x:Static vb:StockIcons.FolderOpen}"/>
<Image Grid.Row="1" Grid.Column="2" Stretch="None"
Source="{x:Static vb:StockIcons.Drive525}"/>
<Image Grid.Row="1" Grid.Column="3" Stretch="None"
Source="{x:Static vb:StockIcons.Drive35}"/>
<Image Grid.Row="2" Grid.Column="0" Stretch="None"
Source="{vb:StockIcon Shield}"/>
<Image Grid.Row="2" Grid.Column="1" Stretch="None"
Source="{vb:StockIcon DocumentNotAssociated, 'Small,Selected,LinkOverlay'}"/>
<Image Grid.Row="2" Grid.Column="2" Stretch="None"
Source="{vb:StockIcon DocumentAssociated, Selected}"/>
<Image Grid.Row="2" Grid.Column="3" Stretch="None"
Source="{vb:StockIcon Application, LinkOverlay}"/>
<Image Grid.Row="3" Grid.Column="0" Stretch="None"
Source="{vb:StockIcon Identifier=Folder, Small=True, Selected=True}"/>
<Image Grid.Row="3" Grid.Column="1" Stretch="None"
Source="{vb:StockIcon Identifier=FolderOpen, Small=True, LinkOverlay=True, ShellSize=True}"/>
</Grid>
</Window>
If as Charles Petzold, you prefer code:
public partial class Window1 : System.Windows.Window {
public Window1() {
InitializeComponent();
// The Elvis way:
StockIcon icon = new StockIcon();
icon.Identifier = StockIconIdentifier.Drive525;
icon.Small = true;
icon.LinkOverlay = true;
icon.Selected = true;
Image image = new Image();
image.Source = icon.Bitmap;
image.Stretch = Stretch.None;
TheGrid.Children.Add(image);
Grid.SetRow(image, 3);
Grid.SetColumn(image, 2);
// The Einstein way:
image = new Image();
image.Source = new StockIcon(StockIconIdentifier.Drive35, StockIconOptions.LinkOverlay | StockIconOptions.Selected | StockIconOptions.Small).Bitmap;
image.Stretch = Stretch.None;
TheGrid.Children.Add(image);
Grid.SetRow(image, 3);
Grid.SetColumn(image, 3);
}
}
And now the C# code behind the StockIcons static class and StockIcon markup extension class:
using System;
using System.Runtime.InteropServices; // too many types. Let's include the whole namespace
using Int32Rect = System.Windows.Int32Rect;
using Freezable = System.Windows.Freezable;
using InteropImaging = System.Windows.Interop.Imaging;
using MarkupExtension = System.Windows.Markup.MarkupExtension;
using ImageSource = System.Windows.Media.ImageSource;
using BitmapSource = System.Windows.Media.Imaging.BitmapSource;
using TypeConverter = System.ComponentModel.TypeConverter;
using MediaImaging = System.Windows.Media.Imaging;
using TypeConverterAttribute = System.ComponentModel.TypeConverterAttribute;
using ITypeDescriptorContext = System.ComponentModel.ITypeDescriptorContext;
using EnumConverter = System.ComponentModel.EnumConverter;
using CultureInfo = System.Globalization.CultureInfo;
namespace VistaBridge.UI {
public static class StockIcons {
public static BitmapSource GetBitmapSource(StockIconIdentifier identifier) {
return StockIcon.GetBitmapSource(identifier, 0);
}
public static BitmapSource DocumentNotAssociated {get {return GetBitmapSource(StockIconIdentifier.DocumentNotAssociated);}}
public static BitmapSource DocumentAssociated {get {return GetBitmapSource(StockIconIdentifier.DocumentAssociated);}}
public static BitmapSource Application {get {return GetBitmapSource(StockIconIdentifier.Application);}}
public static BitmapSource Folder {get {return GetBitmapSource(StockIconIdentifier.Folder);}}
public static BitmapSource FolderOpen {get {return GetBitmapSource(StockIconIdentifier.FolderOpen);}}
public static BitmapSource Drive525 {get {return GetBitmapSource(StockIconIdentifier.Drive525);}}
public static BitmapSource Drive35 {get {return GetBitmapSource(StockIconIdentifier.Drive35);}}
public static BitmapSource DriveRemove {get {return GetBitmapSource(StockIconIdentifier.DriveRemove);}}
public static BitmapSource DriveFixed {get {return GetBitmapSource(StockIconIdentifier.DriveFixed);}}
public static BitmapSource DriveNetwork {get {return GetBitmapSource(StockIconIdentifier.DriveNetwork);}}
public static BitmapSource DriveNetworkDisabled {get {return GetBitmapSource(StockIconIdentifier.DriveNetworkDisabled);}}
public static BitmapSource DriveCD {get {return GetBitmapSource(StockIconIdentifier.DriveCD);}}
public static BitmapSource DriveRAM {get {return GetBitmapSource(StockIconIdentifier.DriveRAM);}}
public static BitmapSource World {get {return GetBitmapSource(StockIconIdentifier.World);}}
public static BitmapSource Server {get {return GetBitmapSource(StockIconIdentifier.Server);}}
public static BitmapSource Printer {get {return GetBitmapSource(StockIconIdentifier.Printer);}}
public static BitmapSource MyNetwork {get {return GetBitmapSource(StockIconIdentifier.MyNetwork);}}
public static BitmapSource Find {get {return GetBitmapSource(StockIconIdentifier.Find);}}
public static BitmapSource Help {get {return GetBitmapSource(StockIconIdentifier.Help);}}
public static BitmapSource Share {get {return GetBitmapSource(StockIconIdentifier.Share);}}
public static BitmapSource Link {get {return GetBitmapSource(StockIconIdentifier.Link);}}
public static BitmapSource SlowFile {get {return GetBitmapSource(StockIconIdentifier.SlowFile);}}
public static BitmapSource Recycler {get {return GetBitmapSource(StockIconIdentifier.Recycler);}}
public static BitmapSource RecyclerFull {get {return GetBitmapSource(StockIconIdentifier.RecyclerFull);}}
public static BitmapSource MediaCDAudio {get {return GetBitmapSource(StockIconIdentifier.MediaCDAudio);}}
public static BitmapSource Lock {get {return GetBitmapSource(StockIconIdentifier.Lock);}}
public static BitmapSource AutoList {get {return GetBitmapSource(StockIconIdentifier.AutoList);}}
public static BitmapSource PrinterNet {get {return GetBitmapSource(StockIconIdentifier.PrinterNet);}}
public static BitmapSource ServerShare {get {return GetBitmapSource(StockIconIdentifier.ServerShare);}}
public static BitmapSource PrinterFax {get {return GetBitmapSource(StockIconIdentifier.PrinterFax);}}
public static BitmapSource PrinterFaxNet {get {return GetBitmapSource(StockIconIdentifier.PrinterFaxNet);}}
public static BitmapSource PrinterFile {get {return GetBitmapSource(StockIconIdentifier.PrinterFile);}}
public static BitmapSource Stack {get {return GetBitmapSource(StockIconIdentifier.Stack);}}
public static BitmapSource MediaSVCD {get {return GetBitmapSource(StockIconIdentifier.MediaSVCD);}}
public static BitmapSource StuffedFolder {get {return GetBitmapSource(StockIconIdentifier.StuffedFolder);}}
public static BitmapSource DriveUnknown {get {return GetBitmapSource(StockIconIdentifier.DriveUnknown);}}
public static BitmapSource DriveDVD {get {return GetBitmapSource(StockIconIdentifier.DriveDVD);}}
public static BitmapSource MediaDVD {get {return GetBitmapSource(StockIconIdentifier.MediaDVD);}}
public static BitmapSource MediaDVDRAM {get {return GetBitmapSource(StockIconIdentifier.MediaDVDRAM);}}
public static BitmapSource MediaDVDRW {get {return GetBitmapSource(StockIconIdentifier.MediaDVDRW);}}
public static BitmapSource MediaDVDR {get {return GetBitmapSource(StockIconIdentifier.MediaDVDR);}}
public static BitmapSource MediaDVDROM {get {return GetBitmapSource(StockIconIdentifier.MediaDVDROM);}}
public static BitmapSource MediaCDAudioPlus {get {return GetBitmapSource(StockIconIdentifier.MediaCDAudioPlus);}}
public static BitmapSource MediaCDRW {get {return GetBitmapSource(StockIconIdentifier.MediaCDRW);}}
public static BitmapSource MediaCDR {get {return GetBitmapSource(StockIconIdentifier.MediaCDR);}}
public static BitmapSource MediaCDBurn {get {return GetBitmapSource(StockIconIdentifier.MediaCDBurn);}}
public static BitmapSource MediaBlankCD {get {return GetBitmapSource(StockIconIdentifier.MediaBlankCD);}}
public static BitmapSource MediaCDROM {get {return GetBitmapSource(StockIconIdentifier.MediaCDROM);}}
public static BitmapSource AudioFiles {get {return GetBitmapSource(StockIconIdentifier.AudioFiles);}}
public static BitmapSource ImageFiles {get {return GetBitmapSource(StockIconIdentifier.ImageFiles);}}
public static BitmapSource VideoFiles {get {return GetBitmapSource(StockIconIdentifier.VideoFiles);}}
public static BitmapSource MixedFiles {get {return GetBitmapSource(StockIconIdentifier.MixedFiles);}}
public static BitmapSource FolderBack {get {return GetBitmapSource(StockIconIdentifier.FolderBack);}}
public static BitmapSource FolderFront {get {return GetBitmapSource(StockIconIdentifier.FolderFront);}}
public static BitmapSource Shield {get {return GetBitmapSource(StockIconIdentifier.Shield);}}
public static BitmapSource Warning {get {return GetBitmapSource(StockIconIdentifier.Warning);}}
public static BitmapSource Info {get {return GetBitmapSource(StockIconIdentifier.Info);}}
public static BitmapSource Error {get {return GetBitmapSource(StockIconIdentifier.Error);}}
public static BitmapSource Key {get {return GetBitmapSource(StockIconIdentifier.Key);}}
public static BitmapSource Software {get {return GetBitmapSource(StockIconIdentifier.Software);}}
public static BitmapSource Rename {get {return GetBitmapSource(StockIconIdentifier.Rename);}}
public static BitmapSource Delete {get {return GetBitmapSource(StockIconIdentifier.Delete);}}
public static BitmapSource MediaAudioDVD {get {return GetBitmapSource(StockIconIdentifier.MediaAudioDVD);}}
public static BitmapSource MediaMovieDVD {get {return GetBitmapSource(StockIconIdentifier.MediaMovieDVD);}}
public static BitmapSource MediaEnhancedCD {get {return GetBitmapSource(StockIconIdentifier.MediaEnhancedCD);}}
public static BitmapSource MediaEnhancedDVD {get {return GetBitmapSource(StockIconIdentifier.MediaEnhancedDVD);}}
public static BitmapSource MediaHDDVD {get {return GetBitmapSource(StockIconIdentifier.MediaHDDVD);}}
public static BitmapSource MediaBluRay {get {return GetBitmapSource(StockIconIdentifier.MediaBluRay);}}
public static BitmapSource MediaVCD {get {return GetBitmapSource(StockIconIdentifier.MediaVCD);}}
public static BitmapSource MediaDVDPlusR {get {return GetBitmapSource(StockIconIdentifier.MediaDVDPlusR);}}
public static BitmapSource MediaDVDPlusRW {get {return GetBitmapSource(StockIconIdentifier.MediaDVDPlusRW);}}
public static BitmapSource DesktopPC {get {return GetBitmapSource(StockIconIdentifier.DesktopPC);}}
public static BitmapSource MobilePC {get {return GetBitmapSource(StockIconIdentifier.MobilePC);}}
public static BitmapSource Users {get {return GetBitmapSource(StockIconIdentifier.Users);}}
public static BitmapSource MediaSmartMedia {get {return GetBitmapSource(StockIconIdentifier.MediaSmartMedia);}}
public static BitmapSource MediaCompactFlash {get {return GetBitmapSource(StockIconIdentifier.MediaCompactFlash);}}
public static BitmapSource DeviceCellPhone {get {return GetBitmapSource(StockIconIdentifier.DeviceCellPhone);}}
public static BitmapSource DeviceCamera {get {return GetBitmapSource(StockIconIdentifier.DeviceCamera);}}
public static BitmapSource DeviceVideoCamera {get {return GetBitmapSource(StockIconIdentifier.DeviceVideoCamera);}}
public static BitmapSource DeviceAudioPlayer {get {return GetBitmapSource(StockIconIdentifier.DeviceAudioPlayer);}}
public static BitmapSource NetworkConnect {get {return GetBitmapSource(StockIconIdentifier.NetworkConnect);}}
public static BitmapSource Internet {get {return GetBitmapSource(StockIconIdentifier.Internet);}}
public static BitmapSource ZipFile {get {return GetBitmapSource(StockIconIdentifier.ZipFile);}}
public static BitmapSource Settings {get {return GetBitmapSource(StockIconIdentifier.Settings);}}
}
public class StockIcon : MarkupExtension {
StockIconIdentifier _identifier;
StockIconOptions _flags;
BitmapSource _bitmapSource = null;
public StockIcon() {
}
public StockIcon(StockIconIdentifier identifier) : this(identifier,0){
}
public StockIcon(StockIconIdentifier identifier, StockIconOptions flags) {
Identifier = identifier;
Selected = (flags & StockIconOptions.Selected) == StockIconOptions.Selected;
LinkOverlay = (flags & StockIconOptions.LinkOverlay) == StockIconOptions.LinkOverlay;
ShellSize = (flags & StockIconOptions.ShellSize) == StockIconOptions.ShellSize;
Small = (flags & StockIconOptions.Small) == StockIconOptions.Small;
}
protected void Check() {
if (_bitmapSource != null)
throw new InvalidOperationException("The BitmapSource has already been created");
}
public bool Selected {
get {return (_flags & StockIconOptions.Selected) == StockIconOptions.Selected ;}
set {
Check();
if (value)
_flags |= StockIconOptions.Selected;
else
_flags &= ~StockIconOptions.Selected;
}
}
public bool LinkOverlay {
get {return (_flags & StockIconOptions.LinkOverlay) == StockIconOptions.LinkOverlay;}
set {
Check();
if (value)
_flags |= StockIconOptions.LinkOverlay;
else
_flags &= ~StockIconOptions.LinkOverlay;
}
}
public bool ShellSize {
get {return (_flags & StockIconOptions.ShellSize) == StockIconOptions.ShellSize;}
set {
Check();
if (value)
_flags |= StockIconOptions.ShellSize;
else
_flags &= ~StockIconOptions.ShellSize;
}
}
public bool Small {
get { return (_flags & StockIconOptions.Small) == StockIconOptions.Small; }
set {
Check();
if (value)
_flags |= StockIconOptions.Small;
else
_flags &= ~StockIconOptions.Small;
}
}
public StockIconIdentifier Identifier {
get { return _identifier; }
set {
Check();
_identifier = value;
}
}
public override Object ProvideValue(IServiceProvider serviceProvider) {
return Bitmap;
}
public BitmapSource Bitmap {
get {
if (_bitmapSource == null) {
_bitmapSource = GetBitmapSource(_identifier, _flags);
}
return _bitmapSource;
}
}
protected internal static BitmapSource GetBitmapSource(StockIconIdentifier identifier, StockIconOptions flags) {
BitmapSource bitmapSource = (BitmapSource) InteropHelper.MakeImage(identifier, StockIconOptions.Handle | flags);
bitmapSource.Freeze();
return bitmapSource;
}
}
[Flags]
public enum StockIconOptions : uint {
Small = 0x000000001, // Retrieve the small version of the icon, as specified by the SM_CXSMICON and SM_CYSMICON system metrics.
ShellSize = 0x000000004, // Retrieve the shell-sized icons rather than the sizes specified by the system metrics.
Handle = 0x000000100, // The hIcon member of the SHSTOCKICONINFO structure receives a handle to the specified icon.
SystemIndex = 0x000004000, // The iSysImageImage member of the SHSTOCKICONINFO structure receives the index of the specified icon in the system imagelist.
LinkOverlay = 0x000008000, // Add the link overlay to the file's icon.
Selected = 0x000010000 // Blend the icon with the system highlight color.
}
public enum StockIconIdentifier : uint {
DocumentNotAssociated = 0, // document (blank page), no associated program
DocumentAssociated = 1, // document with an associated program
Application = 2, // generic application with no custom icon
Folder = 3, // Folder (closed)
FolderOpen = 4, // Folder (open)
Drive525 = 5, // 5.25" floppy disk Drive
Drive35 = 6, // 3.5" floppy disk Drive
DriveRemove = 7, // removable Drive
DriveFixed = 8, // Fixed (hard disk) Drive
DriveNetwork = 9, // Network Drive
DriveNetworkDisabled = 10, // disconnected Network Drive
DriveCD = 11, // CD Drive
DriveRAM = 12, // RAM disk Drive
World = 13, // entire Network
Server = 15, // a computer on the Network
Printer = 16, // printer
MyNetwork = 17, // My Network places
Find = 22, // Find
Help = 23, // Help
Share = 28, // overlay for shared items
Link = 29, // overlay for shortcuts to items
SlowFile = 30, // overlay for slow items
Recycler = 31, // empty recycle bin
RecyclerFull = 32, // full recycle bin
MediaCDAudio = 40, // Audio CD Media
Lock = 47, // Security lock
AutoList = 49, // AutoList
PrinterNet = 50, // Network printer
ServerShare = 51, // Server share
PrinterFax = 52, // Fax printer
PrinterFaxNet = 53, // Networked Fax Printer
PrinterFile = 54, // Print to File
Stack = 55, // Stack
MediaSVCD = 56, // SVCD Media
StuffedFolder = 57, // Folder containing other items
DriveUnknown = 58, // Unknown Drive
DriveDVD = 59, // DVD Drive
MediaDVD = 60, // DVD Media
MediaDVDRAM = 61, // DVD-RAM Media
MediaDVDRW = 62, // DVD-RW Media
MediaDVDR = 63, // DVD-R Media
MediaDVDROM = 64, // DVD-ROM Media
MediaCDAudioPlus = 65, // CD+ (Enhanced CD) Media
MediaCDRW = 66, // CD-RW Media
MediaCDR = 67, // CD-R Media
MediaCDBurn = 68, // Burning CD
MediaBlankCD = 69, // Blank CD Media
MediaCDROM = 70, // CD-ROM Media
AudioFiles = 71, // Audio Files
ImageFiles = 72, // Image Files
VideoFiles = 73, // Video Files
MixedFiles = 74, // Mixed Files
FolderBack = 75, // Folder back
FolderFront = 76, // Folder front
Shield = 77, // Security shield. Use for UAC prompts only.
Warning = 78, // Warning
Info = 79, // Informational
Error = 80, // Error
Key = 81, // Key / Secure
Software = 82, // Software
Rename = 83, // Rename
Delete = 84, // Delete
MediaAudioDVD = 85, // Audio DVD Media
MediaMovieDVD = 86, // Movie DVD Media
MediaEnhancedCD = 87, // Enhanced CD Media
MediaEnhancedDVD = 88, // Enhanced DVD Media
MediaHDDVD = 89, // HD-DVD Media
MediaBluRay = 90, // BluRay Media
MediaVCD = 91, // VCD Media
MediaDVDPlusR = 92, // DVD+R Media
MediaDVDPlusRW = 93, // DVD+RW Media
DesktopPC = 94, // desktop computer
MobilePC = 95, // mobile computer (laptop/notebook)
Users = 96, // users
MediaSmartMedia = 97, // Smart Media
MediaCompactFlash = 98, // Compact Flash
DeviceCellPhone = 99, // Cell phone
DeviceCamera = 100, // Camera
DeviceVideoCamera = 101, // Video camera
DeviceAudioPlayer = 102, // Audio player
NetworkConnect = 103, // Connect to Network
Internet = 104, // InterNet
ZipFile = 105, // ZIP File
Settings = 106 // Settings
}
internal static class InteropHelper {
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct StockIconInfo {
internal UInt32 StuctureSize;
internal IntPtr Handle;
internal Int32 ImageIndex;
internal Int32 Identifier;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
internal string Path;
}
[DllImport("Shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
internal static extern int SHGetStockIconInfo(StockIconIdentifier identifier, StockIconOptions flags, ref StockIconInfo info);
[DllImport("User32.dll", SetLastError = true)]
internal static extern bool DestroyIcon(IntPtr handle);
internal static ImageSource MakeImage(StockIconIdentifier identifier, StockIconOptions flags) {
IntPtr iconHandle = GetIcon(identifier, flags);
ImageSource imageSource;
try {
imageSource = InteropImaging.CreateBitmapSourceFromHIcon(iconHandle, Int32Rect.Empty, null);
} finally {
DestroyIcon(iconHandle);
}
return imageSource;
}
internal static IntPtr GetIcon(StockIconIdentifier identifier, StockIconOptions flags) {
StockIconInfo info = new StockIconInfo();
info.StuctureSize = (UInt32) Marshal.SizeOf(typeof(StockIconInfo));
int hResult = SHGetStockIconInfo( identifier, flags, ref info);
if (hResult < 0)
throw new COMException("SHGetStockIconInfo execution failure", hResult);
return info.Handle;
}
}
}
Comments
- Anonymous
October 10, 2007
I recall needing/wanting to use some of the stock Windows Icons way back when. Stumbled across this blog