Поделиться через


Получение идентификатора папки

Прежде чем использовать объект пространства имен, его необходимо определить. Это означает получение указателя на список идентификаторов элементов (PIDL) или, в случае объектов файловой системы, его путь. В этом разделе рассматриваются два простых способа получения идентификаторов объектов.

Для более эффективного подхода, который будет работать с любой папкой, используйте интерфейс IShellFolder. Для получения дополнительной информации см. раздел "Сведения о содержимом папки".

Диалоговое окно OpenFiles

Чтобы пользователь мог перемещаться по пространству имен и выбирать папку, приложение может использовать интерфейс IFileDialog. Вызов этого интерфейса с флагом FOS_PICKFOLDERS запускает диалоговое окно "Открыть файлы" в режиме выбора папок.

Для Windows Vista и более поздних версий это рекомендуемый способ выбора папок.

Диалоговое окно SHBrowseForFolder

Чтобы пользователь мог перемещаться по пространству имен и выбрать папку, приложение может просто вызвать SHBrowseForFolder. Вызов этой функции запускает диалоговое окно с пользовательским интерфейсом, который работает похожий на Открыть или Сохранить распространенные диалоговые окна.

Когда пользователь выбирает папку, SHBrowseForFolder возвращает полный идентификатор PIDL папки и его отображаемое имя. Если папка находится в файловой системе, приложение может преобразовать PIDL в путь, вызвав SHGetPathFromIDList. Приложение также может ограничить диапазон папок, которые пользователь может выбрать, указав корневую папку. Отображаются только папки, которые находятся ниже корневого каталога в пространстве имен. На следующем рисунке показано диалоговое окно SHBrowseForFolder с корневой папкой, заданной в Program Files.

снимок экрана диалогового окна поиска папки

Ниже приведен простой пример использования SHBrowseForFolder.

Специальные папки и CSIDL

Некоторые часто используемые папки системой обозначены как специальные. Эти папки имеют четко определенную цель, и большинство из них присутствуют во всех системах. Даже если они не присутствуют изначально, их имена и расположения по-прежнему определены, поэтому их можно добавить позже. Коллекция специальных папок включает все стандартные виртуальные папки системы, такие как принтеры, мои документы и сетевой район. Она также включает ряд стандартных папок файловой системы, таких как Program Files и System.

Несмотря на то, что папки являются стандартным компонентом всех систем, их имена и расположения в пространстве имен могут отличаться. Например, системный каталог — C:\Winnt\System32 в некоторых системах и C:\Windows\System32 на других устройствах. В прошлом переменные среды предоставили способ определения имени и расположения специальной папки в любой конкретной системе. Оболочка теперь предоставляет более надежный и гибкий способ определения специальных папок, CSIDLs. Обычно их следует использовать вместо переменных среды.

CSIDLs предоставляют универсальный способ идентификации и поиска специальных папок независимо от их имени или расположения в определенной системе. В отличие от переменных среды, csIDLs можно использовать с виртуальными папками, а также папками файловой системы. Каждая специальная папка имеет уникальный CSIDL, назначенный ему. Например, папка файловой системы Program Files содержит CSIDL CSIDL_PROGRAM_FILES, а виртуальная папка "Район сети" содержит CSIDL CSIDL_NETWORK.

CSIDL используется в сочетании с одной из нескольких функций оболочки для получения PIDL специальной папки или пути специальной папки файловой системы. Если папка не существует в системе, ваше приложение может принудительно создать её, объединив её CSIDL с CSIDL_FLAG_CREATE. CSIDL можно передать в следующие функции:

  • SHGetFolderLocation, которая извлекает PIDL специальной папки.
  • SHGetFolderPath, которая извлекает путь к специальной папке файловой системы.

Обратите внимание, что эти две функции были представлены с версией 5.0 оболочки и заменены функциями SHGetSpecialFolderLocation и SHGetSpecialFolderPath.

Простой пример использования CSIDLs и SHBrowseForFolder

В следующем примере функции PidlBrowse показано, как использовать CSIDLs для получения PIDL папки и использовать SHBrowseForFolder для выбора папки. Он возвращает PIDL и отображаемое имя выбранной папки.

LPITEMIDLIST PidlBrowse(HWND hwnd, int nCSIDL, LPSTR pszDisplayName)
{
    LPITEMIDLIST pidlRoot = NULL;
    LPITEMIDLIST pidlSelected = NULL;
    BROWSEINFO bi = {0};

    if(nCSIDL)
    {
        SHGetFolderLocation(hwnd, nCSIDL, NULL, NULL, &pidlRoot);
    }

    else
    {
        pidlRoot = NULL;
    }

    bi.hwndOwner = hwnd;
    bi.pidlRoot = pidlRoot;
    bi.pszDisplayName = pszDisplayName;
    bi.lpszTitle = "Choose a folder";
    bi.ulFlags = 0;
    bi.lpfn = NULL;
    bi.lParam = 0;

    pidlSelected = SHBrowseForFolder(&bi);

    if(pidlRoot)
    {
        CoTaskMemFree(pidlRoot);
    }

    return pidlSelected;
}

Вызывающее приложение передает дескриптор окна, который необходим SHBrowseForFolder. Параметр nCSIDL является необязательным CSIDL, используемым для указания корневой папки. Будут отображаться только папки под корневой папкой в иерархии. Рисунок, показанный ранее, был создан путем вызова этой функции с nCSIDL для параметра CSIDL_PROGRAM_FILES. Вызывающее приложение также передает строковый буфер pszDisplayName, чтобы сохранить отображаемое имя выбранной папки при возврате PidlBrowse. Это обязанность вызывающего приложения — освободить IDList, возвращаемый SHBrowseForFolder, с помощью CoTaskMemFree.