delphi - romualfons - ronald seo
¿Se pueden obtener íconos de 48x48 o 64x64 desde Vista Shell? (4)
Debe usar la función SHGetImageList para obtener la lista de imágenes con los iconos más grandes.
Aquí tienes un ejemplo en 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;
Puedes usar estas funciones de esta manera
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;
Si hay iconos de 48x48 o 64x64 en el Shell de Vista, ¿cómo puede obtener el identificador para mostrar uno en un TImage utilizando SHGetFileInfo?
Me gustaría seleccionar un icono de una lista de imágenes que represente una ruta de carpeta y mostrar un icono de 48x48 o 64x64 en 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 );
Cuenta
Encontramos que el índice del archivo no era correcto porque se mostró el ícono incorrecto durante la prueba del código publicado por RRUZ. El método GetIconFromFile estaba configurando el índice en el recuento de imágenes. Cambiamos GetIconFromFile para usar el índice SFI (aIndex: = SFI.iIcon) y se obtuvo el ícono correcto. Aparentemente, la shellimagelist cambia constantemente, por lo que el índice era incorrecto.
Gracias a todos por asistir. Esto parece un muy buen código ahora.
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;
Lea here: (Código en C ++)
Obtener los íconos 16 × 16 y 32 × 32 en Windows es relativamente fácil y con frecuencia es tan simple como una llamada a ExtractIconEx.
Sin embargo, obtener los iconos extra grandes (48 × 48) y jumbo (256 × 256) introducidos respectivamente por XP y Vista es un poco más complejo. Esto normalmente se hace por:
- Obtención de la información del archivo, en particular el índice de iconos, para el archivo dado usando SHGetFileInfo
- Recuperando la lista de imágenes del sistema donde se almacenan todos los iconos
- Enviar la lista de imágenes a una interfaz de IImageList y obtener el icono desde allí
Utilizo el método kicon apropiado ( LoadFromFile / LoadFromModule / LoadFromModuleByIndex ) dependiendo del tipo de archivo de origen.
Si estos métodos fallan, utilizo PrivateExtractIconsA :
function PrivateExtractIcons (lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHandle; piconid: PDWORD; nIcons, flags: DWORD): DWORD; stdcall; nombre ''user32.dll'' externo ''PrivateExtractIconsA'';
y pase el identificador resultante al método LoadFromHandle de kicon .
una vez que se haya cargado en kicon, itere sobre la matriz icondata [] para seleccionar el tamaño que desee. kicon tiene métodos para convertir la imagen devuelta a PNG.