短版
什么是
SHCIDS_ALLFIELDS
标志
IShellFolder.CompareIDs
意思是?
长版
在Windows95中,微软引入了
壳
. 它不是假设计算机由文件和文件夹组成,而是由一个抽象的
命名空间
-
而不是从驱动器根目录开始的路径(例如
C:\Documents & Settings\Ian
)
-
路径从命名空间的根目录开始(
Desktop
)
为了容纳非文件和文件夹的内容(如网络打印机、控制面板、我的Android手机):
-
您不需要使用由反斜杠分隔的一系列名称(例如
丙:
\
用户
\
伊恩
)
-
你使用
皮德尔
一系列不透明的斑点(例如
桌面
这台电脑
操作系统(C:)
用户
伊恩
)
pidl是不透明的blob,每个blob只对生成它的文件夹有意义。
为了扩展(或使用)shell命名空间,可以实现(或调用)一个
IShellFolder
接口。
方法之一
IShellFolder文件夹
用于向请求命名空间扩展
比较
(PID)
:
IShellFolder::CompareIds方法
根据两个文件对象或文件夹的项标识符列表确定其相对顺序。
HRESULT CompareIDs(
[in] LPARAM lParam,
[in] PCUIDLIST_RELATIVE pidl1,
[in] PCUIDLIST_RELATIVE pidl2
);
多年来,
LPARAM
几乎总是0。从
shlobj.h
C.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.
所以你比较了两个ID列表——不管它是什么意思来比较它们,我们就这样做了。
Windows 2000添加了其他排序选项标志
从开始
版本5
外壳的16位
拉帕姆
现在可以包含其他标志来控制
IShellFolder文件夹
应该处理排序。
从
ShObjIdl.idl
c.Windows 8.1软件开发工具包:
// 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是我们拥有的最快、最有效的一种
-
从用户界面可用性的角度来看,它不必是合乎逻辑的;它只需保持一致即可。
正如陈瑞蒙指出的那样,
the moral equivalent of a Unicode
ordinal
comparison
。
头文件甚至注意到
习惯于
“最快”
排序。但现在我们要用旗子
说
“使用可用的最快排序”
:
在我们之前
SHCIDS_CANONICALONLY
我们假设列0是“高效”排序列。
它还注意到,您可以忽略lparam的低16位(即列),因为我们不在乎—我们使用的是最有效的。
很多情况都反映在官方文件中:
经典地
版本5.0。
按名称比较时,比较系统名称,但不比较显示名称。当传递此标志时,只要shell文件夹实现一致的排序函数,就可以根据shell文件夹确定的最有效的标准来比较这两个项。当比较是否相等或排序结果未显示给用户时,此标志很有用。此标志不能与其他标志组合。
但是有了希希兹·艾菲尔德,我们开始偏离轨道了。
头文件注意到
所有字段
只能与
经典地
:
只能与shcids_canoncalonly或第0列一起使用。
但软件开发工具包说
经典地
必须单独出现:
此标志不能与其他标志组合。
那是哪一个?
我们可以判断头文件是错误的,sdk是cannon,并按照它所说的做。
但是Allfields在说什么?
有一些概念认为
所有字段
是
尝试
要求,但在文件后面被掩盖。
比较itemidlist结构中包含的所有信息,而不仅仅是显示名称。
itemidlist不包含显示名称,它包含itemidlist。他们想说我应该
只有
看看pidl blob的内容?
-
例如,如果这两个项目是文件,文件夹应该比较它们的名称、大小、文件时间、属性以及结构中的任何其他信息。
在什么情况下,对*同一**文件的两个引用可以具有不同的名称、大小、文件时间、属性等?
sdk示例做了一些不同的事情
Windows SDK
资源管理器数据提供程序外壳扩展
样品(
github
)似乎表现得好像
经典地
和
所有字段
标志将同时出现:
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
}
因此,我们有完全冲突的文档、标题和示例:
所有字段
-
SDK
:不能与SHCIDS一起出现
-
邮件头
:可以随时显示
-
示例
:只能与SHCIDS一起显示
它想问什么
Windows始终假定列0是
快速的
列。这可能是因为Windows Shell API作者假定PIDL的itemID始终包含名称
里面
pidl不透明斑点。
这一点得到了加强,因为shell strret结构允许您指向pidl中的字符串。
奖励阅读:
The kooky STRRET structure
因此,在某个时刻,他们添加了一个表示:
-
我们不关心本地化、特定于区域的语言排序规则和Unicode规范化算法。
-
只需对它们进行排序,因为我们需要查找重复项并检查是否相等
这对
规范的
旗帜:
但是,当他们谈论
所有字段
选项:
如果要求我们进行全字段比较,请测试共享相同标识的项中可能不同的任何其他字段。例如:
-
如果该项表示一个文件,则标识可能只是文件名
-
但idlist中包含的其他字段可能是文件大小和文件修改日期,这些字段可能会随着时间的推移而更改。
如果两个pidl表示相同
文件
比较它们的大小、日期等有什么意义?我已经告诉过你了
文件
你要我做什么?
所有字段
旗帜?为什么我不能对这些斑点进行二进制比较呢?为什么贝壳不呢?做什么?
比较对象
做那件事
MemCmp(pidl1, pidl2)
不?
-
威尔
只有
与一起出现
经典地
?
-
意志
所有字段
从未
与一起出现
经典地
?
-
罐头
所有字段
同时出现和不出现
经典地
?
-
做什么?
所有字段
具有
经典地
意思是?
-
做什么?
所有字段
没有
经典地
意思是?
如果
所有字段
通过了吗?我应该点击底层数据存储进行查询吗
所有字段
我知道吗?
CompareID是用来比较ID,还是用来比较对象?
我想知道Compareids的目的是为了
绝对不是
点击底层数据存储区(如硬盘、USB电话、MAPI),仅根据您拥有的数据进行比较
现有
在pidl中。
这有两个原因:
-
它更快;许多命名空间在其pidl blob中包含一些元数据-无需返回磁盘/Internet
-
尽管pidl可能引用同一个对象,但它们的元数据可能已过时。
-
shcids_通常让调用者意识到两个pidl是相同的。
-
但是另一个电话
SHCIDS_CANONICALONLY | SHCIDS_ALLFIELDS
可以告诉我们额外的元数据可能已经过时了(尽管我不知道这些信息对调用者有什么用处)
或许如此
经典地
手段:
-
请将自己限制在pidl-不要触摸磁盘执行比较
-
省略意味着:
“是的,如果你真的需要,你可以点击硬盘”
是这样吗?
-
如果
经典地
手段:
“除了pidl中的内容,不要看任何东西,告诉我这两个东西是否是同一个对象。”
-
那么从中得到什么
所有字段
?
-
他们什么时候会不同?
-
壳牌在问我什么?
奖金问题
-
如果
经典地
意味着执行最有效的排序,
-
是否缺少
经典地
表示可以根据名称的本地化和自定义进行排序?
-
是否缺少
经典地
意思是
强制性的
是否根据名称的本地化和自定义进行排序?
“排序”
到itemID列表?
sdk示例执行
switch
基于每列,并查找每列的值。如果这意味着我必须通过网络加载视频才能加载音频采样率?
-
我比较皮德尔吗
-
或者我比较这些pidl指向的对象?