You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WinUI3 C++/WinRT自定义ListView中显示文件扩展名图标

在WinUI3 C++/WinRT中将HICON/BITMAP转换为ListView可用的ImageSource

一、核心转换实现

1. 必要头文件与GDI+初始化

首先确保包含依赖头文件,并在应用启动时初始化GDI+:

#include <winrt/Windows.Graphics.Imaging.h>
#include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")

// 在App构造函数中初始化GDI+
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartupInput startupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &startupInput, nullptr);

// 在App析构函数中释放GDI+
Gdiplus::GdiplusShutdown(gdiplusToken);

2. HICON转ImageSource

winrt::Microsoft::UI::Xaml::Media::Imaging::ImageSource HiconToImageSource(HICON hIcon)
{
    if (!hIcon) return nullptr;

    // 将HICON转为HBITMAP
    ICONINFO iconInfo{};
    if (!GetIconInfo(hIcon, &iconInfo)) return nullptr;
    HBITMAP hBitmap = iconInfo.hbmColor;

    // 通过GDI+处理位图数据
    Gdiplus::Bitmap bitmap(hBitmap, nullptr);
    DeleteObject(hBitmap); // 释放临时HBITMAP

    Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
    Gdiplus::BitmapData bitmapData{};
    if (bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bitmapData) != Gdiplus::Ok)
        return nullptr;

    // 创建WinRT SoftwareBitmap
    auto softwareBitmap = winrt::Windows::Graphics::Imaging::SoftwareBitmap(
        winrt::Windows::Graphics::Imaging::BitmapPixelFormat::Bgra8,
        bitmap.GetWidth(),
        bitmap.GetHeight(),
        winrt::Windows::Graphics::Imaging::BitmapAlphaMode::Premultiplied);

    softwareBitmap.CopyFromBuffer(winrt::Windows::Storage::Streams::Buffer(
        reinterpret_cast<uint8_t*>(bitmapData.Scan0),
        bitmapData.Stride * bitmapData.Height));

    bitmap.UnlockBits(&bitmapData);

    // 转换为可绑定的ImageSource
    auto bitmapSource = winrt::Microsoft::UI::Xaml::Media::Imaging::SoftwareBitmapSource();
    // 异步场景建议用co_await替代.get(),避免阻塞UI线程
    bitmapSource.SetBitmapAsync(softwareBitmap).get();

    return bitmapSource;
}

3. BITMAP转ImageSource

如果已经直接拿到HBITMAP,可跳过HICON转换步骤,直接处理:

winrt::Microsoft::UI::Xaml::Media::Imaging::ImageSource BitmapToImageSource(HBITMAP hBitmap)
{
    if (!hBitmap) return nullptr;

    Gdiplus::Bitmap bitmap(hBitmap, nullptr);
    Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
    Gdiplus::BitmapData bitmapData{};

    if (bitmap.LockBits(&rect, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bitmapData) != Gdiplus::Ok)
        return nullptr;

    auto softwareBitmap = winrt::Windows::Graphics::Imaging::SoftwareBitmap(
        winrt::Windows::Graphics::Imaging::BitmapPixelFormat::Bgra8,
        bitmap.GetWidth(),
        bitmap.GetHeight(),
        winrt::Windows::Graphics::Imaging::BitmapAlphaMode::Premultiplied);

    softwareBitmap.CopyFromBuffer(winrt::Windows::Storage::Streams::Buffer(
        reinterpret_cast<uint8_t*>(bitmapData.Scan0),
        bitmapData.Stride * bitmapData.Height));

    bitmap.UnlockBits(&bitmapData);

    auto bitmapSource = winrt::Microsoft::UI::Xaml::Media::Imaging::SoftwareBitmapSource();
    bitmapSource.SetBitmapAsync(softwareBitmap).get();

    return bitmapSource;
}

二、ListView中绑定显示

1. XAML ItemTemplate定义

给ListView设置包含Image和文本的模板:

<ListView x:Name="FileListView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Height="32">
                <Image Source="{Binding FileIcon}" Width="24" Height="24" Margin="4"/>
                <TextBlock Text="{Binding FileName}" VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

2. 数据模型与绑定

定义数据模型类存储文件名和图标:

namespace winrt::YourAppNamespace::implementation
{
    struct FileItem : FileItemT<FileItem>
    {
        winrt::hstring FileName() { return m_fileName; }
        void FileName(winrt::hstring const& value) { m_fileName = value; }

        winrt::Microsoft::UI::Xaml::Media::Imaging::ImageSource FileIcon() { return m_fileIcon; }
        void FileIcon(winrt::Microsoft::UI::Xaml::Media::Imaging::ImageSource const& value) { m_fileIcon = value; }

    private:
        winrt::hstring m_fileName;
        winrt::Microsoft::UI::Xaml::Media::Imaging::ImageSource m_fileIcon;
    };
}

3. 填充ListView数据

在代码中生成数据项并添加到ListView:

// 示例:获取文件图标后转换并绑定
HICON hFileIcon = /* 你的HICON获取逻辑 */;
auto fileItem = winrt::make<winrt::YourAppNamespace::implementation::FileItem>();
fileItem.FileName(L"demo.pdf");
fileItem.FileIcon(HiconToImageSource(hFileIcon));

FileListView.Items().Append(fileItem);

注意事项

  • 异步场景下,将.get()替换为co_await,避免阻塞UI线程。
  • HICON资源由调用者负责释放,转换过程中生成的临时HBITMAP已通过DeleteObject释放。
  • 确保像素格式统一为Bgra8,这是WinUI3 ImageSource的兼容格式。

内容的提问来源于stack exchange,提问作者Claudiu HBann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 15:54:42