C# WPF 按钮加载系统图标 / 动物头像

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="&#xE78B;" Foreground="Black"/>
        <TextBlock Text=" 文件夹" VerticalAlignment="Center"/>
    </StackPanel>
</Button>

常用glyph:

  • &#xE78B; 文件夹
  • &#xE700; 主页
  • &#xE71D; 警告
  • &#xE72E; 信息

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:动物头像(本地图片/项目资源)

① 把图片加入项目资源

  1. 把cat.png放到项目,属性设置:生成操作 = 资源

  2. 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"/>

重要坑点

  1. Win10 1903+ :很多系统图标迁移到 shell32.dll.mun,ExtractIconEx读取mun会失败,优先用Segoe字体图标更稳。
  2. 不要混用System.Drawing.Icon长期持有,WPF用Imaging.CreateBitmapSourceFromHIcon并且必须DestroyIcon释放句柄,否则内存泄漏。
  3. 32位程序在64位系统会被重定向到SysWOW64,读取imageres.dll会拿到旧版本图标,项目平台设为x64。
  4. 动物头像: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全部图标吗?

相关推荐
军训猫猫头1 小时前
C# 封装 MySQL 自动写入与查询工具类(基于 MySqlConnector)
mysql·c#·.net·wpf
zxy284722530112 小时前
C# 音频倍速播放
c#·音频·naudio·soundtouch·倍速
Water_Sunzhipeng15 小时前
HandyControl Demo 设置特定框架记录
c#
czhc114007566316 小时前
插补、另存为、标记过滤、采集超时——今天聊的四件事
c#
小羊没烦恼!17 小时前
Memory 记忆设计讨论:Agent Memory 的数据模型可以怎么设计
java·开发语言·前端·c++·c#
小羊没烦恼!20 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
...62221 小时前
C# 中 Lambda 表达式的全面讲解
c#
...6221 天前
WinForm中Socket通信服务端客户端代码实现讲解
tcp/ip·c#·socket
小羊没烦恼!1 天前
Memory 记忆设计讨论:Agent Memory 的安全边界:权限、删除、版本与回执
java·大数据·word·powerpoint·.net