Можно ли получить значки 48x48 или 64x64 в оболочке Vista? - PullRequest
18 голосов
/ 09 ноября 2009

Если в оболочке Vista присутствуют значки 48x48 или 64x64, как вы можете заставить ручку отображать ее в TImage, используя SHGetFileInfo?

Я бы хотел выбрать значок из списка изображений, представляющий путь к папке, и отобразить значок 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 );

Bill

Ответы [ 4 ]

22 голосов
/ 10 ноября 2009

Вы должны использовать функцию 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;
6 голосов
/ 09 ноября 2009

Читать здесь: (код на C ++)

Получение значков 16 × 16 и 32 × 32 Windows относительно проста и часто так просто, как один звонок ExtractIconEx.

Однако, получая очень большой (48 × 48) и гигантские (256 × 256) значки введены соответственно XP и Vista немного сложнее. Это обычно делается:

  1. Получение информации о файле, в частности индекса значков, для данный файл, используя SHGetFileInfo
  2. Получение списка системных изображений, в котором хранятся все значки
  3. Приведение списка изображений в интерфейс IImageList и получение иконка оттуда
4 голосов
/ 10 ноября 2009

Мы обнаружили, что индекс файла был неверным, потому что во время тестирования кода, размещенного 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;
1 голос
/ 10 ноября 2009

kicon

я использую соответствующий метод kicon ( LoadFromFile / LoadFromModule / LoadFromModuleByIndex ) в зависимости от типа исходного файла.

если эти методы не работают, я использую PrivateExtractIconsA :

функция PrivateExtractIcons (lpszFile: PChar; nIconIndex, cxIcon, cyIcon: integer; phicon: PHandle; piconid: PDWORD; nIcons, флаги: DWORD): DWORD; STDCALL; внешнее 'user32.dll' имя 'PrivateExtractIconsA';

и передайте полученный дескриптор методу LoadFromHandle kicon.

как только он будет загружен в kicon, выполните итерацию по массиву icondata [], чтобы выбрать нужный размер. У kicon есть методы для преобразования возвращаемого изображения в PNG.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...