在我的代码中,我通过函数SHGETImageList得到一个图像列表,大小为SHIL_JUMBO。
IImageList iml;
var hres = SHGetImageList(SHIL_JUMBO, ref iidImageList, out iml);
IntPtr hIcon = IntPtr.Zero;
iml.GetIcon(i, ILD_TRANSPARENT | ILD_IMAGE, ref hIcon);
Icon ico = (Icon)System.Drawing.Icon.FromHandle(hIcon).Clone();
ShellAPI.DestroyIcon(hIcon);
一切都很好,但是当它必须得到更小的图标(当它们的大小不是256x256时),GetIcon函数会返回一个大小为256x256的图标,但左上角的图标大小为32x32 。我想将此图标调整为新大小(256 x 256)。
我没有任何关于如何让系统将我的图标大小调整为256 x 256的信息。对于这个大小,iml中的每个函数(如GetImageInfo,GetImageRect)都会返回一个空结构。
可以获得此图标较小的信息,我可以从其他来源获取图标。
答案 0 :(得分:2)
看起来,自Vista以来,微软希望开发人员依赖IShellItem
和IShellItemImageFactory
接口。与IImageList
系统映像列表的实现不同(大多数方法都失败了E_NOTIMPL
,未报告图标大小),IShellItemImageFactory
生成的图像与在资源管理器中显示的图像完全相同。如果以“巨型”大小请求小图标,它们将居中并被边框包围(至少在Windows 7上)。虽然使用它比IImageList
效率更低,内存消耗更多,但资源管理器也可能使用它,所以这没什么大不了的。
有关详细信息,请参阅MSDN上的IShellItemImageFactory::GetImage method。
.NET有一个支持这些接口的库:Windows® API Code Pack for Microsoft® .NET Framework。
虽然这并没有完全回答你的问题(仍然没有可靠的方法来确定图标的大小),我认为将一个小的32x32图标调整为256x256是一个坏主意,而且Explorer方式(仅调整大小为48x48,然后居中)应该优先考虑。这也将提供一致的行为,这是一个好主意。
考虑到这样的问题已在很多地方发布,多年来都没有得到解答,我担心只能通过逆向工程Windows Shell获得更多信息,特别是标准/默认IShellItemImageFactory::GetImage
实现。 Geoff Chappell对shell进行了相当多的逆向工程,所以也许值得尝试问他......
答案 1 :(得分:0)
您可以执行一些代码来识别图像指标,并在需要时使用以下内容:
var hres = SHGetImageList(SHIL_LARGE, ref iidImageList, out iml);
SHIL_LARGE适用于32x32。
IImageList指针类型,例如ppv参数中返回的指针类型,可以根据需要转换为HIMAGELIST;例如,用于列表视图。相反,HIMAGELIST可以被转换为指向IImageList的指针。 自Windows Vista起,SHIL_SMALL, SHIL_LARGE 和SHIL_EXTRALARGE 缩放,每英寸点数(dpi),如果进程标记为dpi-aware 。要将这些类型设置为dpi-aware,请调用SetProcessDPIAware。无论dpi-aware设置如何,SHIL_JUMBO都固定为256像素。
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762185(v=vs.85).aspx
答案 2 :(得分:-1)
我已经使用
运行了您的示例const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";
在CommonControls.h中定义 运行时:
IEnumerable<int> shils = new int[]{
ShellAPI.SHIL_EXTRALARGE,
ShellAPI.SHIL_JUMBO,
ShellAPI.SHIL_SYSSMALL,
ShellAPI.SHIL_LARGE,
ShellAPI.SHIL_SMALL,
ShellAPI.SHIL_LAST
};
ShellAPI.IImageList ppv = null;
Guid guil = new Guid(IID_IImageList2);//or IID_IImageList
foreach (int iil in shils)
{
ShellAPI.SHGetImageList(iil, ref guil, ref ppv);
int noImages = 0;
ppv.GetImageCount(ref noImages);
//...
}
图像计数保持不变。因此,我必须不同意
当他们没有256x256的大小时
对于每个图像列表类型,都有一定数量的图像,因此不会丢失巨型设置的图标。
我坚持使用所有分辨率(16x16,32x32,48x48,256x256)保存所有找到的图标。 纵横比在相同图标的所有不同尺寸(相同图像列表索引/不同分辨率)之间是相同的。宽高比意味着256x256版本不是粘贴在角落的48x48版本,其余是黑色背景填充。
而且,所有的
图标大小为256x256,但左上角的图标大小为32x32 实际上是覆盖图像,可以检查:
int currentImageListIndex; //loop by noImages above
int idx0Based=0;
ppv.GetOverlayImage(currentImageListIndex+1, ref idx0Based);
使用IImageAList :: GetItemFlags可以轻松找到质量下降,并检查输出dwFlags参数是否为ILIF_LOWQUALITY,下面是msdn引用
Windows Vista及更高版本。表示图像列表中的项目是通过StretchBlt函数生成的,因此图像质量可能会降低