1

Most operating systems tend to use a common set of "stock" icons for indicating "warning", "error", and other states. And most of us know that we should not grovel into undocumented resources and use them in our application.

However, in GTK, it is possible to retrieve these icons because the toolkit provides documented APIs to do so. In Windows, while it is possible to extract a limited set of icons from the appropriate DLLs, this is undocumented and not guaranteed to work in future versions of Windows. Icons provided by an API are a contract; icons stored in a DLL are an implementation detail.

Is there any Windows (or .NET 4) API function to retrieve a "stock icon"? I know that for file associations, one could grovel the registry to locate the DefaultIcon entry, but this wouldn't take into account custom icon handlers, and it is not a solution for other stock icons such as the ones used in warning or error message boxes.

If there is no such functionality, what would be the most future-proof way to use these icons in my application? Or do I just have to do all the work myself and worry about Microsoft changing the implementation details in a future version of Windows?

  • 2
    SHGetStockIconInfo? https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetstockiconinfo – Simon Mourier Sep 11 '20 at 13:25
  • @SimonMourier that only works for Shell icons, which I don't think are the ones being asked about here. – Mark Ransom Sep 11 '20 at 13:26
  • Oh...... WOW. I had no idea that function even existed. +1! I might be nitpicking here, I would prefer a solution that works as far back as Windows XP... but I can live with that. This is exactly what I was looking for. – slickdeveloper Sep 11 '20 at 13:27
  • @MarkRansom - well, this is the Windows Shell official stock icons. It has warning, error, etc. What would be an icon without shell? – Simon Mourier Sep 11 '20 at 13:29
  • I didn't think the shell would have "the ones used in warning or error message boxes" as those are supplied at a lower level. I was thinking you would use it to get application icons for example. – Mark Ransom Sep 11 '20 at 13:31
  • @MarkRansom You can get application icons with ExtractIconEx. Prior to Windows Vista though there was no good way to get the standard warning or error icons aside from groveling into shell32.dll . – slickdeveloper Sep 11 '20 at 13:34
  • My question was mainly wondering if there was a better solution than groveling into DLLs and calling ExtractIconEx manually. Fortunately as @SimonMourier pointed out there is now an API to do exactly what I was asking. – slickdeveloper Sep 11 '20 at 13:35
  • I may very well be present under Windows XP. Official doc only show systems that are still supported, you should check/try, I don't have an XP at hand (XP? seriously?). – Simon Mourier Sep 11 '20 at 13:43
  • @SimonMourier re "only show systems that are still supported" is not entirely correct, as the docs for the LoadIcon/LoadImage functions specifically say Windows 2000... I only mentioned XP because I'm still using .NET 4 and that is portable (surprisingly) all the way back to XP. I'm big on nostalgia. VMs are great :) though I do miss the clickety-clack of old spinning hard disks and floppies... – slickdeveloper Sep 11 '20 at 13:48
  • 1
    @slickdeveloper This [SO question](https://stackoverflow.com/questions/60887975/getting-modern-system-icons-with-loadicon), I've asked a few months ago and the associated answer might be interesting too. – Jabberwocky Sep 11 '20 at 13:51
  • @slickdeveloper - yeah, sometimes it's Windows 2000, sometimes it's Windows Vista. For ex, IUnknown existed long before that: https://learn.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown or GetWindowText (Windows 1.0) XP is very hard to use today (updates don't work, internet don't work because of HTTPS, certificates, browsers don't work, etc. nothing really works anymore, it's pretty useless) – Simon Mourier Sep 11 '20 at 14:29
  • @SimonMourier In this case, the documentation is accurate - `SHGetStockIconInfo` really was introduced in Vista. – Remy Lebeau Sep 11 '20 at 18:29

1 Answers1

2

You can use LoadIcon or LoadImage to load stock icons. Microsoft recommends LoadImage but doesn't document the icons you can load, only pointing you to a .h file that contains the list.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I like this one, it seems portable all the way back to Win2k, compared to the newer solution provided by Windows Vista. I think it didn't come to mind for me initially because I had assumed you had to pass in the library loaded by LoadLibrary, but I see now the docs state that you can also use "predefined icons" which seems to work for what I'm asking about. – slickdeveloper Sep 11 '20 at 13:39
  • 1
    This [SO question](https://stackoverflow.com/questions/60887975/getting-modern-system-icons-with-loadicon), I've asked a few months ago and the associated answer might be interesting too. – Jabberwocky Sep 11 '20 at 13:45
  • @Jabberwocky Ooh. See. That is exactly why I don't always trust APIs. Windows tends to "fake" some things if they think your application can't handle it. Though I'm not sure this is what's happening here. Very strange... it seems like they ship two entirely different icons (the modern one and the Vista-era one) though why they would do this is rather baffling. Unless it has something to do with icon sizes and metrics and other compatibility nonsense I don't completely understand... – slickdeveloper Sep 11 '20 at 13:52
  • 1
    @slickdeveloper I don't understand either. I've replaced the old WIndows 7 icons by the new ones in all applications my company maintains, and there haven't been any issues whatsoever, even though the new "attention" icon is slightly higher than the old one. If you want to use this approach and you want to run your software on Windows XP, you need a fallback to LoadIcon though. – Jabberwocky Sep 11 '20 at 13:56