可以从Vista Shell获得48x48或64x64图标吗?

时间:2009-11-09 19:25:11

标签: delphi

如果Vista Shell中存在48x48或64x64图标,您如何使用SHGetFileInfo获取在TImage中显示一个图标的句柄?

我想从图像列表中选择一个代表文件夹路径的图标,并在Timage中显示48x48或64x64图标。

// load the large system image for the current path into Image1
SHGetFileInfo( PChar( CurrentPath ), FILE_ATTRIBUTE_NORMAL, SFI,
             SizeOf( TSHFileInfo ), SHGFI_ICON or SHGFI_LARGEICON or SHGFI_SHELLICONSIZE or
             SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_DISPLAYNAME );
AImageIndex := SFI.iIcon;
ImageList2.GetBitmap( AImageIndex, Image1.Picture.Bitmap );

比尔

4 个答案:

答案 0 :(得分:22)

您必须使用SHGetImageList功能,以获取带有较大图标的图像列表。

这里有一个delphi的例子

uses ShellApi, Commctrl, ShlObj;

const
  SHIL_LARGE     = $00;  //The image size is normally 32x32 pixels. However, if the Use large icons option is selected from the Effects section of the Appearance tab in Display Properties, the image is 48x48 pixels.
  SHIL_SMALL     = $01;  //These images are the Shell standard small icon size of 16x16, but the size can be customized by the user.
  SHIL_EXTRALARGE= $02;  //These images are the Shell standard extra-large icon size. This is typically 48x48, but the size can be customized by the user.
  SHIL_SYSSMALL  = $03;  //These images are the size specified by GetSystemMetrics called with SM_CXSMICON and GetSystemMetrics called with SM_CYSMICON.
  SHIL_JUMBO     = $04;  //Windows Vista and later. The image is normally 256x256 pixels.
  IID_IImageList: TGUID= '{46EB5926-582E-4017-9FDF-E8998DAA0950}';

function GetImageListSH(SHIL_FLAG:Cardinal): HIMAGELIST;
type
  _SHGetImageList = function (iImageList: integer; const riid: TGUID; var ppv: Pointer): hResult; stdcall;
var
  Handle        : THandle;
  SHGetImageList: _SHGetImageList;
begin
  Result:= 0;
  Handle:= LoadLibrary('Shell32.dll');
  if Handle<> S_OK then
  try
    SHGetImageList:= GetProcAddress(Handle, PChar(727));
    if Assigned(SHGetImageList) and (Win32Platform = VER_PLATFORM_WIN32_NT) then
      SHGetImageList(SHIL_FLAG, IID_IImageList, Pointer(Result));
  finally
    FreeLibrary(Handle);
  end;
end;


Procedure GetIconFromFile(aFile:String; var aIcon : TIcon;SHIL_FLAG:Cardinal);
var
  aImgList    : HIMAGELIST;
  SFI         : TSHFileInfo;
Begin
    //Get the index of the imagelist
    SHGetFileInfo(PChar(aFile), FILE_ATTRIBUTE_NORMAL, SFI,
                 SizeOf( TSHFileInfo ), SHGFI_ICON or SHGFI_LARGEICON or SHGFI_SHELLICONSIZE or
                 SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_DISPLAYNAME );

    if not Assigned(aIcon) then
    aIcon:= TIcon.Create;
    //get the imagelist
    aImgList:= GetImageListSH(SHIL_FLAG);
    //extract the icon handle
    aIcon.Handle:= ImageList_GetIcon(aImgList, Pred(ImageList_GetImageCount(aImgList)), ILD_NORMAL);
End;

您可以这样使用这些功能

var
 hicon :TIcon;
begin
    hicon:= TIcon.Create;
    try
     GetIconFromFile('C:\Tools\reflector\readme.htm',hicon,SHIL_JUMBO);
     Image1.Picture.Icon.Assign(hIcon); //assign to timage
    finally
     hIcon.Free;
    end;
end;

答案 1 :(得分:6)

阅读here:(C ++中的代码)

  

打开16×16和32×32图标   Windows相对容易而且是   通常就像打电话一样简单   ExtractIconEx。

     

然而,获得额外的大   (48×48)和巨型(256×256)图标   分别由XP和   Vista稍微复杂一点。这是   通常由:

完成      
      
  1. 获取文件信息,特别是图标索引   给定文件使用SHGetFileInfo
  2.   
  3. 检索存储所有图标的系统图像列表
  4.   
  5. 将图像列表转换为IImageList接口并获取   那里的图标
  6.   

答案 2 :(得分:4)

我们发现该文件的索引不正确,因为在测试RRUZ发布的代码时显示了错误的图标。 GetIconFromFile方法是根据图像计数设置索引。我们将GetIconFromFile更改为使用SFI索引(aIndex:= SFI.iIcon)并获取了正确的图标。显然,shellimagelist不断变化,因此索引不正确。

感谢所有人的协助。这似乎是一段非常好的代码。

procedure GetIconFromFile( aFile: string; var aIcon: TIcon;SHIL_FLAG: Cardinal );
var
  aImgList: HIMAGELIST;
  SFI: TSHFileInfo;
  aIndex: integer;
begin // Get the index of the imagelist
  SHGetFileInfo( PChar( aFile ), FILE_ATTRIBUTE_NORMAL, SFI, SizeOf( TSHFileInfo ),
    SHGFI_ICON or SHGFI_LARGEICON or SHGFI_SHELLICONSIZE or SHGFI_SYSICONINDEX or SHGFI_TYPENAME or SHGFI_DISPLAYNAME );
  if not Assigned( aIcon ) then
    aIcon := TIcon.Create;
  // get the imagelist
  aImgList := GetImageListSH( SHIL_FLAG );
  // get index
  //aIndex := Pred( ImageList_GetImageCount( aImgList ) );
  aIndex := SFI.iIcon;
  // extract the icon handle
  aIcon.Handle := ImageList_GetIcon( aImgList, aIndex, ILD_NORMAL );
end;

答案 3 :(得分:1)

kicon

我使用适当的kicon方法( LoadFromFile / LoadFromModule / LoadFromModuleByIndex ),具体取决于源文件类型。

如果这些方法失败,我使用PrivateExtractIconsA

  

function PrivateExtractIcons(lpszFile:PChar; nIconIndex,cxIcon,cyIcon:integer; phicon:PHandle; piconid:PDWORD; nIcons,flags:DWORD):DWORD; STDCALL;外部'user32.dll'名称'PrivateExtractIconsA';

并将生成的句柄传递给kicon的 LoadFromHandle 方法。

一旦加载到kicon,迭代icondata []数组以选择你想要的大小。 kicon有将返回的图像转换为PNG的方法。