ishellfolderВсем привет! В этой статье мы начнем рассматривать оболочку Shell, а в частности интерфейс IShellFolder. Этот интерфейс, в первую очередь работает с обслуживанием файлов и папок операционной системы Windows.

Именно в данной статье, мы рассмотрим, как можно получить значок файла, ассоциируемый с конкретным приложением. Мы уже рассматривали что-то подобное, в статье – «Извлечение значков из EXE-файлов . Там мы получали все значки, которые были доступны из ресурсов файла, а в этой статье мы рассмотрим: как получить значок, ассоциируемый, именно с конкретным приложением (через какое приложение он открывается). Причем, как и в прошлой статье, мы сможем получать значки большого (large) и маленького (small) размера.

Для того, чтобы получить доступ к интерфейсу IShellFolder, необходимо подключить к проекту в Delphi следующие модули:

  • Shellapi
  • ShlObj

Поэтому, давайте создадим проект в Delphi и в uses подключим данные модули. Кроме того, на форму установим следующие компоненты:

  • TLabel
  • TButton – 2 шт
  • TEdit
  • TImage – 2 шт
  • TOpenDialog

В компоненте TEdit, мы будем показывать путь к нашему файлу, для которого мы будем получать значок ассоциируемого ему приложения. По нажатию на одну кнопку, мы будем запускать диалог выбора файла, по нажатию на другую кнопку, мы будем отображать нашу иконку в компоненте TImage (в одном – маленькую иконку, во втором – большую иконку). В общем, у меня проект выглядит следующим образом:

izvlechenie-znachkov-iz-exe-failov

Для всех этих целей нам понадобится функция:

function SHGetFileInfo(pszPath: PAnsiChar; dwFileAttributes: DWORD; var psfi: TSHFileInfo; cbFileInfo, uFlags: UINT): DWORD;

  • pszPath – параметр, в который передается строка, которая содержит путь к файлу. Для этого файла мы и собираемся получать иконку.
  • dwFileAttributes – это флаги атрибута файлов.
  • Psfi – структура, в которую помещается результат (в большинстве случаях). Для того, чтобы получить значок, необходимо обратиться к полу hIcon нашей структуры типа TSHFileInfo. Поля hIcon имеет тип HICON. Также в этой структуре имеется поле szTypeName (тип у него – array[0..79] of AnsiChar) – так вот, через данное поле структуры, можно получить название типа файла, например – Документ Microsoft Excel.
  • cbFileInfo – передает размеры структуры psfi: TSHFileInfo, указывать необходимо в байтах.
  • uFlags – флаги, которые определяют возвращаемую информацию

Теперь, на событие OnClick кнопки, которая будет выбирать путь к файлу, мы напишем следующий код:

procedure TForm1.Button1Click(Sender: TObject);
begin
   if OpenDialog1.Execute then
    Edit1.Text:=OpenDialog1.FileName
   else
    Exit;
end;

Тут все понятно и просто, поэтому на событие кнопки OnClick, которой мы будем отображать значок, ассоциируемые с конкретным приложением, в компоненте TImage, мы напишем следующий код:

procedure TForm1.Button2Click(Sender: TObject);
var
 infoFile:SHFILEINFO;
 flag:Cardinal;
begin
   try
    flag:=SHGFI_ICON;
    flag:=flag or SHGFI_SMALLICON;
    ZeroMemory(Addr(infoFile),SizeOf(infoFile));
    SHGetFileInfo(PAnsiChar(Edit1.Text),0,infoFile,SizeOf(infoFile),flag);
    Image1.Picture.Icon.Handle:=infoFile.hIcon;
   except
    on e:Exception do
   end;
end;

Этот код позволяет загружать маленький значок, ассоциируемого файла, для того, чтобы получить большой значок необходимо строчку flag:=flag or SHGFI_SMALLICON; заменить на    flag:=flag or SHGFI_LARGEICON; В итоге получиться следующее:]

izvlechenie-znachkov-iz-exe-failov2

Как Вы поняли, мы получили данные из нашей структуры, которая имеет тип TSHFileInfo, мы можем также получить:

  • szdisplayName (тип array[0..max_patch-1] of AnsiChar) – буфер, в котором хранится имя заданного объекта, например System(C:).
  • szTypeName (тип у него – array[0..79] of AnsiChar) – так вот, через данное поле структуры, можно получить название типа файла, например – Документ Microsoft Excel.

Для этого, необходимо использовать флаги:

  • SHGFI_DISPLAYNAME – для szdisplayName
  • SHGFI_EXETYPE – для szTypeName

Использовать их можно комбинированием, как в примере, с помощи операции ИЛИ (or), например:

flag:=flag or SHGFI_LARGEICON or SHGFI_EXETYPE;

Вот и все, следующая статья про то, как можно получить все пути системных папок. Исходные коды проекты прилагаются и их можно скачать тут.

Метки: , ,




К записи “Интерфейс IShellFolder. Получение значков, ассоциированные с файлами” оставлено комментариев: 4.

  1. SamsungS:

    Хорошая статейка…

  2. teran:

    пара советов по стилистике кода (субъективно, конечно).
    В работе с диалогами файлов и т.п. лучше сразу сделать выход, если диалог закрыли, а в противном случае работать далее.
    т.е. код переписать в виде
    if not OpenDialog.Execute() then exit;
    DoSomething(openDialog.filename);

    это уменьшит вложенность кода и улучшит читаемость.

    что касается флагов применяемых в ShGetFileInfo. Во-первых, если вы в методе зануляете память, то делайте это в самом начале метода, а не в середине (перед непосредственным использованием), это упростит вам жизнь в дальнейшем.
    И второе — не смысла присваивать сначала одно значение переменной flag, а потом к этой же переменной нему прибавлять еще одно значение, это только ухудшит читаемость
    пишите сразу flag := SHGFI_ICON or SHGFI_SMALLICON;

    ну и напоследок, остается не понятным, при чем тут IShellFolder, про который писалось в начале статьи, но который нигде не используется (:

    • Andrey:

      спасибо за замечание, тут такой вводный пост был на IshellFolder, дальше буду писать, уже именно про данный интерфейс!

Оставить комментарий на teran

Вы можете использовать следующие теги:

*