È ansible ottenere icone 48×48 o 64×64 dalla Vista Shell?

Se le icone 48×48 o 64×64 sono presenti in Vista Shell, come si può ottenere l’handle per visualizzarne uno in un TImage usando SHGetFileInfo?

Mi piacerebbe selezionare un’icona da un elenco di immagini che rappresenta un percorso di cartella e visualizzare un’icona 48×48 o 64×64 in un Timage.

// 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 ); 

Conto

È necessario utilizzare la funzione SHGetImageList per ottenere l’elenco di immagini con le icone più grandi.

Qui hai un esempio in 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; 

Puoi usare queste funzioni in questo modo

 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; 

Leggi qui: (Codice in C ++)

Ottenere le icone 16 × 16 e 32 × 32 su Windows è relativamente facile ed è spesso semplice come una chiamata a ExtractIconEx.

Tuttavia, ottenere le icone extra large (48 × 48) e jumbo (256 × 256) introdotte rispettivamente da XP e Vista è leggermente più complessa. Questo normalmente è fatto da:

  1. Ottenere le informazioni sul file, in particolare l’indice delle icone, per il file specificato usando SHGetFileInfo
  2. Recupero della lista di immagini del sistema in cui sono memorizzate tutte le icone
  3. Trasmetti l’elenco delle immagini a un’interfaccia IImageList e ottieni l’icona da lì

Abbiamo riscontrato che l’indice del file non era corretto perché l’icona errata veniva mostrata durante il test del codice pubblicato da RRUZ. Il metodo GetIconFromFile stava impostando l’indice baised sul conteggio delle immagini. Abbiamo modificato GetIconFromFile per utilizzare l’indice SFI (aIndex: = SFI.iIcon) e l’icona corretta è stata ottenuta. Apparentemente la shellimagelist cambia continuamente, quindi l’indice non era corretto.

Grazie a tutti per aver assistito. Questo sembra un ottimo codice ora.

 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; 

kicon

utilizzo il metodo kicon appropriato ( LoadFromFile / LoadFromModule / LoadFromModuleByIndex ) a seconda del tipo di file di origine.

se questi metodi falliscono, io uso PrivateExtractIconsA :

function PrivateExtractIcons (lpszFile: PChar; nIconIndex, cxIcon, cyIcon: intero; phicon: PHandle; piconid: PDWORD; nIcons, flags: DWORD): DWORD; stdcall; nome ‘user32.dll’ esterno ‘PrivateExtractIconsA’;

e passare l’handle risultante al metodo LoadFromHandle di kicon.

una volta caricato in kicon, scorrere l’array icondata [] per selezionare la dimensione desiderata. kicon ha metodi per convertire l’immagine restituita in PNG.