Перейти к содержанию
Fire Monkey от А до Я
  • 0

Как получить иконку файла или папки?


Dmitry_4501

Вопрос

Доброго времени суток. Имеется необходимость получить иконки файлов. Суть такая:

Имеются некие файлы-архивы, с нестандартной структурой файла. Проще говоря, я пишу приложение-архиватор для своего типа файлов.

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

Например: у меня установлен AIMP и все поддерживаемые AIMP'ом файлы отображаются его иконками. EXE, DLL, BAT, CMD и др - системными иконками.
Можно поискать готовые решения в виде ShellListBox, ShellListView и т.д., но они не подойдут, как минимум потому, что файлы, которыми я заполняю список не распакованы, они находятся в файле-архиве.

Соответственно функции по типу ExtractIcon (ссылка на docs.microsoft.com) и др. не подходят, файла-то нет. Я нашел одно решение - поиск иконок по реестру. В принципе это работает, но далеко не так, как хотелось бы... 

Информация в реестре почему-то порой не соответствует указанным мною параметрам. Например, в реестре у меня иконки подгружаются из файла VLC.exe. Изначально так оно и было, пока я не сменил их на AIMP, в проводнике это привело к нужному результату (иконки сменились), а вот в реестре до сих пор отображается VLC, соответственно, когда я ищу иконку по расширению .mp3, я нахожу иконку VLC, хотя настройки ассоциации формата .mp3 явно указывают на AIMP. 

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

Собственно вопрос: В какую сторону копать для решения данной проблемы? (Решения "только для FireMonkey" не подойдут, ибо нужны именно WinAPI-решения).

Код получения иконки по формату файла: (не самое лучшее решение, это очевидно).

Спойлер

function GetIcon(aExtension: string): HICON;
  begin
    if reg = nil then
        reg := TRegistry.Create();

    reg.RootKey := HKEY_CLASSES_ROOT;

    var iconPath: TArray<string> := [];

    if (aExtension = '') then
      begin
        reg.OpenKey('Folder\DefaultIcon', false);
        iconPath := reg.ReadString('').Split([',']);
        reg.CloseKey();
        FreeAndNil(reg);
        Exit(ExtractIcon(0, PChar(iconPath[0]), StrToInt(iconPath[1])));
      end
    else
      begin
        reg.OpenKey(aExtension, false);
        var iconRef: string := reg.ReadString('');
        reg.CloseKey();
        reg.OpenKey(iconRef, false);
        if (reg.KeyExists('DefaultIcon')) then
          begin
            reg.OpenKey('DefaultIcon', false);
            iconPath := reg.ReadString('').Split([',']);
            if (iconPath[0].StartsWith('"') or iconPath[0].EndsWith('"')) then
                iconPath[0] := iconPath[0].Trim(['"']);

            reg.CloseKey();
            FreeAndNil(reg);
            Exit(ExtractIcon(0, PChar(iconPath[0]), StrToInt(iconPath[1])));
          end;
      end;
    reg.CloseKey();
    reg.OpenKey('Unknown\DefaultIcon', false);
    iconPath := reg.ReadString('').Split([',']);
    Result := ExtractIcon(0, PChar(iconPath[0]), StrToInt(iconPath[1]));
  end;

 

Прикрепляю небольшой пример использования этой функции.

Project1.zip

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
12 часов назад, slav_z сказал:

господи, как же я давно не писал ничего на vcl

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


Просто у меня архив с нестандартной структурой и хотелось бы получить иконки файлов без их извлечения на диск. Например (насколько я знаю), так работает WinRar и 7-zip, они не извлекают файлы для того получить их иконки. Можно открыть архив на несколько гигабайт и он корректно покажет иконки файлов. Вот чего я хочу добиться, чтобы отобразить иконку файла, но если самого файла на диске нет.

P.S: Даже смотрел в сторону еще одного костыльного решения: создавать пустые файлы, которые содержатся в архиве и тогда вполне корректно смогу получить их иконки.

Ссылка на комментарий
  • 1

Да вроде не должно, тут по идее нужно только расширение файла:

SHGetFileInfo(PChar(Extension),

                    FILE_ATTRIBUTE_NORMAL,

                    FileInfo,

                    SizeOf(FileInfo),

                    SHGFI_ICON or SHGFI_SMALLICON or

                    SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES

                    );

Ссылка на комментарий
  • 0
5 часов назад, Дмитрий Потапов сказал:

P.S: Даже смотрел в сторону еще одного костыльного решения: создавать пустые файлы, которые содержатся в архиве и тогда вполне корректно смогу получить их иконки.

ну воще уже понесло не туда...

в примере файлы из массива..  там по расширению возвращает...  OnePeople правильно уже написал...

но! если вы хотите использовать это в FMX надо будет немного потрудиться... надо написать функцию которая из  HICON  делает FMX.Bitmap

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...