如何获取Windows中任何文件的关联图标(.ICO)并在Delphi中显示所有图标图像大小?

时间:2013-02-27 02:54:05

标签: delphi file icons

我想要一个在Windows中占用任何文件路径的函数(任何文件系统对象 - 文件,文件夹,驱动器,快捷方式等),并返回相关的.ICO文件(或带有所有图像的图标的某个句柄)大小表示)。例如,如果我在Windows 7中指定了“C:\ MyTextFile.txt”,我将获得位于imageres中的.ICO文件中的.txt文件的所有256x256,48x48,32x32和16x16表示。偏移102处的dll:

Text file icon in imageres.dll

^ Stardock IconPackager安装的Icon选项卡,用于查找文件系统对象的图标

到目前为止,我的研究似乎并不那么容易。有ExtractIconEx函数,但它只提供16和32px表示。还有this post,其中显示了如何获取SHIL_SMALLSHIL_LARGESHIL_EXTRALARGESHIL_JUMBO尺寸,一般为16,32,48和256分别是像素。但是,这不一定涵盖将存储在.ICO文件中的其他大小。例如,一些图标存储10个或更多不同的大小而不是仅存储4个。

所以,我正在尝试:

  1. 找到文件系统对象图标的位置,
  2. 从DLL,EXE或任何封装它的资源中检索它。
  3. 我猜一个问题是:这是Windows注册表的任务吗?如下所示,注册表的txtfile-> DefaultIcon值包含.txt文件类型的图标位置。

    txtfile in Windows registry

    但是,还有一些独立的.exe文件,例如,它们自包含一个不会存储在注册表中的图标。

    最终,我想在TImage中显示所有不同的大小,并可能将它们一起输出到.ICO文件中。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:4)

作为选项,有一个IShellItemImageFactory界面,提供有关IShellItem(文件)缩略图的信息。这个界面可以返回所需的大小,但它需要一些神奇的图标透明度。有2个选项 - 缩略图或图标。对于Folder,它始终返回相同的图像(更新:不是真的,文件夹缩略图还包含文件的小预览,包含)。但是例如对于png,它返回带有thumbnail标志的小预览图像和带有icon标志的png-image-icon(默认值为0)。对于您的任务,您应该使用SIIGBF_ICONONLY标志来获取文件/文件夹/驱动器系统图标。

以下是示例代码,它会加载不同大小的图像。

type
    TIconSize = (is16, is32, is48, is64, is96, is128, is256);
const
    ICON_SIZE : array[TIconSize] of integer = (16,32,48,64,96,128,256);

我在表单上添加了SizeRadioGroup : TRadioGroupImage1 : TImageImage1.Size设置为256. SizeRadioGroup点击事件hanlder将缩略图加载到Image1

procedure TForm7.SizeRadioGroupClick(Sender: TObject);
const FILE_NAME = 'd:\_projects\';
var icoSize : TIconSize;
    wh : integer;
    siif : IShellItemImageFactory;
    size : TSize;
    icon_handle : HBitmap;
    bm : TBitmap;
begin
    icoSize := TIconSize(SizeRadioGroup.ItemIndex);
    wh := ICON_SIZE[icoSize];

    SHCreateItemFromParsingName(FILE_NAME, nil, IID_IShellItemImageFactory, siif);

    size.cx := wh;
    size.cy := wh;

    siif.GetImage(size, 0 {SIIGBF_THUMBNAILONLY}{SIIGBF_ICONONLY}, icon_handle);
    bm := TBitmap.Create();
    bm.PixelFormat := pf32bit;
    try
        bm.Handle := icon_handle;
        Image1.Picture.Assign(bm);
    finally
        bm.Free();
    end;
end;