如何在我的WPF应用程序中使用标准的Windows警告/错误图标?

52

我正在为我的WPF应用程序制作自定义错误对话框,我想使用标准的Windows错误图标。我能从WPF中获取特定于操作系统的图标吗?如果不能,有人知道在哪里获取带有透明度的.png文件吗?或者知道从Windows中提取它们的位置吗?

到目前为止,我的搜索还没有发现什么。


你是想要在任何平台上都使用同一张图片,还是想要与当前版本的Windows(包括未来版本)相对应的图标? - Ben Voigt
理想情况下,图标应该看起来像那个版本Windows的标准图标。但是我可以满足于获得Vista/7的标准图标。 - RandomEngy
10个回答

40

有一个SystemIcons类,但它需要进行调整以满足WPF的需求(即将Icon转换为ImageSource)。


1
你完全避免了需要使用p/invoke。做得好。 - Ben Voigt
4
顺便说一下,https://dev59.com/6XNA5IYBdhLWcg3wAI3e,这可能有所帮助。 - bohdan_trotsenko
3
那个线程的步骤多了大约四步。使用 http://msdn.microsoft.com/en-us/library/system.windows.interop.imaging.createbitmapsourcefromhicon(v=VS.90).aspx。 - Ben Voigt
18
Imaging.CreateBitmapSourceFromHIcon(SystemIcons.Error.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); - 看起来很不错,谢谢! - RandomEngy
同意。此外,另一个线程也展示了CreateBitmapSourceFromHIcon的解决方案--你只需要向下滚动即可看到它(它不是被接受的答案)。 - Richard Walters

29

1
谢谢您的回复,但如果我没有记错的话,您必须自己剪切每个图标。哎呀! - greenoldman
2
请注意,图像库不再随Visual Studio一起提供,请参见https://dev59.com/WHA65IYBdhLWcg3w8zjt#20612263。 - BurnsBA

26

这是我在XAML中使用系统图标的方法:

xmlns:draw="clr-namespace:System.Drawing;assembly=System.Drawing"
...
<Image Source="{Binding Source={x:Static draw:SystemIcons.Warning},
        Converter={StaticResource IconToImageSourceConverter},
        Mode=OneWay}" />

我使用了这个转换器将一个图标转换为ImageSource:

public class IconToImageSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var icon = value as Icon;
        if (icon == null)
        {
            Trace.TraceWarning("Attempted to convert {0} instead of Icon object in IconToImageSourceConverter", value);
            return null;
        }

        ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
            icon.Handle,
            Int32Rect.Empty,
            BitmapSizeOptions.FromEmptyOptions());
        return imageSource;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

你是否也有一个名为ToImageSource()的自定义扩展方法?我找不到任何内置的方法可以实现这个。 - RandomEngy
是的,我忘记了。我把扩展方法中的代码添加到转换器本身中了。 - run2thesun
1
对于错误“IconToImageSourceConverter无法解析”。converter需要在FrameworkElement.Resource元素(即Application、Window、UserControl)中定义。请参见SO答案:https://dev59.com/cJLea4cB1Zd3GeqPzDPD#34351777。 - Matt M

6
在Visual Studio中,使用文件+打开+文件并选择c:\windows\system32\user32.dll。打开图标节点,双击103。在我的机器上,这是错误图标。返回,右键单击它并选择导出以保存到文件。
这是一种可行的方法。这些图标也可以在Visual Studio中使用。从您的Visual Studio安装目录中,导航到Common7\VS2008ImageLibrary\xxxx\VS2008ImageLibrary.zip + VS2008ImageLibrary\Annotations&Buttons\ico_format\WinVista\error.ico。Visual Studio安装目录中的redist.txt文件明确赋予您在自己的应用程序中使用此图标的权利。

实际上,未管理的资源ID在winuser.h中被定义,并且现在已经编译成数百万个程序。因此它们不会改变。 DLL中的索引,甚至包含系统图标的DLL可能会更改,但资源ID永远不会改变。 - Ben Voigt
@Ben:不,MB_ICONERROR的值为0x10。与资源ID无关。再次强调:如果您对此有特殊知识,请发表自己的答案。 - Hans Passant
你似乎决定让每个技术主题都变得个人化,而不是让它们独立存在。在这种特殊情况下,你可以通过阅读我正在输入的答案来教育自己,在你发表评论几个小时之前。使用MAKEINTRESOURCE宏定义的资源ID OIC_HAND或等效的OIC_ERROR自LoadImage引入以来从未更改过,并且永远不会更改,因为它已经编译进了数百万个程序中。 - Ben Voigt
抱歉,我关于干扰时间的错误。之前只有大约一小时,而不是几个小时。 - Ben Voigt

5

如果默认大小足够,请使用.NET的SystemIcons类进行前三个步骤,参见modosansreves答案

所以它可以很简单:

 Imaging.CreateBitmapSourceFromHIcon(SystemIcons.Error.Handle)

4
请使用以下内容:
using System;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media.Imaging;

using Extensions
{
    [ContentProperty("Icon")]
    public class ImageSourceFromIconExtension : MarkupExtension
    {
        public Icon Icon { get; set; }

        public ImageSourceFromIconExtension()
        {
        }

        public ImageSourceFromIconExtension(Icon icon)
        {
            Icon = icon;
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return Imaging.CreateBitmapSourceFromHIcon(Icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
        }
    }
}

不要忘记从全局位置添加System.Drawing引用到您的项目中。

然后在您的xaml中使用以下代码:

<WindowOrSomething x:Class="BlaBlaWindow"
    xmlns:draw="clr-namespace:System.Drawing;assembly=System.Drawing"
    xmlns:ext="clr-namespace:Extensions">
    <Image Source="{ext:ImageSourceFromIcon {x:Static draw:SystemIcons.Error}}"/>
</WindowOrSomething>

3

您是否可以简单地使用Windows API?

Delphi示例:

procedure TForm1.FormClick(Sender: TObject);
var
  errIcon: HICON;
begin
  errIcon := LoadIcon(0, IDI_ERROR);
  DrawIcon(Canvas.Handle, 10, 10, errIcon)
end;

0

使用SystemIcons并将它们转换为ImageSource,如下所示:

try   
{
    var temp = SystemIcons.WinLogo.ToBitmap();  //Your icon here
    BitmapImage bitmapImage = new BitmapImage();
    using (MemoryStream memory = new MemoryStream())
    {
       temp.Save(memory, ImageFormat.Png);
       memory.Position = 0;
       bitmapImage.BeginInit();
       bitmapImage.StreamSource = memory;
       bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
       bitmapImage.EndInit();
    }
    this.Icon = bitmapImage;
}
catch (Exception ex)
{
    this.Icon = null;
}

0

将 SystemIcons.Error 等转换为 .png 格式(保持透明度),然后将输出添加到资源中,并像往常一样在 WPF Image 控件中使用。

    System.Drawing.SystemIcons.Error.ToBitmap().Save("Error.png", System.Drawing.Imaging.ImageFormat.Png);

0
你可以像这样绘制它:
Graphics g = this.CreateGraphics();
g.DrawIcon(SystemIcons.Question, 40, 40);

1
WPF 中没有 Graphics。你所写的是针对 GDI 的。 - bohdan_trotsenko
实际上是GDI+,但我们中没有人提供转换为WPF图像的方法。我不熟悉WPF,但我相信有人会知道怎么做。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接