47

How do i get an System.Drawing.Image for the various System.Windows.MessageBoxImage(s) and/or System.Windows.Forms.MessageBoxIcon(s)

Simon
  • 30,844
  • 15
  • 120
  • 187

4 Answers4

60

SystemIcons is what I was looking for:

SystemIcons.Warning.ToBitmap();
Sebastian Brosch
  • 37,059
  • 14
  • 61
  • 73
Simon
  • 30,844
  • 15
  • 120
  • 187
36

You can also include SystemIcons in your XAML as follows:

Include a converter (see code below) as a Resource, and an Image control in your XAML. This Image sample here shows the information icon.

     <Window.Resources>
        <Converters:SystemIconConverter x:Key="iconConverter"/>
     </Window.Resources>

     <Image Visibility="Visible"  
            Margin="10,10,0,1"
            Stretch="Uniform"
            MaxHeight="25"
            VerticalAlignment="Top"
            HorizontalAlignment="Left"
            Source="{Binding Converter={StaticResource iconConverter}, ConverterParameter=Information}"/>

Here is the implementation for the converter:

using System;
using System.Drawing;
using System.Globalization;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Interop;
using System.Windows.Media.Imaging;

namespace Converters
{
   [ValueConversion(typeof(string), typeof(BitmapSource))]
   public class SystemIconConverter : IValueConverter
   {
      public object Convert(object value, Type type, object parameter, CultureInfo culture)
      {
         Icon icon = (Icon)typeof(SystemIcons).GetProperty(parameter.ToString(), BindingFlags.Public | BindingFlags.Static).GetValue(null, null);
         BitmapSource bs = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
         return bs;
      }

      public object ConvertBack(object value, Type type, object parameter, CultureInfo culture)
      {
         throw new NotSupportedException();
      }
   }
}
Zamboni
  • 7,437
  • 5
  • 39
  • 48
  • Thanks so much! This works great! However, I noticed that StackOverflow operates under the Creative Commons licence. Thus I technically can't use/adapt your code in my commercial application (which I don't want to be under the Creative Commons licence) without your permission. Are you willing to give me permission? I can still credit your work. – skybluecodeflier Sep 07 '11 at 16:10
  • @skybluecodeflier, any code posted to StackOverflow is creative commons: http://meta.stackexchange.com/questions/12527/do-i-have-to-worry-about-copyright-issues-for-code-posted-on-stack-overflow – Ed Bayiates May 01 '14 at 20:06
  • @Zamboni Is there any particular reason your converter ignores the `value` and performs the conversion using only the `parameter`? That seems atypical of converters. – Disillusioned Oct 17 '16 at 11:59
16

As others have stated SystemIcons is the class that should contain those icons, but on Windows 8.1 (and possibly on earlier versions too) the icons present in the SystemIcons differ from the ones displayed on the MessageBoxes in the case of Asterisk, Information and Question. The icons on the dialog look much flatter. See - for example - the Question icon:

Question icon

The icon in the dialog is the native dialog icon, and the leftmost icon on the form in the background is the icon retrieved from the SystemIcons class.

For various methods and details on how to get the icon from the MessageBox see this answer, but I include here a quick summary, just for the sake of completeness:

You should use the SHGetStockIconInfo function:

 SHSTOCKICONINFO sii = new SHSTOCKICONINFO();
 sii.cbSize = (UInt32)Marshal.SizeOf(typeof(SHSTOCKICONINFO));

 Marshal.ThrowExceptionForHR(SHGetStockIconInfo(SHSTOCKICONID.SIID_INFO,
         SHGSI.SHGSI_ICON ,
         ref sii));
 pictureBox1.Image = Icon.FromHandle(sii.hIcon).ToBitmap();

Please note:

If this function returns an icon handle in the hIcon member of the SHSTOCKICONINFO structure pointed to by psii, you are responsible for freeing the icon with DestroyIcon when you no longer need it.

Of course for this to work you will have to define a few enums and structs:

public enum SHSTOCKICONID : uint
{
    //...
    SIID_INFO = 79,
    //...
}

[Flags]
public enum SHGSI : uint
{
    SHGSI_ICONLOCATION = 0,
    SHGSI_ICON = 0x000000100,
    SHGSI_SYSICONINDEX = 0x000004000,
    SHGSI_LINKOVERLAY = 0x000008000,
    SHGSI_SELECTED = 0x000010000,
    SHGSI_LARGEICON = 0x000000000,
    SHGSI_SMALLICON = 0x000000001,
    SHGSI_SHELLICONSIZE = 0x000000004
}

[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHSTOCKICONINFO
{
    public UInt32 cbSize;
    public IntPtr hIcon;
    public Int32 iSysIconIndex;
    public Int32 iIcon;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260/*MAX_PATH*/)]
    public string szPath;
}

[DllImport("Shell32.dll", SetLastError = false)]
public static extern Int32 SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI uFlags, ref SHSTOCKICONINFO psii);
Community
  • 1
  • 1
qqbenq
  • 8,737
  • 3
  • 33
  • 41
-3
MessageBox.Show(
  "Hello, world!",
  "My App",
  MessageBoxButton.OK, MessageBoxImage.Information);

As simple as that.

jschoi
  • 1,372
  • 9
  • 26
  • Thanks for the answer. but i actually want an instance of the bitmap used, not "how to show the message box". And welcome to stackoverflow – Simon Jul 24 '19 at 21:03