【发布时间】:2020-04-23 09:57:07
【问题描述】:
我的目标:
将HIMAGELIST 中的所有Window Icon Handle(HICON) 保存为多个图像文件(.png 或.tiff)。
我的问题:
在我的保存过程之后,有些图像质量很差,但有些则不然。
我只在带有子文件夹/子文件的文件夹的图像上注意到了这个问题。
我的尝试:
代码背景:
- 我正在使用
Vanara来帮助我处理 PInvoke 呼叫等等。 -
HIMAGELIST来自ListView,使用ListViewMessage:LVM_GETIMAGELIST。 - 此方法是 Shell 扩展的一部分(我知道,我不应该这样做)。
private void Saving()
{
var hWnd = GetListViewHWnd(); // This is the Desktop SysListView32 HWND
IntPtr lParam = IntPtr.Zero;
IntPtr pHil = SendMessage(hWnd, ListViewMessage.LVM_GETIMAGELIST, 0, ref lParam);
var sHil = new SafeHIMAGELIST(pHil); // This is the IMAGELIST of the ListView
var imageCount = sHil.Interface.GetImageCount(); // sHil.Interface == IImageList Interface
for (int i = 0; i < imageCount; i++)
{
using (var fs = File.OpenWrite(@"C:\Users\Julien\Desktop\Icons\" + i + ".tiff"))
{
using (SafeHICON sHIcon = sHil.Interface.GetIcon(i, IMAGELISTDRAWFLAGS.ILD_NORMAL))
{
var bmpS = Imaging.CreateBitmapSourceFromHIcon(
sHIcon.DangerousGetHandle(),
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
BitmapEncoder enc = new TiffBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bmpS));
enc.Save(fs);
}
}
}
sHil.Dispose();
}
还有:
var bmp = Bitmap.FromHicon(sHIcon.DangerousGetHandle());
bmp.Save(fs);
常见问题解答:
为什么我使用 listview imagelist 而不是 SHGetFileInfo ?
因为SHGetFileInfo 会给我一个HICON 这样的:
对于实际上看起来像这样的文件夹:
在你的SHGetFileInfo 中传递SHGFI_SYSICONINDEX 怎么样?
同样的,非空文件夹的图标不存储在系统图像列表中。
因为我可以用 C++ 编写我的扩展,所以我也愿意接受任何用 C++ 编写的解决方案。
编辑:
我尝试使用IImageList.Draw() 绘制那些有故障的图像,它似乎有效。很明显,问题出在我如何从HICON 创建图像。
var hdc = GetDC(notepadHWnd);
var dp = new IMAGELISTDRAWPARAMS(
hdc,
new RECT(73, 73, 73, 73), 12,
COLORREF.None,
IMAGELISTDRAWFLAGS.ILD_NORMAL);
sHil.Interface.Draw(dp);
【问题讨论】:
-
您应该使用
IShellItemImageFactory来获取这些图标,而不是在另一个进程中为私有数据而卑躬屈膝。 -
真是巧合,我只是使用
IShellItemImageFactory和SHCreateItemFromIDList完成的。问题是,这些动态文件夹图标被视为Thumbnails而不是Icons。 “SIIGBF_THUMBNAILONLY”。我可以将我的扩展程序扔进垃圾桶,但你知道,卑躬屈膝总是很有趣:) 我会发布一个解决方案,除非之前有人处理过。 -
@JonathanPotter
IShellItemImageFactory.GetImage()适用于Thumbnails但不适用于带有 UAC 防护罩的"icons"。它返回一个没有图标。我知道图标覆盖,但 UAC 盾不是其中之一。