如何在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
相关产品推荐
相关产品推荐

