From MSDN 翻译 By Hendy
位置:MSDN Library - October 2001/Platform SDK Documentation/User Interface Services/Windows Shell/Shell Programmers Guide/Shell Basics/The Shell Namespace
外壳名字空间
外壳名字空间将文件系统及其它的一些同外壳管理的对象组织成一个单一的树状层次结构。从概念上来说,它是文件系统的一个更大的、更广泛的一个概念。
简介:
外壳的一个主要功能是管理组成系统的各种各样的对象以及提供对这些对象的访问(方法)。(我们平常)见得最多和最熟悉的对象就是那些计算机磁盘上的文件及文件夹了。然而,外壳还管理着很多的无文件系统,或者说“虚拟”对象。比如:
·网络打印机
·其它网络计算机
·控制面板应用程序
·回收站
一些虚拟对象根本不战胜物理存储。比如打印机对象,它包含对网络打印机的链接的一些集合。其它的一些虚拟对象,比如回收站,可能包含一些存储在磁盘上的数据,但是这些数据必须与普通的文件区别对待。例如,一个虚拟对象可以用来表示存储在数据库中的数据。从名字空间的角度来看,虽然数据库中不同的项是存储在同一个磁盘文件中,但它们在资源管理器可能以不同的对象出现。
虚拟对象甚至可能位于远程计算机上。比如,为了便于浏览,用户的文档可能存储在一台服务器上。为了能使用户能从不同的个人计算机上访问这些文档,这些个人计算机上的“我的文档”目录可以指向服务器而不是本地的硬盘。文档的路径可以是一个映射的网络磁盘驱动器或者统一的路径名(UNC)。
同普通的文件系统一样,名字空间也包含两种基本的对象:文件夹和文件。文件夹对象是树的“结点”,它们是文件及其它文件夹的一个容器。文件对象是树的“叶子”,它们可以是普通的磁盘文件,也可以是虚拟对象,如打印机链接。那些不属于文件系统的文件夹有时候可称为“虚拟文件夹”。
像文件系统的文件夹一样,虚拟文件夹通常随系统的不同而不同。虚拟文件夹有以下的三类:
·标准的虚拟文件夹,比如回收站,它们可以在所有的系统中找到
·可选的虚拟文件夹,它们有标准的名字和功能,但是不是所有的系统中都有
·非标准的文件夹,它们是由用户安装的
与普通的文件夹不同的是,用户不能自己创建虚拟文件夹。它们只能由第三方的开发者创建。因此,虚拟文件夹的数量要比文件系统中的文件夹少得多。关于如何实现虚拟文件夹的讨论可参见:Creating a Shell Namespace Extension.(位置是:MSDN Library - October 2001/Platform SDK Documentation/User Interface Services/Windows Shell/Shell Programmers Guide/Advanced Shell Techniques/Creating a Shell Namespace Extension)
你可以通过查看Windows资源管理器的浏览栏看到名字空间结构的可视化的表示。例如:下面的Windows资源管理器截屏显示了相关的一些简单的名字空间。
名字空间最顶层的树根是桌面。紧接着树根下面的是几个虚拟文件夹,比如“我的电脑”和“回收站”等到。
在整个大的名字空间里可以看到各个磁盘驱动器的文件系统的了集。文件系统是“我的电脑”(虚拟)文件夹的了文件夹。我的电脑同样包含任何一个映射的网络磁盘驱动器的树根。其它的权树的结点,比如“我的文档”,是虚拟文件夹。
标识名字空间对象
在你能使用一个名字空间对象之前,你必须找到标识它的方法。文件系统中的一个对象可以使用名字比如MyFile.htm标识。因为在系统的其它地方可能会有同名的文件,因此唯一标识一个文件或文件夹需要一个全路径名,如:C:\MyDocs\MyFile.htm。全路径是从文件系统树根(C:\)开始的路径上所有的文件夹的一个有序的序列,它以文件名结束。
在名字空间的上下文中,路径对于标识名字空间中文件系统部分中的对象仍然非常有用。然而,它们不能用来标识虚拟对象。取而代之的是,外壳提供了另外一个方法,它可以标识任何一个名字空间对象。
项目ID
在一个文件夹中,任何一个对象都有一个项目ID,这在功能上等价于文件名或文件夹名。这个项目ID实际上是一个SHITEMID结构:
typedef struct _SHITEMID {
USHORT cb;
BYTE abID[1];
} SHITEMID, * LPSHITEMID;
其中,abID成员是对象的标识。abID的长度没有定义,它的值由包含它的文件夹决定。由于没有一个标准规定应该如何由文件夹来指定abID的值,因此它只对与之相关联的文件夹对象有意义。应用程序应该只是简单地把它们看作标识特定文件夹中对象的一个标记。又由于abID的长度是不定的,成员变量cb用来保存SHITEMID结构的大小(以字节为单位)。
由于项目ID对于显示来说没什么用,包含对象的文件夹通常为对象指定一个用于显示的名称。这就是Windows资源管理器在显示文件夹内容时用的名称。关于如何处理显示名称,参见: Getting Information From a Folder(位置:MSDN Library - October 2001/Platform SDK Documentation/User Interface Services/Windows Shell/Shell Programmers Guide/Shell Basics/Shell Basics: Programming the Shell/Getting Information From a Folder)
项目ID链表
项目ID很少被自身所用到。通常,它是项目ID链表的一部分。ID链表的作用和文件系统的路径是一样的。然而,路径用的是字符表示的,而项目链表是一个ITEMIDLIST结构。这个结构是一个或多个项目ID的有序序列,以两上NULL结束。ID链表中的每一个ID都对应着一个名字空间对象。它们的顺序就表明了在名字空间中的路径,这同文件系统的路径是一样的。
下面的图用图示表示了C:\MyDocs\MyFile.htm的ITEMIDLIST结构。每个项目ID的显示名称在它的上方。abID成员的变宽是不定的,它们表明了abID的大小是可以变化的。
My Computer C:/ MyDocs MyFile.htm
┎───────┰────┰──────┰────┰──────┒
┃cb ┆ abID ┃cb┆abID┃cb┆ abID ┃cb┆abID┃2-byte NULL ┃
┖───────┸────┸──────┸────┸──────┚
PIDLs
对于Shell API,名字空间对象通常是用ITEMIDLIST结构的指针标识的,即PIDL。为方便起见,在这篇文档里,将用PIDL表示这个结构本身而还表示指针。
在前面的图示中所显示的PIDL是全路径PIDL或者说是绝对路径的PIDL。全路径PIDL是从桌面开始的,并且它包含了全路径中间的所有文件夹的ID。全路径PIDL由对象的项目ID结束,并且紧接着是两个NULL。全路径PIDL与全路径是类似的,它唯一标识了外壳名字空间中的一个对象。
全路径PIDL是经常被用到的。许多函数及方法都需要一个相对的PIDL(作为参数)。相对PIDL的根是一个文件夹而不是桌面。同相对路径一样,组成相对PIDL结构的一系列项目ID定义了名字空间中两个对象之间路径。尽管他们不能唯一标识一个对象,但是他们通常可比全路径PIDL小一些而且在很多情况下是够用的。
最常用的相对PIDL是一级结构的PIDL,它是相对于对象父文件夹的。它只包含对象本身的ID并且以NULL结束。多级的PIDL在很多情况下也被用到。它们包含两个或两个以上的项目ID,定义了经过一系列的子文件夹从(某级)父文件夹到对象的路径。注意一个一级的PIDL也可以是一个全路径PIDL。特别的,桌面对象是桌面的子对象,因此它们的全路径PIDL就只包含一个项目ID。
就像在Getting a Folder's ID(位置:MSDN Library - October 2001/Platform SDK Documentation/User Interface Services/Windows Shell/Shell Programmers Guide/Shell Basics/Shell Basics: Programming the Shell/Getting a Folder's ID)专题中计论的,Shell API提供了多条途径取得对象的PIDL。一旦你取得了PIDL,你通常只是在你调用其它Shell API函数及方法时用它标识一个对象。在这篇文档中,PIDL的内涵是不透明和无关的。在这种情况下,将PIDL想象成代表特定名字空间对象的标识,并且将注意力集中到在平时的任务中如何使用它们。
分配PIDL
尽管PIDL与路径有一些相似,使用它们需要稍微不同的步骤。最主要的不同在于如何分配及释放它们的内存。
像路径中的字符串一样,我们必须为PIDL分配内存。如果应用程序要创建一个PIDL,它必须为ITEMIDLIST结构分配足够的内存。在这里讨论的大部分情况下,由外壳创建和处理内存分配。不管谁分配PIDL,当它们不再使用时,都应该由应用程序释放PIDL。
为了分配和释放PIDL,你必须使用外壳分配器提供的IMalloc接口。你可以使用SHGetMalloc得到这个接口。使用IMalloc::Alloc方法分配PIDL,使用IMalloc::Free方法释放它。在Getting a Folder's ID(位置:MSDN Library - October 2001/Platform SDK Documentation/User Interface Services/Windows Shell/Shell Programmers Guide/Shell Basics/Shell Basics: Programming the Shell/Getting a Folder's ID)章节,有一个如何使用这个接口处理外壳内存分配的例子。
|