Этот интерфейс соответствует папке — одному из основных элементов пространства имен Проводника. Зачем было вводить термин "папка", когда существовали уже общепринятые "каталог" и "директория"? В отличие от последних двух, папка может быть не просто обычным элементом файловой системы. Она может быть виртуальной — как папки Принтеры, Документы или Панель управления. Любая папка может содержать коллекцию объектов из состава пространства имен.
Получив указатель на интерфейс ishellFoider, соответствующий папке, вы можете работать с ней, как с объектом СОМ. "Верхушкой" (корневой папкой) пространства имен является папка Рабочий стол (Desktop). Получить интерфейс isheiiFoider этой папки можно путем вызова функции:
function SHGetDesktopFolder(var ppshf: IShellFolder): HResult;
Логика работы с описываемым интерфейсом такова: сначала необходимо получить интерфейс нужной папки, а затем можно переходить к работе с ее содержимым. Содержимое представляет собой список, а каждый элемент папки представлен структурой pitemiDList. Эта структура не типизирована; ее единственное обязательное поле содержит длину в байтах, зная которую можно переместиться к следующему элементу. То есть получается обычная цепочка. Все остальные поля заполняются соответствующими функциями и методами интерфейса ishellFoider.
Примечание
Все служебные функции работы со структурами PitemiDList — создание, уничтожение, копирование, перемещение по цепочке и т. п. — содержатся в примере Virtual ListView, поставляемом с Delphi. Если вы намерены писать программы, работающие с ishellFoider, целесообразно взять их на заметку. В дальнейшем для простоты эти структуры будем именовать pidl.
Рассмотрим функции интерфейса ishellFoider. Под "текущей папкой" в табл. 31.1 понимается та папка, которая в данный момент представляет интерфейс IShellFolder.
Метод - Описание
function ParseDisplayName (hwndOwner : HWND; pbcReserved: Pointer; IpszDisplayName: POLESTR; out pchEaten: ULONG; out ppidl: PitemiDList; var dwAttributes : ULONG) : HResult; - Эта функция позволяет получить указатель на элемент ppidl, зная только его полное имя (с путем)
IpszDisplayName
function EnumObjects (hwndOwner: HWND; grf Flags: DWORD; out EnumlDList: lEnumlDList) : HResult; - Возвращает указатель на специальный интерфейс lEnumlDList, предназначенный для организации цикла по всем элементам списка в текущей папке
function BindToObject (pidl: PitemiDList; pbcReserved: Pointer; const riid: TIID; out ppvOut: Pointer) : HResult; - Возвращает интерфейс папки pidl, которая должна находиться в текущей папке (на которую ссылается интерфейс, вызвавший этот метод)
function ComparelDs (IParam: LPARAM; pidll, pid!2: PitemiDList): HResult; - Сравнивает два первых элемента В списках pidll И pidl2
function CreateViewObject (hwndOwner: HWND; const riid: TIID; out ppvOut: Pointer) : HResult; - Создает визуальный объект для текущей папки и возвращает указатель на него в параметре ppvOut
function GetAttributesOf (cidl: UINT; var apidl: PItemlDList; var rgflnOut: UINT): HResult; - Возвращает атрибуты элемента под номером cidl в списке apidl. Результат — набор флагов, устанавливаемых в параметре rgf inOut
function GetUIObjectOf (hwndOwner : HWND; cidl: UINT; var apidl: PItemlDList; const riid: TIID; prgflnOut: Pointer; out ppvOut: Pointer) : HResult; - Создает объект пользовательского интерфейса, связанный с элементом списка aplidl под номером cidl
function GetDisplayNameOf (pidl: PItemlDList; uFlags: DWORD; var IpName: TStrRet) : HResult; - Возвращает имя элемента pidl. Полнота возвращаемой информации определяется параметром uFlags
function SetNaraeOf (hwndOwner: HWND; pidl: PItemlDList; IpszName: POLEStr; uFlags: DWORD; var ppidlOut: PItemlDList) : HResult; - Задает новое имя IpszName для списка pidl. При этом возвращается новый указатель на список — ppidlOut
Два метода — ParseDisplayName и GetDisplayNameOf — взаимно дополняют друг друга. Первый из них нужен, если вы имеете указатель на ishellFoider и хотите связать его с конкретной папкой. На практике это сводится к задаче в три действия:
1. Получить указатель на интерфейс какой-либо папки, скажем, рабочего стола при помощи ShGetDesktopFolder.
2. Получить указатель (pidl) нужного вам элемента. Это осуществимо многими способами. Первый из них — как раз через вызов метода IShellFolder. ParseDisplayName. Если вы хотите получить доступ к одной из виртуальных (специальных) папок, то незаменимой будет следующая функция:
function SHGetSpecialFolderLocation(hwndOwner: HWND; nFolder: Integer; var ppidl: PItemlDList): HResult;
В параметре nFolder вы задаете константу, соответствующую выбранной специальной папке. На выходе будет указатель на элемент ppidl, соответствующий этой папке.
Примечание
Во многих функциях Shell API и методах его интерфейсов встречается параметр hwndOwner. Он должен задавать дескриптор окна на тот случай, если придется выводить диалоговое окно или окно с сообщением об ошибке.
Возможные значения параметра nFolder перечислены в табл. 31.2. В комментариях к ним "виртуальная" папка является особым объектом, который предоставляется пользователю при помощи Shell API. Просто "папка" реально существует где-то в файловой системе.
Значение - Комментарий
CSIDL_BITBUCKET - Корзина (Recycle bin) — специальная папка для удаленных файлов. Пути к Recycle bin нет в системном реестре во избежание перемещения или удаления, и его не узнать иным методом
CSIDL_CONTROLS - Панель инструментов (Control Panel) — виртуальная папка, содержащая значки апплетов Панели инструментов
CSIDL_DESKTOP - Виртуальная папка Рабочий стол (Desktop), корневая в пространстве имен
CSIDL_DESKTOPDIRECTORY - Папка файловой системы, реально содержащая объекты рабочего стола
CSIDL DRIVES - Виртуальная папка Мой компьютер (My Computer), содержащая элементы для всех накопителей на компьютере подключенных сетевых устройств, папки Принтеры, Панель инструментов, Удаленный доступ к сети
CSIDL FONTS - Виртуальная папка Шрифты
CSIDL NETHOOD - Папка, содержащая объекты сетевого окружения
CSIDL_NETWORK - Виртуальная папка Сетевое окружение (Network Neighborhood)
CSIDL_PERSONAL - Папка Мои документы
CSIDL_PRINTERS - Виртуальная папка Принтеры (Printers)
CSIDL_PROGRAMS - Папка Программы из главного меню, содержащая папки установленных на компьютере программ
CSIDL RECENT - Папка, содержащая ссылки на последние использовавшиеся документы (Recent)
CSIDL SENDTO - Папка, содержащая элементы контекстного меню Send To...
CSIDL_STARTMENU - Папка, содержащая элементы главного меню Пуск (Start)
CSIDL_STARTUP - Папка, содержащая элементы меню Автозапуск (Startup)
CSIDL_TEMPIATES - Папка, содержащая шаблоны типовых документов
Третий вариант получить pidi нужной папки — интерактивный, с помощью функции Shell API.
function ShBrowseForFolder(var Ipbi: TBrowselnfo): PItemlDList;
Перед ее вызовом следует заполнить структуру типа TBrowselnfo, содержащую в частности pidi того элемента, который будет корневым. После вызова функции пользователь увидит перед собой диалоговое окно выбора папки (рис. 31.3).

В данном примере корневой служит виртуальная папка My Computer. Пользователю предоставляется возможность выбрать одну из папок файловой системы (за это отвечает флаг TBrowseinfo.uiFlags, равный
BIF_RETURNONLYFSDIRS).
На выходе функция возвращает pidi папки, имя которой извлекается из него вызовом еще одной функции Shell — shGetPathFromList.
procedure TForml/ButtonlClick(Sender: TObject) ; var BI : TBrowselnfo; Image : integer; StartPIDL, ResPIDL : PItemlDList; S, Path : ArraytO..max_path-l] Of WideChar; begin 01eCheck(SHGetSpecialFolderLocation(Handle, CSIDL_DRIVES, StartPIDL)); With BI do Begin hwndOwner = Application.Handle; pszDisplayName = @S; IpszTitle = 'Выберите необходимую папку'; ulFlags = BIF_RETURNONLYFSDIRS; pidlRoot = StartPIDL; Ipfn = nil; iImage = 1; end; ResPIDL := SHBrowseForFolder(BI) ; if SHGETPathFromlDList(ResPIDL, @Path[0]) then Labe11.Caption := StrPas(@Path[0]) ; end;
Полученное имя здесь отображается при помощи компонента Label 1.
3. Наконец, перейдем к третьему действию нашей задачи. Теперь, зная pidi папки, с которой вы будете работать, можно получить указатель на интерфейс ishellFolder вызовом метода BindToObject. Мы еще не рассмотрели такой важный аспект работы с папками, как просмотр их содержимого. Верные правилу СОМ: "каждый должен заниматься своим делом", разработчики Shell предоставили для просмотра еще один интерфейс — IEnumiDList. Пугаться нечего, набор возможностей этого интерфейса даже меньше, чем у пульта ДУ в магнитофоне. Его четыре метода — Next, Skip, Reset и clone — позволяют организовать просмотр списка в одном направлении, а также возврат к началу и дублирование (Clone) выбранного элемента списка. Вот как это выглядит на практике.
Memol.Clear; try 01eCheck(SHGetDesktopFolder(DeskTop)); 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)}); OleCheck(NewShellFolder.EnumObj ects(Self.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS, Enumerator)); while Enumerator.Next(1, pidl, Numpidls) = S_OK do begin NewShellFolder.GetDisplayNameOf(PIDL, SHGDN_FORPARSING, StrRet); case StrRet.uType of STRRET_CSTR: s := StrRet.cStr; STRRET_OFFSET: begin P := @PIDL.mkid.abID[StrRet.uOffset - SizeOf(PIDL.mkid.cb)]; SetString(s, P, PIDL.mkid.cb - StrRet.uOffset); end; STRRET_WSTR: s := StrRet.pOleStr; end;//case Memol.Lines.Add(s); end; except on ErEOleSysError do ShowMessage(''); end;
В этом примере имя нужной папки извлекается из компонента 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); var Filelnfo: TSHFilelnfo; ImageListHandle: THandle; begin ImageListHandle := SHGetFilelnfo('С:\', 0, Filelnfo, SizeOf(Filelnfo) , SHGFI_SYSICONINDEX or SHGFI_ICON); SendMessage(ToolBarl.Handle, TB_SETIMAGELIST, 0, ImageListHandle); end;
Точно так же можно извлечь значок, соответствующий конкретному файлу. В составе 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.
Если у вас есть двор и вы хотите оградить его от посторонних тогда вам нужно изготовление металлических ворот цена, на которых не такая дорогая. Различные красивые ворота с узорами.
Комментарии
?
?