SHGetImageList - SHIL_JUMBO 用于较小的图标 (32,32)
在我的代码中,我通过函数 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);
一切都很好,但是当它必须获得较小的图标时(当它们没有 256×256 的尺寸时),函数 GetIcon
返回一个尺寸为 256×256 的图标,但带有左上角大小为 32×32 的图标。我想将此图标调整为新尺寸(256×256)。
我没有任何信息如何让系统将我的图标大小调整为 256×256。 iml
中针对此大小的每个函数(例如 GetImageInfo
、GetImageRect
)都会返回一个空结构。
是否可以获得该图标较小的信息,并且我可以从其他来源获取图标吗?
In my code I get a list of images through the function SHGETImageList
with size 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);
Everything is ok, but when it has to get smaller icons (when they don't have a size for 256×256) the function GetIcon
returns me an icon with the size of 256×256 but with the icon of size 32×32 in top left corner. I want to resize this icon to the new size (256×256).
I don't have any information how to have the system resize my icon to 256×256. Every function in iml
(like GetImageInfo
, GetImageRect
) for this size returns an empty structure.
Is it possible to get information that this icon is smaller and can I get icon from another source?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看起来,从 Vista 开始,微软希望开发人员依赖
IShellItem
和IShellItemImageFactory
接口。与系统图像列表的IImageList
实现不同,该实现严重损坏(大多数方法因E_NOTIMPL
失败,不报告图标大小),IShellItemImageFactory
生成图像与资源管理器中显示的完全一样。如果需要“巨型”尺寸的小图标,它们会居中并被边框包围(至少在 Windows 7 上)。虽然与IImageList
相比,它的使用效率较低且消耗更多内存,但 Explorer 可能也会使用它,因此这没什么大不了的。请参阅 IShellItemImageFactory::GetImage 方法 在 Microsoft 文档中了解更多详细信息。
有一个 .NET 库支持这些接口: 适用于 Microsoft® .NET Framework 的 Windows® API 代码包。
虽然这并不能完全回答你的问题(仍然没有可靠的方法来确定图标的大小),但我认为将小 32x32 图标调整为 256x256 是一个坏主意,而资源管理器方式(仅调整大小到 48x48,然后居中)应该被优先考虑。这也将提供一致的行为,这是一个好主意。
考虑到类似的问题已经在很多地方发布,而且多年来都没有得到解答,恐怕只能通过对 Windows Shell 进行逆向工程来获取更多信息,特别是标准/默认的
IShellItemImageFactory::GetImage< /代码>实施。 Geoff Chappell 做了相当多的 shell 逆向工程,所以也许值得尝试问他......
Looks like, since Vista, Microsoft expects developers to rely on
IShellItem
andIShellItemImageFactory
interfaces. UnlikeIImageList
implementation of the system image lists, which is badly broken (most methods fail withE_NOTIMPL
, icon sizes are not reported),IShellItemImageFactory
produces images exactly like they are displayed in Explorer. In case of small icons requested in "jumbo" size, they are centered and surrounded by a border (on Windows 7, at least). While it is less efficient and more memory consuming to use thanIImageList
, Explorer probably uses it too, so it's no big deal.See IShellItemImageFactory::GetImage method in Microsoft documentation for more details.
There's a library for .NET which supports these interfaces: Windows® API Code Pack for Microsoft® .NET Framework.
While this doesn't exactly answer your question (there's still no reliable way to determine size of icons), I think resizing a small 32x32 icon to 256x256 is a bad idea, and Explorer way (resizing only up to 48x48, then centering) should be preferred. This will also provide a consistent behavior which is a good idea.
Considering questions like this have been posted in many places, and none have been answered for years, I'm afraid more information can only be obtained by reverse-engineering Windows Shell, and in particular standard/default
IShellItemImageFactory::GetImage
implementation. Geoff Chappell did quite a bit of reverse engineering of shell, so maybe it's worth trying to ask him...您可以执行一些代码来识别图像指标,并在需要时使用以下代码:
var hres = SHGetImageList(SHIL_LARGE, ref iidImageList, out iml);
SHIL_LARGE 适用于 32x32。
IImageList 指针类型,例如 ppv 参数中返回的指针类型,可以根据需要转换为 HIMAGELIST;例如,用于列表视图。相反,HIMAGELIST 可以转换为指向 IImageList 的指针。
从 Windows Vista 开始,如果进程被标记为支持 dpi,则 SHIL_SMALL、SHIL_LARGE 和 SHIL_EXTRALARGE 按每英寸点数 (dpi) 缩放。要将这些类型设置为 dpi 感知,请调用 SetProcessDPIAware。无论 dpi 感知设置如何,SHIL_JUMBO 都固定为 256 像素。
http://msdn.microsoft。 com/en-us/library/windows/desktop/bb762185(v=vs.85).aspx
You could execute some code to identify the image metrics and use the following when required:
var hres = SHGetImageList(SHIL_LARGE, ref iidImageList, out iml);
SHIL_LARGE is for 32x32.
The IImageList pointer type, such as that returned in the ppv parameter, can be cast as an HIMAGELIST as needed; for example, for use in a list view. Conversely, an HIMAGELIST can be cast as a pointer to an IImageList.
As of Windows Vista, SHIL_SMALL, SHIL_LARGE, and SHIL_EXTRALARGE scale with dots per inch (dpi) if the process is marked as dpi-aware. To set these types to be dpi-aware, call SetProcessDPIAware. SHIL_JUMBO is fixed at 256 pixels regardless of the dpi-aware setting.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762185(v=vs.85).aspx
我已经使用
CommonControls.h 中定义 的来运行您的示例
运行时:
图像计数保持不变。因此我必须不同意
对于每种图像列表类型,都有固定数量的图像,因此巨型设置不会缺少图标。
我保留了所有找到的所有分辨率的图标(16x16、32x32、48x48、256x256)。
同一图标的所有不同尺寸(相同图像列表索引/不同分辨率)之间的长宽比相同。长宽比意味着256x256版本不是粘贴在角落的48x48版本,其余黑色背景填充。
而且,所有的
使用 IImageAList::GetItemFlags 并检查输出 dwFlags 参数的 ILIF_LOWQUALITY 可以轻松找出质量下降情况,下面引用 msdn
I have run your example using
defined in CommonControls.h
Upon running:
the images count stays constant. Therefore I must disagree with
For every image list type there's a constant number of images, so no icons missing for the jumbo setting.
I have persisted all found icons with all resolutions (16x16,32x32,48x48,256x256).
The aspect ratio is identical between all different sizes of the same icon (same image list index/different resolution). Aspect ratio means that the 256x256 version is not the 48x48 version pasted in a corner, and the rest black background padding.
Moreover, all the
Quality degradation can be easily found out using IImageAList::GetItemFlags and checking the output dwFlags parameter for ILIF_LOWQUALITY, msdn quote below