Інтерфейс ishellfolder - глава 31

Цей інтерфейс відповідає теці - одному з основних елементів простору імен Провідника. Навіщо було вводити термін "папка", коли існували вже загальноприйняті "каталог" і "директорія"? На відміну від останніх двох, папка може бути не просто звичайним елементом файлової системи. Вона може бути віртуальної - як папки Принтери, Документи або Панель управління. Будь-яка папка може містити колекцію об'єктів зі складу простору імен.

Отримавши покажчик на інтерфейс ishellFoider, відповідний папці, ви можете працювати з нею, як з об'єктом СОМ. "Вершиною" (кореневої папкою) простору імен є папка Робочий стіл (Desktop). Отримати інтерфейс isheiiFoider цієї папки можна шляхом виклику функції:

function SHGetDesktopFolder (var ppshf: IShellFolder): HResult;

Логіка роботи з описуваних інтерфейсом така: спочатку необхідно отримати інтерфейс потрібної папки, а потім можна переходити до роботи з її вмістом. Вміст являє собою список, а кожен елемент папки представлений структурою pitemiDList. Ця структура не типізовані; її єдине обов'язкове поле містить довжину в байтах, знаючи яку можна переміститися до наступного елементу. Тобто виходить звичайна ланцюжок. Всі інші поля заповнюються відповідними функціями і методами інтерфейсу ishellFoider.

Розглянемо функції інтерфейсу ishellFoider. Під "поточної папкою" в табл. 31.1 розуміється та папка, яка в даний момент представляє інтерфейс IShellFolder.

Таблиця 31.1. Функції інтерфейсу IShellFolder

Третій варіант отримати pidi потрібної папки - інтерактивний, за допомогою функції Shell API.

function ShBrowseForFolder (var Ipbi: TBrowselnfo): PItemlDList;

Перед її викликом слід заповнити структуру типу TBrowselnfo, що містить зокрема pidi того елемента, який буде кореневим. Після виклику функції користувач побачить перед собою діалогове вікно вибору папки (рис. 31.3).

Мал. 31.3. Діалогове вікно вибору папки, створене при виконанні функції ShBrowseForFolder

В даному прикладі кореневою служить віртуальна папка MyComputer. Користувачеві надається можливість вибрати одну з папок файлової системи (за це відповідає прапор TBrowseinfo.uiFlags, рівний

На виході функція повертає pidi папки, ім'я якої витягується з нього викликом ще однієї функції Shell - shGetPathFromList.

procedure TForml / ButtonlClick (Sender: TObject);

StartPIDL, ResPIDL. PItemlDList;

S, Path. ArraytO..max_path-l] Of WideChar;

01eCheck (SHGetSpecialFolderLocation (Handle, CSIDL_DRIVES, StartPIDL));

IpszTitle = 'Виберіть необхідну папку';

if SHGETPathFromlDList (ResPIDL, @Path [0])

then Labe11.Caption: = StrPas (@Path [0]);

Отримане ім'я тут відображується за допомогою компонента Label 1.

if not Succeeded (DeskTop.ParseDisplayName

(Self.Handle, nil, StringToWideChar (Editl.Text, ws, MAX_PATH), n, pidi, attr))

then begin ShowMessage ( 'Невідоме ім'я');

Exit; end; OleCheck (DeskTop.BindToObject (pidl, nil, IID_IShellFolder, Pointer (NewShellFolder)>);

SHCONTF_FOLDERS or SHCONTF_NONFOLDERS, Enumerator)); while Enumerator.Next (1, pidl, Numpidls) = S_OK do

NewShellFolder.GetDisplayNameOf (PIDL, SHGDN_FORPARSING, StrRet); case StrRet.uType of STRRET_CSTR:

s: = StrRet.cStr; STRRET_OFFSET:

P: = @ PIDL.mkid.abID [StrRet.uOffset - SizeOf (PIDL.mkid.cb)];

SetString (s, P, PIDL.mkid.cb - StrRet.uOffset);

on ErEOleSysError do ShowMessage ( '');

У цьому прикладі ім'я потрібної папки витягується з компонента Edit1. Отримавши покажчик на інтерфейс ishellFoider і потім інтерфейс IEnumiDList, програма заповнює отриманими іменами файлів список Memol.Lines.

Крім назви з більшості об'єктів файлової системи можна "витягнути" масу корисної інформації. Найчастіше задаються питанням: а як витягти значок, який відповідає цьому файлу або зберігається в ньому?

Способів для досягнення цієї мети кілька. Найпростіший - через виклик функції:

function SHGetFileInfo (pszPath: PAnsiChar; dwFileAttributes: DWORD;

var psfi: TSHFilelnfo; cbFilelnfo, uFlags: UINT): DWORD;

Параметр pszPath може бути дороговказом як на рядок з ім'ям файлу, так і на структуру виду pidl. Функція заповнює структуру psfi (тип TSHFilelnfo) довжиною cbFilelnfo байт. Залежно від значення слова прапорів (параметр uFlags) на виході може бути різноманітна інформація. Зокрема, якщо в параметрі uFlags задані значення SHGFI_SYSICONINDEX і SHGFI_ICON, то в структуру psfi буде записаний номер значка для даного файлу в системному списку зображень, а результатом виконання функції буде дескриптор цього списку. Скористатися ним можна (наприклад, для панелі інструментів) так:

procedure TForml.FormCreate (Sender: TObject);

SHGFI_SYSICONINDEX or SHGFI_ICON);

SendMessage (ToolBarl.Handle, TB_SETIMAGELIST, 0, ImageListHandle);

Точно так само можна витягти значок, відповідний конкретному файлу. У складі Shell є інші функції, створені для отримання значків:

  • function Extractlcon (hlnst: HINST; IpszExeFileName: PChar; nlconlndex: UINT): HICON;

Ця функція витягує значок з файлу IpszExeFileName (це повинен бути файл типу EXE, DLL або ICO) і повертає його дескриптор. Якщо значок не знайдений, повертається значення дорівнює 0.

  • function ExtractAssociatedIcon (hInst: HINST; IpIconPath: PChar; var Ipilcon: Word): HICON;

Ця функція може працювати з файлами різних форматів. Спочатку вона, як і попередня, шукає значок в тілі файлу. Якщо його там немає, робиться спроба відшукати значок в додатку, пов'язаному з даним типом файлів. Наприклад, з файлу з розширенням doc буде витягнутий один із значків Microsoft Word.