delphi 使用SHGetFileInfo函数获取任何文件大图标(修复长时间运行报错问题)

uses
    ShellAPI, CommCtrl;


function GetFileICO(AFile: string; AWidth, AHeight: Integer): TBitmap;
   function GetFileIconEX(AFile: string; ASHIL_FLAG: Cardinal): HICON;
      function _X: Boolean; {判断是否符合系统版本}
      begin
         Result := False;
         if Win32MajorVersion < 5 then
            Exit;
         if (Win32MajorVersion = 5) and (Win32MinorVersion < 1) then
            Exit;
         Result := True;
      end;
   type
      _SHGetImageList = function(iImageList: Integer; const riid: TGUID; var ppvObj: Pointer): HResult; stdcall;
   var
      nHandle: THandle;
      nImageList: HIMAGELIST;
      nSHGetImageList: _SHGetImageList;
      nFileInfo: TSHFileInfo;
   const
      IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}';
   begin
      Result := 0;
      nHandle := LoadLibrary('Shell32.dll');
      nImageList := 0;
      if nHandle <> S_OK then
      try
         nSHGetImageList := GetProcAddress(nHandle, PChar(727));
         if Assigned(nSHGetImageList) and _X then
            nSHGetImageList(ASHIL_FLAG, IID_IImageList, Pointer(nImageList));

         if nImageList > 0 then
         begin
            SHGetFileInfo(PChar(AFile), FILE_ATTRIBUTE_NORMAL, nFileInfo, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX);
            Result := ImageList_GetIcon(nImageList, nFileInfo.iIcon, ILD_NORMAL); //?????
         end;
      finally
         FreeLibrary(nHandle);
      end;
   end;
   function IcoToBmp(Icon: TIcon; ASHIL_FLAG: Cardinal): TBitmap;
   begin
      Result := TBitmap.Create;
      with Result do
      begin
         case ASHIL_FLAG of
            0:
               Width := 32;
            1:
               Width := 16;
            2:
               Width := 48;
            3:
               Width := 16;
            4:
               Width := 256;
         end;
         case ASHIL_FLAG of
            0:
               Height := 32;
            1:
               Height := 16;
            2:
               Height := 48;
            3:
               Height := 16;
            4:
               Height := 256;
         end;
         Canvas.Lock;
         Canvas.StretchDraw(Rect(0, 0, Width, Height), Icon);
         Canvas.Unlock;
      end;
   end;
   function BMPCenter(bmpSrc: TBitmap): TBitmap;
   begin
      Result := TBitMap.Create;
      Result.Width := AWidth;
      Result.Height := AHeight;
      Result.Canvas.Lock;
      Result.Canvas.Draw((AWidth - bmpSrc.Width) div 2, (AHeight - bmpSrc.Height) div 2, bmpSrc);
      Result.Canvas.Unlock;      
   end;

const
   SHIL_LARGE = 0; {32x32}
   SHIL_SMALL = 1; {16x16} //小图标
   SHIL_EXTRALARGE = 2; {48x48} //中图标
   SHIL_SYSSMALL = 3; {16x16}
   SHIL_JUMBO = 4; {256x256}
var
   ico: HIcon;
   ico2: TIcon;
   IconInfo: _ICONINFO;
   b: Boolean;
   i: Integer;
   bmp: TBitmap;
begin
   Result := nil;

   if (AWidth <= 16) or (AHeight <= 16) then
      i := SHIL_SMALL
   else if (AWidth <= 32) or (AHeight <= 32) then
      i := SHIL_LARGE
   else if (AWidth <= 48) or (AHeight <= 48) then
      i := SHIL_EXTRALARGE
   else if (AWidth < 256) or (AHeight < 256) then
      i := SHIL_EXTRALARGE
   else
      i := SHIL_EXTRALARGE; //SHIL_JUMBO; 256大图有些图标获取不到,暂时使用SHIL_EXTRALARGE吧
   try
      ico := GetFileIconEX(AFile, i);
      if ico = 0 then
         Exit;
      try
         b := GetIconInfo(ico, IconInfo);
         if b then
         begin
            ico2 := TIcon.Create;
            try
               ico2.Handle := CreateIconIndirect(IconInfo);
               bmp := IcoToBmp(ico2, i); 
               try
                  Result := BMPCenter(bmp);
               finally
                  FreeAndNil(bmp);
               end;
            finally
               FreeAndNil(ico2);
            end;
         end;
         DeleteObject(IconInfo.hbmMask); //网上的其它文章这里没有释放
         DeleteObject(IconInfo.hbmColor); //网上的其它文章这里没有释放
      finally
         DestroyIcon(ico); //网上的其它文章这里没有释放
      end;
   except
      on e: Exception do
      begin
      end;
   end;
end;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值