Можно ли получить значки 48x48 или 64x64 из оболочки Vista?
Если в оболочке Vista присутствует значки 48x48 или 64x64, как вы можете заставить дескриптор отображать его в TImage с помощью SHGetFileInfo?
Я хотел бы выбрать значок из imagelist, который представляет путь к папке, и отображать значок 48x48 или 64x64 в 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 );
Билл
Ответы
Ответ 1
Вы должны использовать функцию 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;
Ответ 2
Прочитайте здесь: (код на С++)
Получение значков 16 × 16 и 32 × 32 Windows относительно проста и часто так же просто, как один призыв к ExtractIconEx.
Однако, получая сверхбольшие (48 × 48) и jumbo (256 × 256) введенные соответственно XP и Vista немного сложнее. Это обычно выполняется:
- Получение информации о файле, в частности индекса значка, для заданный файл с использованием SHGetFileInfo
- Получение списка системных изображений, в котором хранятся все значки.
- Передача списка изображений в интерфейс IImageList и получение значок оттуда
Ответ 3
Мы обнаружили, что индекс файла был неправильным, потому что был показан неправильный значок во время тестирования кода, размещенного 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;
Ответ 4
kicon
Я использую соответствующий метод kicon (LoadFromFile/ LoadFromModule/ LoadFromModuleByIndex) в зависимости от типа исходного файла.
Если эти методы терпят неудачу, я использую PrivateExtractIconsA:
Функция PrivateExtractIcons (lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHandle; piconid: PDWORD; nIcons, flags: DWORD): DWORD; STDCALL; external 'user32.dll' name 'PrivateExtractIconsA';
и передать полученный дескриптор в метод kicon LoadFromHandle.
после того, как он был загружен в kicon, перейдите по массиву icondata [], чтобы выбрать нужный размер. kicon имеет методы для преобразования возвращенного изображения в PNG.