SHGetImageList - SHIL_JUMBO 用于较小的图标 (32,32)

发布于 2024-11-17 06:34:28 字数 678 浏览 2 评论 0原文

在我的代码中,我通过函数 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 中针对此大小的每个函数(例如 GetImageInfoGetImageRect)都会返回一个空结构。

是否可以获得该图标较小的信息,并且我可以从其他来源获取图标吗?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋凉 2024-11-24 06:34:28

看起来,从 Vista 开始,微软希望开发人员依赖 IShellItemIShellItemImageFactory 接口。与系统图像列表的 IImageList 实现不同,该实现严重损坏(大多数方法因 E_NOTIMPL 失败,不报告图标大小),IShellItemImageFactory 生成图像与资源管理器中显示的完全一样。如果需要“巨型”尺寸的小图标,它们会居中并被边框包围(至少在 Windows 7 上)。虽然与 IImageList 相比,它的使用效率较低且消耗更多内存,但 Explorer 可能也会使用它,因此这没什么大不了的。

请参阅 IShellItemImageFactory::GetImage 方法 在 Microsoft 文档中了解更多详细信息。

有一个 .NET 库支持这些接口: 适用于 Microsoft® .NE​​T Framework 的 Windows® API 代码包


虽然这并不能完全回答你的问题(仍然没有可靠的方法来确定图标的大小),但我认为将小 32x32 图标调整为 256x256 是一个坏主意,而资源管理器方式(仅调整大小到 48x48,然后居中)应该被优先考虑。这也将提供一致的行为,这是一个好主意。

考虑到类似的问题已经在很多地方发布,而且多年来都没有得到解答,恐怕只能通过对 Windows Shell 进行逆向工程来获取更多信息,特别是标准/默认的 IShellItemImageFactory::GetImage< /代码>实施。 Geoff Chappell 做了相当多的 shell 逆向工程,所以也许值得尝试问他......

Looks like, since Vista, Microsoft expects developers to rely on IShellItem and IShellItemImageFactory interfaces. Unlike IImageList implementation of the system image lists, which is badly broken (most methods fail with E_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 than IImageList, 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...

反话 2024-11-24 06:34:28

您可以执行一些代码来识别图像指标,并在需要时使用以下代码:

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

<逆流佳人身旁 2024-11-24 06:34:28

我已经使用

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 函数生成的,因此图像质量可能会下降

I have run your example using

const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";

defined in CommonControls.h
Upon running:

        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);
            //...
        }

the images count stays constant. Therefore I must disagree with

when they don't have a size for 256x256

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

icons with the size of 256x256 but with the icon of size 32x32 in top left corner
are in fact overlay images, as one can check:

int currentImageListIndex; //loop by noImages above
int idx0Based=0;
ppv.GetOverlayImage(currentImageListIndex+1, ref idx0Based);

Quality degradation can be easily found out using IImageAList::GetItemFlags and checking the output dwFlags parameter for ILIF_LOWQUALITY, msdn quote below

Windows Vista and later. Indicates that the item in the imagelist was generated via a StretchBlt function, consequently image quality may have degraded

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文