Scouring the features that WinForms got in .NET 8, I found one slipped in near the very bottom of the list under “miscellaneous improvements” called GetStockIcon. It’s a new method for grabbing Windows stock icons (i.e. save, folder, etc) at runtime, to use in the UI.

When I’ve wanted to add system icons to buttons, toolbars, etc in the past, it usually meant extracting them from shell32.dll, imageres.dll.mun, the Visual Studio Image Library, etc, and then copying them into the project. Then I’d add them to an ImageList and hook that up to various UI elements. So I’m wondering.. does this new method give us an easier way to use system icons?

The code in this post is available on GitHub, for you to use, extend, or just follow along while you read… and hopefully discover something new along the way!

Usage

The way it’s called is simple enough. We just pass a StockIconId enum value to tell it which icon to retrieve, and then do whatever we like with the icon:

1
Icon driveIcon = SystemIcons.GetStockIcon(StockIconId.DriveNet);

Once we have it, we could add it to an ImageList and then use that on a Button or other controls. We could also specify a size in the second parameter, like I did here with a PictureBox to display a larger icon that’s still sharp:

1
2
3
4
5
6
// Populate image list with default size, which should be 32 px
imageList1.Images.Add("Conn", SystemIcons.GetStockIcon(StockIconId.DriveNet));
imageList1.Images.Add("Disconn", SystemIcons.GetStockIcon(StockIconId.DriveNetDisabled));

button1.ImageKey = "Conn";
pictureBox1.Image = SystemIcons.GetStockIcon(StockIconId.DriveNet, 128).ToBitmap();

Or we could loop through all of them, adding each to an ImageList, and then use that to create the world’s busiest toolbar: 😏

1
2
3
4
5
foreach (StockIconId icon in Enum.GetValues(typeof(StockIconId)))
    imageList2.Images.Add(icon.ToString(), SystemIcons.GetStockIcon(icon, 64));

toolStrip1.Items.AddRange(imageList2.Images.Keys.Cast<string>().Select(x =>
    new ToolStripButton(imageList2.Images[x]) { ToolTipText = x }).ToArray());

Pros and Cons

The biggest limitation is only being able to call this at runtime. Of course, that’s just the nature of this being a method call, but one of the best things about WinForms is its drag-and-drop designer and this definitely works against that. I’m not sure how much usage this will get if it means having a designer with blank toolbars, incomplete buttons, etc. Maybe I’m missing an obvious use case?

A nice feature, though, is that this method “returns icons that are themed for the running version of Windows”. If we copy icons into the project, they are what they are, unchanged no matter what version of Windows someone happens to be running. But with this new call, when someone runs our app in a different version of Windows from the one we designed it in, they’ll see the icons that are normal for their OS.

Learning More

If you want to learn more, check out the GetStockIcon docs, the StockIconId enum that lists all the available images, and the StockIconOptions enum that lets us set a few options like adding a link overlay to the image. Since a couple of the options involve resizing the icon, we’re not allowed to specify a size and options, but that also means it’s not possible to request a larger image that has a link overlay.. seems like an odd choice.

Lastly, since the StockIconId page doesn’t include the actual images of the icons, here’s a list so you can see what they look like, at least in Windows 11:

NameValueDescriptionImage
DocumentNoAssociation0Document (blank page), no associated program.
DocumentWithAssociation1Document with an associated program.
Application2Generic application with no custom icon.
Folder3Closed folder.
FolderOpen4Open folder.
Drive52555.25" floppy disk drive.
Drive3563.5" floppy disk drive.
DriveRemovable7Removable drive.
DriveFixed8Fixed drive.
DriveNet9Network drive.
DriveNetDisabled10Disabled network drive.
DriveCD11CD drive.
DriveRam12RAM disk drive.
World13Entire network.
Server15A computer on the network.
Printer16Printer.
MyNetwork17My network places.
Find22Find.
Help23Help.
Share28Overlay for shared items.
Link29Overlay for shortcuts to items.
SlowFile30Overlay for slow items.
Recycler31Empty recycle bin.
RecyclerFull32Full recycle bin.
MediaCDAudio40Audio CD media.
Lock47Security lock.
AutoList49AutoList.
PrinterNet50Network printer.
ServerShare51Server share.
PrinterFax52Fax printer.
PrinterFaxNet53Networked fax printer.
PrinterFile54Print to file.
Stack55Stack.
MediaSVCD56SVCD media.
StuffedFolder57Folder containing other items.
DriveUnknown58Unknown drive.
DriveDVD59DVD drive.
MediaDVD60DVD media.
MediaDVDRAM61DVD-RAM media.
MediaDVDRW62DVD-RW media.
MediaDVDR63DVD-R media.
MediaDVDROM64DVD-ROM media.
MediaCDAudioPlus65CD+ (Enhanced CD) media.
MediaCDRW66CD-RW media.
MediaCDR67CD-R media.
MediaCDBurn68Burning CD.
MediaBlankCD69Blank CD media.
MediaCDROM70CD-ROM media.
AudioFiles71Audio files.
ImageFiles72Image files.
VideoFiles73Video files.
MixedFiles74Mixed files.
FolderBack75Folder back.
FolderFront76Folder front.
Shield77Security shield. Use for UAC prompts only.
Warning78Warning.
Info79Informational.
Error80Error.
Key81Key / secure.
Software82Software.
Rename83Rename.
Delete84Delete.
MediaAudioDVD85Audio DVD media.
MediaMovieDVD86Movied DVD media.
MediaEnhancedCD87Enhanced CD media.
MediaEnhancedDVD88Enhanced DVD media.
MediaHDDVD89HD-DVD media.
MediaBluRay90BluRay media.
MediaVCD91VCD media.
MediaDVDPlusR92DVD+R media.
MediaDVDPlusRW93DVD+RW media.
DesktopPC94Desktop computer.
MobilePC95Mobile computer.
Users96Users.
MediaSmartMedia97Smart media.
MediaCompactFlash98Compact Flash.
DeviceCellPhone99Cell phone.
DeviceCamera100Camera.
DeviceVideoCamera101Video camera.
DeviceAudioPlayer102Audio player.
NetworkConnect103Connect to network.
Internet104Internet.
ZipFile105ZIP file.
Settings106Settings.
DriveHDDVD132HD-DVD drive.
DriveBD133BluRay drive.
MediaHDDVDROM134HD-DVD-ROM media.
MediaHDDVDR135HD-DVD-R media.
MediaHDDVDRAM136HD-DVD-RAM media.
MediaBDROM137BluRay-ROM media.
MediaBDR138BluRay-R media.
MediaBDRE139BluRay-RE media.
ClusteredDrive140Clustered disk.

If you found this content useful, and would like to learn more about a variety of C# features, check out my CSharpDotNetFeatures repo, where you’ll find links to plenty more blog posts and practical examples!