Короткая версия
Что означает флаг SHCIDS_ALLFIELDS
IShellFolder.CompareIDs ?? 1008 *
Длинная версия
В Windows 95 Microsoft представила оболочку .Вместо того, чтобы предполагать, что компьютер состоит из файлов и папок, он состоит из абстрактного пространства имен элементов.
- , а не путей, начинающихся в корне диска (например,
C:\Documents & Settings\Ian
) - пути начинаются в корне пространства имен (
Desktop
)
И для размещения вещей, которые не являются файлами и папками (например, сетевые принтеры,Панель управления, мой телефон Android):
- вы не используете серию имен, разделенных обратной косой чертой (например, C: \ Users \ Ian )
- Вы используете pidls , серию непрозрачных блобов (например, Рабочий стол Этот ПК ОС (C:) Пользователи Ian )
PIDL являются непрозрачными BLOB-объектами, каждый BLOB-объект имеет смысл только для папки, которая его сгенерировала.
Чтобы расширить (или использовать) пространство имен оболочки, вы реализуете (или вызываете) интерфейс IShellFolder .
Один из методовиз IShellFolder используется для запроса расширения пространства имен до сравнения со списками идентификаторов (PIDL) :
IShellFolder :: CompareIDs метод
Определяет относительный порядок двух файловых объектов или папок, учитывая их списки идентификаторов элементов.
HRESULT CompareIDs(
[in] LPARAM lParam,
[in] PCUIDLIST_RELATIVE pidl1,
[in] PCUIDLIST_RELATIVE pidl2
);
В течение многих лет документ LPARAM
почти всегда был равен 0От shlobj.h
в.1999:
// IShellFolder::CompareIDs(lParam, pidl1, pidl2)
// This function compares two IDLists and returns the result. The shell
// explorer always passes 0 as lParam, which indicates "sort by name".
// It should return 0 (as CODE of the scode), if two id indicates the
// same object; negative value if pidl1 should be placed before pidl2;
// positive value if pidl2 should be placed before pidl1.
Итак, вы сравнили два списка идентификаторов - что бы они ни сравнивали, и все готово.
В Windows 2000 добавлены дополнительные флаги параметров сортировки
Начиная с версии 5 оболочки, старшие 16 бит LPARAM
теперь могут содержать дополнительные флаги для управления тем, как IShellFolder должен обрабатывать сортировку.
С ShObjIdl.idl
c.Windows 8.1 SDK:
// IShellFolder::CompareIDs lParam flags
// *these should only be used if the folder supports IShellFolder2*
//
// SHCIDS_ALLFIELDS
//
// only be used in conjunction with SHCIDS_CANONCALONLY or column 0.
// This flag requests that the folder test for *pidl identity*, that is
// "are these pidls logically the same". This implies that cached fields
// in the pidl that would distinguish them should be tested.
// Without this flag, you are comparing the *object* s the pidls refer to.
//
// SHCIDS_CANONICALONLY
//
// This indicates that the sort should be *the most efficient sort possible*, the implication
// being that the result will not be displayed to the UI: the SHCIDS_COLUMNMASK portion
// of the lParam can be ignored. (Before we had SHCIDS_CANONICALONLY
// we assumed column 0 was the "efficient" sort column.)
Обратите внимание на важные моменты:
- SHCIDS_CANONICALONLY предназначен для того, чтобы быть самым быстрым и самым эффективным видом сортировки, который у нас есть
- , и это нене должно быть логичным с точки зрения юзабилити пользовательского интерфейса;он просто должен быть последовательным
Как отметил Рэймонд Чен, это моральный эквивалент Юникода порядковый номер сравнение .
Заголовочный файл даже отмечает, что мы использовали , чтобы просто предположить, что столбец 0 был "самым быстрым" сортировщиком.Но теперь мы будем использовать флаг, чтобы скажем "использовать самую быструю из доступных сортировок" :
До того, как у нас было SHCIDS_CANONICALONLY
, мы предполагали, что столбец 0 был«эффективный» столбец сортировки.
Также отмечается, что вы можете игнорировать младшие 16 бит LPARAM (т. е. столбец), потому что нам все равно - мы используем самый эффективный.
Многое из этого отражено в официальной документации:
SHCIDS_CANONICALONLY
Версия 5.0. Когдасравнивая по имени, сравните системные имена, но не отображаемые имена.Когда этот флаг передается, эти два элемента сравниваются по любым критериям, которые папка Shell определяет наиболее эффективными, если она реализует согласованную функцию сортировки.Этот флаг полезен при сравнении на равенство или когда результаты сортировки не отображаются пользователю.Этот флаг не может быть объединен с другими флагами.
Но с SHCIDS_ALLFIELDS мы начинаем сбегать с рельсов
Заголовочный файл отмечает, что AllFields можно комбинировать толькос CanonicalOnly :
может использоваться только в сочетании с SHCIDS_CANONCALONLY или столбцом 0.
Но SDK сообщает, что CanonicalOnly должен появиться один:
Этот флаг нельзя комбинировать с другими флагами.
Так что же это?
Мы могли бы решить, что заголовочный файл неправильный, что SDK является пушечным, и делать то, что он говорит.
Но что говорит AllFields?
Существует некоторая концепция, что AllFields - это , пытающийся запросить, но скрытый за документацией.
Сравните всю информацию, содержащуюся в структуре ITEMIDLIST, а не только отображаемые имена.
ItemIDList не содержит отображаемого имени, он содержит ItemIDList.Они пытаются сказать, что я должен только посмотреть содержимое BLOB-объекта pidl?
- Например, если два элемента являются файлами, папка должна сравнить их имена и размеры, время файла, атрибуты и любую другую информацию в структурах.
В какой ситуации две ссылки на * один и тот же ** файл могут иметь разные имена, размеры, время файла, атрибуты и т. Д.?
Примеры SDK делают что-то другое
Windows Shell SDK Расширение оболочки провайдера данных Explorer * Пример 1187 * ( github ), похоже, работает так, как если бы CanonicalOnly и AllFields флагипоявляются вместе:
HRESULT CFolderViewImplFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
{
if (lParam & (SHCIDS_CANONICALONLY | SHCIDS_ALLFIELDS))
{
// First do a "canonical" comparison, meaning that we compare with the intent to determine item
// identity as quickly as possible. The sort order is arbitrary but it must be consistent.
_GetName(pidl1, &psz1);
_GetName(pidl2, &psz2);
ResultFromShort(StrCmp(psz1, psz2));
}
// If we've been asked to do an all-fields comparison, test for any other fields that
// may be different in an item that shares the same identity. For example if the item
// represents a file, the identity may be just the filename but the other fields contained
// in the idlist may be file size and file modified date, and those may change over time.
// In our example let's say that "level" is the data that could be different on the same item.
if ((ResultFromShort(0) == hr) && (lParam & SHCIDS_ALLFIELDS))
{
//...
}
}
else
{
//...Compares by the column number in LOWORD of LPARAM
}
Итак, у нас есть совершенно противоречивые документация, заголовки и образцы:
SHCIDS_ALLFIELDS
- SDK :никогда не может отображаться с SHCIDS_CANONICALONLY
- Заголовки : могут появляться в любое время
- Примеры : могут отображаться только с SHCIDS_CANONICALONLY
Что пытается спросить
Windows всегда считала, что столбец 0 был столбцом fast .Возможно, это связано с тем, что авторы API оболочки Windows предполагали, что ItemID PIDL всегда будет содержать имя внутри непрозрачного BLOB-объекта pidl.
Это подтверждается тем фактом, что структура оболочки STRRET позволяет вам указывать на строку внутри вашего pidl.
Бонусное чтение: Странная структура STRRET
И вот в какой-то момент они добавили экспресс-флаг, который говорит:
- мы не заботимся о локализации, о региональных правилах лингвистической сортировки и алгоритмах нормализации Юникода
- , просто сортируем их, потому что нам нужно найти дубликаты и проверить на равенство
И это делаетсмысл для канонического флага:
- просто скажите мне, если два IDL-списка указывают на один и тот же объект
Но тогда чтоОзначает ли пример SDK, когда они говорят о опции Все поля :
Если нас попросили провести сравнение по всем полям, проверьте любые другие поля, которые могутотличаться в элементе, который разделяет ту же самую идентичность.Например:
- , если элемент представляет файл, идентификатором может быть просто имя файла
- , но другими полями, содержащимися в списке, могут быть размер файла и дата изменения файла, исо временем они могут измениться.
Если два PIDL представляют один и тот же файл , какой смысл сравнивать их размер, дату и т. д.?Я уже говорил вам, что это один и тот же файл , что вы спрашиваете меня с флагом Все поля ?Почему я не могу просто сделать двоичное сравнение с BLOB-объектами?Почему не снаряд?Что CompareIDs делает это
MemCmp(pidl1, pidl2)
нет?
- Будет ли
SHCIDS_ALLFIELDS
только появляться с SHCIDS_CANONICALONLY
? - Будет
SHCIDS_ALLFIELDS
никогда появляться с SHCIDS_CANONICALONLY
? - Может ли
SHCIDS_ALLFIELDS
появляться как с, так и без SHCIDS_CANONICALONLY
? - Что делает
SHCIDS_ALLFIELDS
с SHCIDS_CANONICALONLY
означает? - Что означает
SHCIDS_ALLFIELDS
без SHCIDS_CANONICALONLY
означает?
Что это значитхотите, чтобы я сделал, если SHCIDS_ALLFIELDS
пройден?Должен ли я нажать на базовое хранилище данных, чтобы запросить все поля , о которых я знаю?
Используются ли CompareID для сравнения идентификаторов или для сравнения объектов?
Мне было интересно, было ли назначение CompareID идентификаторами , абсолютно не попадало в основное хранилище данных (например, жесткий диск, телефон через USB, Mapi) и сравнивалось только на основе того, что у вас есть нарука в пидл.
Это имеет смысл по двум причинам:
- это быстрее;многие пространства имен содержат некоторое количество метаданных в своих BLOB-объектах PIDL - нет необходимости возвращаться на диск / Интернет
- , даже если pidls могут ссылаться на один и тот же объект, возможно, их метаданные устарели
- SHCIDS_CANONICALONLY позволяет вызывающему понять, что два pidls - это одно и то же
- , но отдельный вызов с
SHCIDS_CANONICALONLY | SHCIDS_ALLFIELDS
может сказать нам, что дополнительные метаданные могут быть устаревшими (хотя я понятия не имею, для чего эта информация используется длявызывающий)
И, возможно, SHCIDS_CANONICALONLY
означает:
- пожалуйста, ограничьте себя pidl - не трогайте диск, чтобы выполнить сравнение
- и опускание означает: «Да, вы можете нажать на жесткий диск, если вам действительно нужно»
Это так?
- Если
SHCIDS_CANONICALONLY
означает: «Не смотрите ни на что, кроме того, что написано в pidl, и скажите мне, являются ли эти две вещи одним и тем же объектом» - Что тогда получает
SHCIDS_ALLFIELDS
? - Когда они будут отличаться?
- Что спрашивает меня оболочка?
Бонусный вопрос
- Если
SHCIDS_CANONICALONLY
означает, что выполнять наиболее эффективную сортировку, - означает, что отсутствие
SHCIDS_CANONICALONLY
означает, что можно сортировать на основе локализации и настройки имени? - означает ли отсутствие
SHCIDS_CANONICALONLY
, что обязательна сортировка по локализации и настройке имени?
Что означает "сортировка" в списки itemID?
В примере SDK switch
основывается на каждом столбце и ищет значения для каждого столбца.Если это означает, что мне нужно загрузить видео из сети, чтобы загрузить частоту дискретизации звука?
- Я сравниваю PIDL
- или я сравниваю объекты, на которые указывают эти pidls?к?