C# WPF 按钮加载系统图标 / 动物头像
重点:Windows系统DLL里没有动物头像 ,动物图片需要自己准备PNG/ICO。WPF没有
Image属性,按钮内部放Image控件实现图文按钮;WPF原生没有Icon→BitmapSource,需要P/Invoke把HICON转WPF的ImageSource。
方式1:Segoe MDL2 / Fluent 系统字体图标(最简单,推荐)
Windows自带字体图标,不用DLL提取,XAML直接写在Button内,无GDI资源泄漏。
<Button Width="140" Height="40">
<StackPanel Orientation="Horizontal">
<!-- Segoe MDL2 Assets 系统图标,Windows10自带 -->
<TextBlock FontFamily="Segoe MDL2 Assets" FontSize="20" Text="" Foreground="Black"/>
<TextBlock Text=" 文件夹" VerticalAlignment="Center"/>
</StackPanel>
</Button>
常用glyph:
文件夹主页警告信息
Win11:
Segoe Fluent Icons,图标编码不一样。
方式2:从 imageres.dll / shell32.dll 提取系统图标(PInvoke)
完整辅助类 IconHelper.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
public static class IconHelper
{
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern int ExtractIconEx(string lpszFile, int nIconIndex, out IntPtr phIconLarge, out IntPtr phIconSmall, int nIcons);
[DllImport("user32.dll")]
private static extern bool DestroyIcon(IntPtr hIcon);
/// <summary>从DLL提取图标,转为WPF可用ImageSource</summary>
public static BitmapSource? GetIconFromDll(string dllPath, int iconIndex)
{
IntPtr hLarge, hSmall;
int ret = ExtractIconEx(dllPath, iconIndex, out hLarge, out hSmall, 1);
if (ret <= 0 || hLarge == IntPtr.Zero) return null;
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHIcon(hLarge, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
DestroyIcon(hLarge);
DestroyIcon(hSmall);
return bitmapSource;
}
}
XAML按钮
<Button x:Name="btnFolder" Width="140" Height="40">
<StackPanel Orientation="Horizontal">
<Image x:Name="imgIcon" Width="24" Height="24"/>
<TextBlock Text="文件夹按钮" Margin="5,0"/>
</StackPanel>
</Button>
后台C#加载
using System.IO;
public MainWindow()
{
InitializeComponent();
string dll = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), @"System32\imageres.dll");
imgIcon.Source = IconHelper.GetIconFromDll(dll, 3); // index=3 文件夹图标
}
方式3:动物头像(本地图片/项目资源)
① 把图片加入项目资源
-
把cat.png放到项目,属性设置:生成操作 = 资源
-
XAML直接写按钮:
② C#代码动态加载本地动物图片
var uri = new Uri(@"C:\Pics\cat.png", UriKind.Absolute);
imgIcon.Source = new BitmapImage(uri);
封装成通用图文Button模板(推荐复用)
<Window.Resources>
<Style x:Key="IconButtonStyle" TargetType="Button">
<Setter Property="Width" Value="140"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image x:Name="imgBtn" Width="22" Height="22"/>
<TextBlock x:Name="txtBtn" Margin="6,0" VerticalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Button Style="{StaticResource IconButtonStyle}" x:Name="btnAnimal"/>
重要坑点
- Win10 1903+ :很多系统图标迁移到
shell32.dll.mun,ExtractIconEx读取mun会失败,优先用Segoe字体图标更稳。 - 不要混用
System.Drawing.Icon长期持有,WPF用Imaging.CreateBitmapSourceFromHIcon并且必须DestroyIcon释放句柄,否则内存泄漏。 - 32位程序在64位系统会被重定向到SysWOW64,读取imageres.dll会拿到旧版本图标,项目平台设为x64。
- 动物头像:Windows没有内置动物图标,只能自己准备PNG图片。
扩展:获取系统内置标准图标(Error/Warning/Info)
// 需要引用 System.Drawing.Common
using System.Drawing;
public static BitmapSource GetSysIcon(System.Drawing.Icon icon)
{
return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
// 调用
imgIcon.Source = GetSysIcon(SystemIcons.Warning);
.NET6+ WPF需要手动NuGet安装
System.Drawing.Common
需要我给你一份Segoe MDL2常用图标清单,或者写一个弹窗预览imageres全部图标吗?