Добираясь до содержимого библиотек Windows 7

Это пятая по счету статья о библиотеках Windows 7. К этому времени вы уже должны быть знакомы с библиотеками Windows 7, понимать их внутреннюю структуру и то, как они встраиваются в оболочку Windows. В предыдущей статье мы показали различные модели программирования и различные пути работы с библиотеками Windows 7. В сегодняшней статье мы сконцентрируемся на модели Windows Shell Programming, которую можно использовать для получения доступа к библиотекам, даже не прибегая к новому интерфейсу IShellLibrary.

В предыдущей статье мы говорили о важности использования правильной версии стандартного файлового диалога (Common File Dialog, CFD), чтобы задействовать все возможности библиотек в Windows 7. Сегодня мы рассмотрим возможности, которые позволят пользователям выбирать и использовать библиотеки, как если бы они были простыми папками. Представим себе приложение для демонстрации слайдов, которое выводит изображения пользователя. Используя библиотеку Pictures, пользователи, по существу, говорят системе, что важные для них изображения хранятся в библиотеке Pictures и, следовательно, нашему приложению может быть просто указана вся библиотека Pictures, так что оно начнет отображать всю коллекцию изображений пользователей. К тому же, с точки зрения разработчиков, использование системы библиотек может исключить необходимость содержать отдельный файл конфигурации или базу данных, поскольку разработчики могут положиться на систему библиотек. Но перед тем как мы углубимся в программируемые интерфейсы Shell Libraries, нам нужно сказать о нескольких концепциях, касающихся самой модели Shell Programming.

Shell Programming Model

  • IShellItem, обычно называемый просто элементом, является основной единицей модели Shell UI и ее программирования. Элементы – это отдельные, независимые источники содержимого. Возьмем, например, вышеупомянутое стандартное диалоговое окно для работы с файлом. Очень немногие методы интерфейса, используемые для управления диалоговыми окнами файла, используют Shell-элементы для обращения к папкам вместо путей к файлам. Это важно, поскольку CFD может сообщать информацию как о папках файловой системы, так и о других виртуальных папках, которые можно найти в оболочке, таких как Control Panel или Computer.
  • Интерфейс IShellFolder представляет объекты папки оболочки из пространства имен оболочки. Используя IShellFolder, можно вывести содержимое папки, узнать название элемента в папке, рассмотреть имя относительно папки и получить список ID элемента.
  • Интерфейс IShellLink выводит ссылку, обычно на файл, папку или исполняемый файл.
  • Интерфейс IPropertyStore может быть использован для управления хранилищем свойств, связанным с различными объектами оболочки.
  • Интерфейс IShellLibrary представляет библиотеку Windows 7, о чем мы будем подробнее говорить в будущих статьях.

Теперь, когда мы определи, что используется в Shell Programming Model, можно поговорить о том, как в эту модель вписываются библиотеки. Поскольку библиотеки не размещены в файловой системе, вы не можете использовать связанные с файловой системой API. Именно поэтому вам нужны две основные возможности для работы с содержимым библиотек – Shell Programming Model и новый IShellLibrary API.

Использование Shell Programming Model

Вы можете использовать интерфейсы IShellItem и IShellFolder и множество вспомогательных функций, чтобы перечислить содержимое библиотек, как если бы они были обычными папками. Это значит, что приложения могут обращаться к содержимому библиотек без использования нового API и без значительных изменений в существующем коде.

Следующий фрагмент кода показывает, как использовать интерфейс IShellItem для перечисления всего содержимого библиотеки Picture.

 

 IShellItem *psi;
HRESULT hr =  SHGetKnownFolderItem(
            FOLDERID_PicturesLibrary, 
            KF_FLAG_CREATE, 
            NULL, 
            IID_PPV_ARGS(&psi));
if(SUCCEEDED(hr))
{
    IShellFolder *psf;
    hr = psi->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&psf));
    if(SUCCEEDED(hr))
    {
        IEnumIDList *penumIDList;
        psf->EnumObjects(NULL, 
                        SHCONTF_FOLDERS  | SHCONTF_NONFOLDERS, 
                        IID_PPV_ARGS(&penumIDList));
        //use penumIDList to enumerate the content of the folder
    }
}

Можно видеть, что при помощи вспомогательной функции SHGetKnownFolderItem мы возвращаем правильное расположение библиотеки, а также используем FOLDERID_PicturesLibrary, который является GUID, представляющий известную папку, в нашем случае библиотеку Pictures. SHGetKnownFolderItem – вспомогательная функция оболочки и часть более широкой группы вспомогательных функций, которые могут быть найдены в файле заголовка shlobj.h в составе Windows 7 SDK. Успешный вызов наполняет IShellItem *psi верной информацией о библиотеке, представленной как Shell Item. С этого места весь код – это обычное программирование Windows Shell, где мы используем BindToHandler, чтобы привязать ранее полученный Shell Item к папке оболочки. Далее мы перечисляем различные элементы в папке оболочки, которые, в случае с библиотекой, могут быть либо файлами, либо папками. Обратите внимание на используемые флаги SHCONTF_FOLDERS | SHCONTF_NONFOLDERS: они говорят папке оболочки, что мы хотим вывести все файлы и папки в библиотеке. Мы бы могли применить SHCONTF_NAVIGATION_ENUM, чтобы получить расположения библиотеки вместо самой библиотеки.

Использование нового IShellLibrary API

Можно добиться того же эффекта, как в вышеприведенном коде, используя новый Windows 7 IShellLibrary API, как показано в следующем фрагменте кода:

 

 IShellLibrary *pslLibrary;
HRESULT hr = SHLoadLibraryFromKnownFolder(
                FOLDERID_PicturesLibrary, 
                STGM_READ, 
                IID_PPV_ARGS(&pslLibrary));
if(SUCCEEDED(hr))
{
    IShellItemArray *psiaFolders;
    hr = pslLibrary->GetFolders(
                            LFF_STORAGEITEMS, 
                            IID_PPV_ARGS(&psiaFolders)); 
    IEnumShellItems *penumShellItems;
    psiaFolders->EnumItems(&penumShellItems);
    //work with penumShellItem to enumerate the library locations.
}

Здесь вы можете видеть другую вспомогательную функцию SHLoadLibraryFromKnownFolder, служащую для создания объекта IShellLibrary, из которого можно вызвать метод GetFolders, чтобы вернуть IShellItemArray, который содержит размещения библиотеки. Это то же самое, что использование SHCONTF_NAVIGATION_ENUM в примере на Shell Programming Model выше. Вы можете прямо перечислить содержимое каждого размещения библиотеки, используя Shell Programming Model или получать путь к каждого отдельного размещения.

В следующей статье мы подробнее рассмотрим оставшуюся часть IShellLibrary API.