В данном примере корневой служит виртуальная папка 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 есть другие функции, созданные для извлечения значков:
Эта функция извлекает значок из файла IpszExeFileName (это должен быть файл типа EXE, DLL или ICO) и возвращает его дескриптор. Если значок не найден, возвращаемое значение равно 0.
Эта функция может работать с файлами разных форматов. Сначала она, как и предыдущая, ищет значок в теле файла. Если его там нет, предпринимается попытка отыскать значок в приложении, связанном с данным типом файлов. Например, из файла с расширением doc будет извлечен один из значков Microsoft Word.