Конференция "WinAPI" » Большие иконки папок и файлов Vista, Win7
 
  • Gu (08.12.10 10:59) [0]
    К вопросу о вытаскивании иконок размером 48х48 и более. Есть чудесный код, многим понравится, он отлично вытаскивает иконки указаного размера у файлов и папок. Вопрос в следующем: когда в проводнике (виста или вин7) в опциях папки отключено "всегда показывать значки а не искизы", то папки, в которых есть рисунки (а также графические файлы) отображаются с рисунками - выглядит так, все видели: http://i041.radikal.ru/1012/3b/2925a25653d6.png

    Вопрос: что нужно добавить в коде, чтобы было как на скрине выше (рисунки в виде эскизов, а папки с рисунками с вложеными миниатюрами). Понимаю, что можно отдельно все вытаскивать, но как быть с отображением папок? Может еще есть какойто ключик (больше чем уверен), который будет иконки в виде эскизов возвращать? Подскажите, пожалуйста.

    вот код модуля

    ----------------------

    unit GetBigIcon;

    interface

    uses ShellApi, Commctrl, ShlObj, Windows, Sysutils, Graphics;

    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}';

    Procedure GetIconFromFile(aFile:String; var aIcon : TIcon; SHIL_FLAG: Cardinal);

    implementation

     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;aIndex: integer;
     Begin
     FillChar(SFI,Sizeof(SFI),#0);
     SHGetFileInfo(PChar(aFile),0, 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;
     aImgList:= GetImageListSH(SHIL_FLAG);
     aIndex := SFI.iIcon;
     aIcon.Handle := ImageList_GetIcon( aImgList, aIndex, ILD_NORMAL );
     End;

    end.



    ----------------------

    Использование (на форме кнопка и image):


    uses getbigicon;
    ...
    procedure TForm1.Button1Click(Sender: TObject);
    var ic:ticon;
    begin
    ic:=ticon.Create;
    GetIconFromFile('c:\windows' {полный путь и имя папки или файла}, ic, SHIL_JUMBO); //SHIL_EXTRALARGE  //SHIL_LARGE
    image1.Picture.Icon:=ic;
    ic.Free;



    P.S. Нашел тут похожий вопрос http://pda.delphimaster.net/?id=1256910300&n=0 , вот, как решение
  • Gu (08.12.10 12:11) [1]
    кстати у меня при работе этого примера выводится "обкушеная папка" (http://i007.radikal.ru/1012/82/861f3aa50299.jpg) :)))

    думал у image1 транспарент вкл, проверил, нет. не пойму, почему такое.
    у все так?

    (вин7, rad 2010)
  • Gu (10.12.10 22:49) [2]
    Блин, ну хоть кто-нить отпишите, плз, с вистой\7 и с rad 2010 - никак обгрызеные папки не могу победить. Значки у файлов (если есть) при помощи юнита выше - отображаются на ура (думал, что чтото с разрешением ико не так - но значки файлов больше по размеру значка папки выводятся норм), а вот с папками беда. Именно при aIndex=1 (иконка с папкой) выводит обкусаный вариант при SHIL_FLAG=SHIL_JUMBO. Попробовал на 2х разных пк - с 7 и 2008 - тоже самое. На буржуйских форумах что-то писали про PNG формат, который может вступать в силу в этот момент при запросе джумбо, но тогда почему только у папковой икошки?

    P.S. пока ковырялся нашел еще одну фичу - при

    aIcon.Handle := ImageList_GetIcon( aImgList, aIndex, ILD_NORMAL);



    это значение может принимать такие (можно затемненные икошки выводить и др, как в проводнике, когда просмотр скрытых файлов включен - они такие..ммм.. полупрозрачненькие)

    {  fStyle
    Drawing style and, optionally, the overlay image. For information about specifying an overlay image index, see the comments section at the end of this topic. This parameter can be a combination of an overlay image index and one or more of the following values:
    ILD_BLEND25,ILD_FOCUS
    Draws the image, blending 25 percent with the system highlight color. This value has no effect if the image list does not contain a mask.
    ILD_BLEND50,ILD_SELECTED,ILD_BLEND
    Draws the image, blending 50 percent with the system highlight color. This value has no effect if the image list does not contain a mask.
    ILD_MASK
    Draws the mask.
    ILD_NORMAL
    Draws the image using the background color for the image list. If the background color is the CLR_NONE value, the image is drawn transparently using the mask.
    ILD_TRANSPARENT
    Draws the image transparently using the mask, regardless of the background color. This value has no effect if the image list does not contain a mask.}




    Может кто-то уже себе версию Codegear XE поставил, попробуйте код, плз, может какието несоответствия rad-vista/7 ?
  • Gu (10.12.10 23:07) [3]
    ..Да, забыл, один товарищь написал на почту - (при использовании) в image1.Picture.Icon:=ic; посоветовал image1.Picture.Icon.assign(ic); - не помогло.
  • Gu (22.12.10 02:29) [4]
    попробывал на Xe - тоже самое.

    вообщем вопрос открыт: как из системы выдрать иконки папок с превьюшками: http://i041.radikal.ru/1012/3b/2925a25653d6.png

    в опциях тотал (там где эскизы) есть пометка, что их выдирает плагин на базе Ole2. Как не искал, ничего не нашел на эту тему.

    Пробовал через AxtiveX импортнуть ShellFolder (там в конце списка есть Shell..) тоже не получилось с этим.

    Пробовал при помощи thumbnail, но там только превьюшки файлов, а попытка передать IExtractImage папку в качестве параметра вызывает ошибку выполнения.

    Скажите хотябы в какую сторону копать..
  • Eraser © (22.12.10 03:03) [5]
    иконки с первьюшками скорее всего рисуте какое-то расширение проводника, думаю вряд ли доберешься, проще самому сделать.
  • Gu (22.12.10 03:26) [6]
    2 Eraser
    .."какое-то расширение проводника" :) так если эта библиотека, то проще подключить и функцию юзать, чем заниматься отрисовкой под углом вида вложеных рисунков и вида папки с тенями.. и патом тотал командер это же делает както..
  • Германн © (22.12.10 03:49) [7]

    > и патом

    <offtop>
    Не надо "коверкать" русский язык
    </offtop>
  • Eraser © (22.12.10 04:21) [8]
    > [6] Gu   (22.12.10 03:26)

    эта библиотека наверняка без документации и может менятся в зависисмости даже от билдов системы. задача то какая?
  • Gu (22.12.10 14:52) [9]
    Задача: на винде начиная с виста (vista, win7, win 2008) вытащить иконку (или битмап) указаной папки. Но не простую иконку, а такую как на скрине http://i041.radikal.ru/1012/3b/2925a25653d6.png т.е. если в папке есть рисунки или другие документы, которые при включенных эскизах и больших значках в проводнике отображают папку как превью с вложеными миниатюрами.
  • Eraser © (22.12.10 15:38) [10]
    Если через SHGetFileInfo не получается - то не получится.
  • Gu (22.12.10 17:04) [11]
    тотал вытаскивает через ole2, писал выше, значит както можно, он же сторонний продукт, в винду не входит, но может.
    а SHGetFileInfo может какие новые ключики появились начиная с виста, скока не лазил ничего не нахожу, на буржуйских форумах тоже все молчат.
  • Gu (30.12.10 19:29) [12]
    на одном форуме дале такой совет:
    >> думаю, тут работает несколько ShellExtension-библиотек, и тебе придется использовать их интерфейсы

    никто не имел с этим дело под дельфями?
  • Eraser © (30.12.10 19:37) [13]
    1. пример есть в "Руководстве разработчика" Тейксейра, Пачеко.
    2. глянь у Rouse'а http://rouse.drkb.ru/ по-моему там что-то было по расширениям проводника.
  • Ruslan A. (17.09.11 15:17) [14]
    Я нашёл ответ на ваш вопрос! С ума сойти. Прямое решение искалось 3 года
    Превьюшки можно получать через IShell

    Вот сорс модуля. Надеюсь, он влезет целиком
    Правда навскидку в этом модуле у папок проблемы с полупрозрачностью, выглядят они не очень, но это уже технические мелочи.
    PDF, всякие JPEG и пр. файлы, которые отображает проводник в режиме thumbnail, получаются на ура.

    unit ShellObjHelper;

    {$IFDEF VER100}{$DEFINE DELPHI3}{$ENDIF}

    interface

    uses
     Windows, ShlObj, ActiveX, ShellAPI, Graphics, StrUtils;

    type
     { from ShlObjIdl.h }
     IExtractImage = interface
       ['{BB2E617C-0920-11D1-9A0B-00C04FC2D6C1}']
       function GetLocation(Buffer: PWideChar;
                            BufferSize: DWORD;
                            var Priority: DWORD;
                            var Size: TSize;
                            ColorDepth: DWORD;
                            var Flags: DWORD): HResult; stdcall;
       function Extract(var BitmapHandle: HBITMAP): HResult; stdcall;
     end;

     IRunnableTask = interface
       ['{85788D00-6807-11D0-B810-00C04FD706EC}']
       function Run: HResult; stdcall;
       function Kill(fWait: BOOL): HResult; stdcall;
       function Suspend: HResult; stdcall;
       function Resume: HResult; stdcall;
       function IsRunning: Longint; stdcall;
     end;

    const
     { from ShlObjIdl.h }
     ITSAT_MAX_PRIORITY      = 2;
     ITSAT_MIN_PRIORITY      = 1;
     ITSAT_DEFAULT_PRIORITY  = 0;

     IEI_PRIORITY_MAX        = ITSAT_MAX_PRIORITY;
     IEI_PRIORITY_MIN        = ITSAT_MIN_PRIORITY;
     IEIT_PRIORITY_NORMAL    = ITSAT_DEFAULT_PRIORITY;

     IEIFLAG_ASYNC     = $001; // ask the extractor if it supports ASYNC
    extract
                               // (free threaded)
     IEIFLAG_CACHE     = $002; // returned from the extractor if it does NOT
    cache
                               // the thumbnail
     IEIFLAG_ASPECT    = $004; // passed to the extractor to beg it to render
    to
                               // the aspect ratio of the supplied rect
     IEIFLAG_OFFLINE   = $008; // if the extractor shouldn't hit the net to get
                               // any content needs for the rendering
     IEIFLAG_GLEAM     = $010; // does the image have a gleam? this will be
                               // returned if it does
     IEIFLAG_SCREEN    = $020; // render as if for the screen  (this is
    exlusive
                               // with IEIFLAG_ASPECT )
     IEIFLAG_ORIGSIZE  = $040; // render to the approx size passed, but crop if
                               // neccessary
     IEIFLAG_NOSTAMP   = $080; // returned from the extractor if it does NOT
    want
                               // an icon stamp on the thumbnail
     IEIFLAG_NOBORDER  = $100; // returned from the extractor if it does NOT
    want
                               // an a border around the thumbnail
     IEIFLAG_QUALITY   = $200; // passed to the Extract method to indicate that
                               // a slower, higher quality image is desired,
                               // re-compute the thumbnail

    {$IFDEF DELPHI3}
    // Delphi 3 SysUtils does not have this function
    function ExcludeTrailingBackslash(const Src: string): string;
    {$ENDIF}

    // IShellFolder methods helper
    procedure ShellFolderBindToObject(const ShellFolder: IShellFolder;
     PIDL: PItemIDList; const riid: TGUID; out pv);
    function ShellFolderGetUIObjectOf(const ShellFolder: IShellFolder;
     cidl: DWORD; var PIDL: PItemIDList; riid: TGUID; out pv): Boolean;
    procedure ShellFolderParseDisplayName(const ShellFolder: IShellFolder;
     const DisplayName: string; out PIDL: PItemIDList);
    function ShellFolderGetExtractImage(const ShellFolder: IShellFolder;
     const RelativeFileName: string; Malloc: IMalloc;
     out XtractImage: IExtractImage): Boolean;

    function GetExtractImageItfPtr(const FileName: string;
     out XtractImage: IExtractImage): Boolean;
    function GetFileLargeIcon(const FileName: string;
     out LargeIcon: TIcon): Boolean;
    function ExtractImageGetFileThumbnail(const XtractImage: IExtractImage;
     ImgWidth, ImgHeight, ImgColorDepth: Integer; var Flags: DWORD; Bmp:
    TBitmap;
     out RunnableTask: IRunnableTask): Boolean;
    function GetSysImgListIndex(const FileName: string): Integer;
    procedure GetShellFolderItfPtr(const FolderName: string; Malloc: IMalloc;
     out TargetFolder: IShellFolder);
    function GetBitmapFromFile(const FileName: String): TGraphic;

    implementation

    uses SysUtils, ComObj;

    {$IFDEF DELPHI3}
    function ExcludeTrailingBackslash(const Src: string): string;
    begin
     Result := Src;
     if AnsiLastChar(Result) = '
    \' then
       SetLength(Result, Pred(Length(Result)));
    end;
    {$ENDIF DELPHI3}

    procedure ShellFolderBindToObject(const ShellFolder: IShellFolder;
     PIDL: PItemIDList; const riid: TGUID; out pv);
    begin
     OleCheck(ShellFolder.BindToObject(PIDL, nil, riid,
       {$IFDEF DELPHI3}Pointer(pv){$ELSE}pv{$ENDIF}));
    end;

    function ShellFolderGetUIObjectOf(const ShellFolder: IShellFolder;
     cidl: DWORD; var PIDL: PItemIDList; riid: TGUID; out pv): Boolean;
    begin
     Result := NOERROR = ShellFolder.GetUIObjectOf(0, cidl, PIDL,
       riid, nil, {$IFDEF DELPHI3}Pointer(pv){$ELSE}pv{$ENDIF});
    end;

    procedure ShellFolderParseDisplayName(const ShellFolder: IShellFolder;
     const DisplayName: string; out PIDL: PItemIDList);
    var
     Attributes, Eaten: DWORD;
    begin
     OleCheck(ShellFolder.ParseDisplayName(0, nil,
       PWideChar(WideString(DisplayName)), Eaten, PIDL, Attributes));
    end;

    function ShellFolderGetExtractImage(const ShellFolder: IShellFolder;
     const RelativeFileName: string; Malloc: IMalloc;
     out XtractImage: IExtractImage): Boolean;
    var
     PIDL: PItemIDList;
    begin
     ShellFolderParseDisplayName(ShellFolder, RelativeFileName, PIDL);
     Result := ShellFolderGetUIObjectOf(ShellFolder, 1, PIDL,
       IExtractImage, XtractImage);
     Malloc.Free(PIDL);
    end;

    function GetExtractImageItfPtr(const FileName: string;
     out XtractImage: IExtractImage): Boolean;
    var
     TargetFolder: IShellFolder;
     FilePath: string;
     ItemIDList: PItemIDList;
     Malloc: IMalloc;
    begin
     FilePath := ExcludeTrailingBackslash(ExtractFilePath(FileName));
     OleCheck(SHGetMalloc(Malloc));
     GetShellFolderItfPtr(FilePath, Malloc, TargetFolder);
     ShellFolderParseDisplayName(TargetFolder, ExtractFileName(FileName),
       ItemIDList);
     try
       Result := ShellFolderGetUIObjectOf(TargetFolder, 1, ItemIDList,
         IExtractImage, XtractImage);
     finally
       Malloc.Free(ItemIDList);
     end;
    end;

  • Ruslan A. (17.09.11 15:18) [15]
    Вторая часть (не влезла просто):

    function GetFileLargeIcon(const FileName: string; out LargeIcon: TIcon):
    Boolean;
    var
     SFI: TSHFileInfo;
    begin
     if 0 <> SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_ARCHIVE, SFI,
       sizeof(SFI), SHGFI_ICON or SHGFI_LARGEICON) then
     begin
       LargeIcon := TIcon.Create;
       LargeIcon.Handle := SFI.hIcon;
       Result := True;
     end else
       Result := False;
    end;

    function ExtractImageGetFileThumbnail(const XtractImage: IExtractImage;
     ImgWidth, ImgHeight, ImgColorDepth: Integer; var Flags: DWORD; Bmp:
    TBitmap;
     out RunnableTask: IRunnableTask): Boolean;
    var
     Size: TSize;
     Buf: array[0..MAX_PATH] of WideChar;
     BmpHandle: HBITMAP;
     Priority: DWORD;
     GetLocationRes: HRESULT;

     procedure FreeAndNilBitmap;
     begin
       {$IFNDEF DELPHI3}
       FreeAndNil(Bmp);
       {$ELSE}
       Bmp.Free;
       Bmp := nil;
       {$ENDIF}
     end;

    begin
     Result := False;
     RunnableTask := nil;
     Size.cx := ImgWidth;
     Size.cy := ImgHeight;
     Priority := IEIT_PRIORITY_NORMAL;
     Flags := Flags or IEIFLAG_ASYNC;
     GetLocationRes := XtractImage.GetLocation(Buf, sizeof(Buf), Priority,
    Size,
       ImgColorDepth, Flags);

     if (GetLocationRes = NOERROR) or (GetLocationRes = E_PENDING) then
     begin
       if GetLocationRes = E_PENDING then
       begin
         { if QI for IRunnableTask succeed, we can use RunnableTask
           interface pointer later to kill running extraction process.
           We could spawn a new thread here to extract image. }

         if S_OK <> XtractImage.QueryInterface(IRunnableTask, RunnableTask)
    then
           RunnableTask := nil;
       end;

       try
         OleCheck(XtractImage.Extract(BmpHandle)); // This could consume a long
    time.
                                                   // If RunnableTask is
    available
                                                   // then calling Kill()
    method
                                                   // will immediately abort
    the process.
         Bmp.Handle := BmpHandle;
         Result := True;
       except
         on E: EOleSysError do
         begin
    //        -------------
           OutputDebugString(PChar(string(E.ClassName) + ': ' + E.Message));
    //        -------------
           FreeAndNilBitmap;
           Result := False;
         end
         else
         begin
           FreeAndNilBitmap;
           raise;
         end;
       end; { try/except }
     end;
    end;

    function GetSysImgListIndex(const FileName: string): Integer;
    var
     SFI: TSHFileInfo;
    begin
     SHGetFileInfo(PChar(FileName), 0, SFI, sizeof(TSHFileInfo),
       SHGFI_SYSICONINDEX);
     Result := SFI.iIcon;
    end;

    procedure GetShellFolderItfPtr(const FolderName: string; Malloc: IMalloc;
     out TargetFolder: IShellFolder);
    var
     DesktopFolder: IShellFolder;
     ItemIDList: PItemIDList;
    begin
     OleCheck(SHGetDesktopFolder(DesktopFolder));
     ShellFolderParseDisplayName(DesktopFolder, FolderName, ItemIDList);
     try
       ShellFolderBindToObject(DesktopFolder, ItemIDList, IShellFolder,
    TargetFolder);
     finally
       Malloc.Free(ItemIDList);
     end;
    end;

    //*******************************************************

    function GetBitmapFromFile(const FileName: String): TGraphic;
    var
     XtractImage: IExtractImage;
     Bmp: TBitmap;
     Icon: TIcon;
     ColorDepth: Integer;
     Flags: DWORD;
     RT: IRunnableTask;
    begin
     Flags := DWORD(IEIFLAG_OFFLINE) or DWORD(IEIFLAG_SCREEN);
     ColorDepth := 32;

     Result := nil;
     Icon := nil;
     Bmp := TBitmap.Create;
     try
       if GetFileLargeIcon(FileName, Icon) then
         Result := Icon;

       if GetExtractImageItfPtr(FileName, XTractImage) and
    //       (not AnsiEndsStr('.dwg', FileName)) and
          ExtractImageGetFileThumbnail(XtractImage, 256, 256, ColorDepth,
    Flags, Bmp, RT) then
       begin
         Result := Bmp;
         Icon.Free;
       end
       else
         Bmp.Free;
     except
     end;
    end;

    end.

    {-------------------------------------------------------------------------------
    Unit Name: ShellObjHelper
    Author   : hans gulo (HG)
    Purpose  : Shell Object helper routines
    Purpose  : Demo application's main unit for retrieving IExtractImage
    interface
               pointer from Windows Shell folder to crete thumbnail image.
               This code is a complementary for Delphi3000.com article at
               http://www.delphi3000.com/articles/article_3806.asp
    -------------------------------------------------------------------------------}

  • Ruslan A. (17.09.11 15:20) [16]
    Комментарии в начале кода съехали. Там где объявление констант.
  • Gu (12.10.11 00:39) [17]
    это не то. меня больше интересуют виды папок вин7, а то что тут (http://www.delphi3000.com/articles/article_3806.asp) писалось в 2003 году когда вин7 еще небыло :) и эскизы криво вытаскивает.
  • Eraser © (12.10.11 04:15) [18]
  • Gu (12.10.11 15:34) [19]

    > Eraser ©   (12.10.11 04:15) [18]


    Во! То, что надо, большое спасибо, буду разбираться
 
Конференция "WinAPI" » Большие иконки папок и файлов Vista, Win7
Есть новые Нет новых   [134430   +2][b:0][p:0.014]