如何在shell命名空间中获取对象的shell映像索引?

时间:2014-08-17 19:52:54

标签: shell delphi

我想获取shell命名空间中对象的系统映像列表中的索引。

如果此对象是文件,我可以使用SHGetFileInfo

function GetFileImageIndex(const Filename: string): Integer;
var
   sfi: TSHFileInfo;
begin
   SHGetFileInfo(PChar(Filename), FILE_ATTRIBUTE_NORMAL, sfi, SizeOf(sfi), 
         SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX);
   Result := sfi.iIcon;
end;

除非我没有文件

我所拥有的东西并不作为文件夹或文件存在于硬盘上,例如:

  • Control Panel
  • Homegroup
  • Network

但是我仍然需要在与此事件相对应的图标的系统图像列表中获取索引。我从SHGetFileInfo开始(因为它支持pidls)。但那分崩离析。然后我尝试使用IExtractIcon,但那分崩离析:

function GetObjectImageIndex(ParentFolder: IShellFolder; const ChildPidl: PItemIDList): Integer;
//var
//  sfi: TSHFileInfo;

//  extractIcon: IExtractIcon;
//  iconFile: WideString;
//  iconIndexInFile: Integer;
//  flags: Cardinal;
begin
    {
        This function is the shell namespace equivalent of GetFileImageIndex helper function.
    }
(*
    Won't work (MSDN: "The PIDL must be a fully qualified PIDL. Relative PIDLs are not allowed.")
    SHGetFileInfo(PWideChar(ChildPidl), FILE_ATTRIBUTE_NORMAL,
            sfi, SizeOf(sfi),
            SHGFI_PIDL or SHGFI_SYSICONINDEX);
*)

(*
    Won't work. Doesn't return an index into the system imagelist
    ParentFolder.GetUIObjectOf(0, 1, ChildPidl, IExtractIcon, nil, {out}extractIcon);
    SetLength(iconFile, MAX_PATH);
    extractIcon.GetIconLocation(0, PWideChar(iconFile), Length(iconFile), iconIndexInFile, {out}flags);
*)

    Result := -1; //TODO: Figure out how to do it.
end;

如果该文件夹中有IShellFolderpidl,我该如何获取该系统的系统图像列表中的图标?

2 个答案:

答案 0 :(得分:0)

简单的答案是您将标识对象的绝对PIDL传递给SHGetFileInfo。你说你试过没有成功,但这是解决问题的方法。

你应该回到SHGetFileInfo并让它发挥作用。看起来你已经拥有相对PIDL并停止了。使用ILCombine创建一个绝对PIDL,你应该回家。

如果您没有包含IShellFolder的PIDL,那么您需要阅读此主题:How to obtain the PIDL of an IShellFolder

答案 1 :(得分:0)

function CreateGlobalChildIDList(AParentFolder: IShellFolder; const AChildIDList: PItemIDList): PItemIDList; forward;

function GetObjectImageIndex(AParentFolder: IShellFolder; const AChildIDList: PItemIDList): Integer;
var
  ShellIcon: IShellIcon;
  ChildIDList: PItemIDList;
  FileInfo: TSHFileInfo;
begin
  try
    Result := -1;
    try
      OleCheck(AParentFolder.QueryInterface(IShellIcon, ShellIcon));
      try
        OleCheck(ShellIcon.GetIconOf(AChildIDList, GIL_FORSHELL, Result));
      finally
        ShellIcon := nil;
      end;
    except
      Result := -1;
    end;

    if Result = -1 then
      begin
        ChildIDList := CreateGlobalChildIDList(AParentFolder, AChildIDList);
        try
          ZeroMemory(@FileInfo, SizeOf(FileInfo));
          SHGetFileInfo(PWideChar(ChildIDList), FILE_ATTRIBUTE_NORMAL, FileInfo, SizeOf(FileInfo), SHGFI_PIDL or SHGFI_SYSICONINDEX);
          Result := FileInfo.iIcon;
        finally
          CoTaskMemFree(ChildIDList);
        end;
      end;
  except
    Result := -1;
  end;
end;

  function CretaeGlobalChildIDList(AParentFolder: IShellFolder; const AChildIDList: PItemIDList): PItemIDList;
  var
    PersistFolder2: IPersistFolder2;
    PersistIDList: IPersistIDList;
    ParentIDList: PItemIDList;
  begin
    if Succeeded(AParentFolder.QueryInterface(IPersistFolder2, PersistFolder2)) then
      try
        OleCheck(PersistFolder2.GetCurFolder(ParentIDList));
        try
          Result := ILCombine(ParentIDList, AChildIDList);
        finally
          CoTaskMemFree(ParentIDList);
        end;
      finally
        PersistFolder2 := nil;
      end
    else
      if Succeeded(AParentFolder.QueryInterface(IPersistIDList, PersistIDList)) then
        try
          OleCheck(PersistIDList.GetIDList(ParentIDList));
          try
            Result := ILCombine(ParentIDList, AChildIDList);
          finally
            CoTaskMemFree(ParentIDList);
          end;
        finally
          PersistIDList := nil;
        end
      else
        raise Exception.Create('Cannot create PIDL');
  end;