Приложение оперирует понятиемуказателя на список идентификаторов (pointer to an identifier list), который кратко именуют как PIDL-указатель. Все глобальные методы (утилиты) оболочки, принимающие в качестве одного из параметров PIDL-указатель, ожидают его в абсолютном формате. В то же время все методы интерфейса IShellFolder, принимающие в качестве одного из параметров pidl-указатель, ожидают его в относительном формате (если только в описании метода не указано иначе).
Ниже представлена функция, позволяющая получить указатель на следующий элемент в списке идентификаторов. В случае неудачи возвращается пустой указатель.
#include
LPITEMIDLIST GetNextItemID(const LPITEMIDLIST pidl) {
size_t cb = pidl->mkid.cb;
if (cb == 0) {
return NULL;
}
pidl = (LPITEMIDLIST)(((LPBYTE)pidl) + cb);
if (pidl->mkid.cb == 0) {
return NULL;
}
return pidl;
}
За размещение списков идентификаторов отвечает распределитель памяти оболочки (Shell's allocator), предоставляющий интерфейс IMalloc. Указатель на данный интерфейс распределителя памяти оболочки можно получить через метод SHGetMalloc.
Таким образом, если Ваше приложение получает от оболочки PIDL-указатель, то оно становится ответственным за обязательное в дальнейшем освобождение этого списка с помощью распределителя памяти оболочки.
Ниже представлен пример копирования списка идентификаторов:
#include
size_t GetItemIDListSize(const LPITEMIDLIST pidl) {
size_t size = 0;
LPBYTE p = LPBYTE(pidl);
while (p != NULL) {
if (static_cast(p + size)->mkid.cb == 0) {
size += sizeof(USHORT); // size of terminator;
break;
}
size += static_cast(p + size)->mkid.cb;
}
return size;
}
LPITEMIDLIST CopyItemIDList(const LPITEMIDLIST pidl) {
LPMALLOC pMalloc;
LPITEMIDLIST pidlResult;
if (pidl == NULL) {
return NULL;
}
if (!SUCCEEDED(SHGetMalloc(&pMalloc)) {
return NULL;
}
size_t size = GetItemIDListSize(pidl);
pidlResult = pMalloc->Alloc(size);
if (pidlResult!= NULL) {
CopyMemory(pidlResult, pidl, size);
}
pMalloc->Release;
return pidlResult;
}
Для увеличения эффективности работы Ваших приложений рекомендуется брать ссылку на распределитель памяти оболочки при запуске приложения, и освобождать эту ссылку при выходе из приложения.
Интерфейс IShellFolder предоставляет метод CompareIDs для определения расположения двух идентификаторов относительно друг друга (выше, ниже или равны) в данной папке. При этом параметр lParam определяет критерий упорядочивания, но заранее определённым для всех объектов-папок является только сортировка по имени (значение 0). Если вызов этого метода завершён успешно, то поле CODE возвращаемого значения содержит ноль при равенстве объектов, отрицательно, если первое меньше второго, и положительно в обратном случае.
hr = ppsf->CompareIDs(0, pidlA, pidlB);
if (SUCCEEDED(hr)) {
iComparisonResult = short(HRESULT_CODE(hr))
}
Некоторые папки имеют особое значение для оболочки. Для нахождения этих специальных папок, а также для того, чтобы пользователь мог сам искать необходимые ему папки, оболочка предоставляет специализированный набор функций: