Как получить иконку файла шрифта в Delphi с помощью SHGetFileInfo
Иногда разработчикам, работающим с Delphi, необходимо получить иконку файла шрифта для использования в своем приложении. Вопрос, поднятый в контексте, заключается в том, как получить иконку для файла шрифта, используя функцию SHGetFileInfo. Проблема заключается в том, что, несмотря на возможность получения иконки для папки шрифтов, непосредственно сама иконка файла шрифта получить не удается.
Описание проблемы
Используя функцию SHGetFileInfo, можно получить иконку для папки шрифтов, но при попытке получить иконку для конкретного файла шрифта (например, ARIALN.TTF) иконка не отображается. Это связано с тем, что оболочка Windows не предоставляет иконку для установленных шрифтов, так как таковой иконки не существует.
Подтвержденный ответ
Чтобы получить иконку файла шрифта, можно использовать альтернативный подход с помощью Windows Shell. Вместо прямого обращения к файлу шрифта, следует запросить иконку, ассоциированную с типом файла шрифта (например, TTF). Для этого можно использовать флаг SHGFI_USEFILEATTRIBUTES в функции SHGetFileInfo, который позволяет получить иконку, не обращаясь к самому файлу.
Пример кода на Object Pascal (Delphi):
var
sfi: SHFILEINFO;
begin
SHGetFileInfo('C:\SomeFileThatNeedNotEvenExist.ttf',
0, sfi, SizeOf(sfi), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON);
// Иконка файла шрифта доступна в sfi.hIcon
// Можно присвоить иконку элементу интерфейса, например, Image1.Picture.Icon.Handle := sfi.hIcon;
end;
Такой подход позволяет получить иконку, ассоциированную с типом файла, даже если файл не существует. Это особенно полезно, когда необходимо отобразить иконку типа файла в пользовательском интерфейсе.
Альтернативный ответ
Если требуется более сложная логика, связанная с перечислением шрифтов в папке шрифтов, можно использовать следующий код, который перечисляет все файлы в папке шрифтов и получает для каждого файла иконку:
var
psfDeskTop: IShellFolder;
psfFont: IShellFolder;
pEnumList: IEnumIdList;
pidFont: PItemIdList;
pidChild: PItemIdList;
FontPath: array[0..MAX_PATH - 1] of Char;
IconFile: array[0..MAX_PATH - 1] of Char;
pchEaten, dwAttributes, ItemsFetched: ULONG;
ExtractIcon: IExtractIcon;
IconIndex: Integer;
Flags: DWORD;
Icon, LH, SH: TIcon;
begin
FillChar(FontPath, SizeOf(FontPath), #0);
// Получаем путь к папке шрифтов
SHGetSpecialFolderPath(0, FontPath, CSIDL_FONTS, False);
SHGetDesktopFolder(psfDeskTop);
// Парсим путь к папке шрифтов
psfDeskTop.ParseDisplayName(0, nil, FontPath, pchEaten, pidFont, dwAttributes);
// Получаем интерфейс папки шрифтов
psfDeskTop.BindToObject(pidFont, nil, IID_IShellFolder, psfFont);
// Перечисляем объекты в папке
psfFont.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, pEnumList);
ItemsFetched := 0;
// Обходим перечисление и получаем иконки
while pEnumList.Next(1, pidChild, ItemsFetched) = NO_ERROR do
begin
// Получаем IExtractIcon для текущего файла/папки
psfFont.GetUIObjectOf(0, 1, pidChild, IID_IExtractIconW, nil, Pointer(ExtractIcon));
// Получаем локацию иконки
if Assigned(ExtractIcon) then
begin
IconIndex := 0;
Icon := TIcon.Create;
ExtractIcon.GetIconLocation(0, @IconFile, MAX_PATH, IconIndex, Flags);
// Получаем иконку
if (IconIndex < 0) or ((Flags and GIL_NOTFILENAME) = 0) then
ExtractIconEx(@IconFile, IconIndex, LH, SH, 1)
else
ExtractIcon.Extract(@IconFile, IconIndex, LH, SH, MakeLong(32, 16));
// Используем иконку по назначению
end;
end;
end;
Этот код перечисляет все элементы в папке шрифтов и для каждого элемента пытается получить иконку, что может быть полезно для создания, например, списка шрифтов с их иконками в пользовательском интерфейсе.
Важно отметить, что в коде необходимо выполнять проверку на ошибки и обрабатывать их соответствующим образом, чтобы обеспечить стабильность работы приложения.
Описание контекста: Разработчики Delphi интересуются, как получить иконку файла шрифта, используя функцию `SHGetFileInfo`, и сталкиваются с проблемой отсутствия стандартной иконки для файлов шрифтов, но находят способ обойти это, запросив иконку для типа
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.