打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
IShellFolder基础概念介绍

原文链接:http://blog.csdn.net/akof1314/article/details/5490921      


                    http://blog.csdn.net/liutaoxwl/article/details/3932219


   Shell即是外壳,Shell的基础是桌面,桌面之下衍生出很多子文件夹,以及系统的“网络”、“控制面板”、“C:/”等文件夹,这些文件夹里又有很多层子文件夹。这里需要用到几个接口和结构体:



  • IShellFolder接口,用来定位某个文件夹,并对其下的文件和文件夹进行操作。
  • IShellFolder2接口,从IShellFolder接口继承而来,提供了一些新的功能。
  • ItemIDList,每个文件夹或者文件都维护自己的ItemIDList,里面记录了它们的所有属性,比如文件名、类型、大小、修改时间。也就是说每个文件逻辑上都对应一个二维表,表有一个ID列,有一个值列,每行的记录用链表实现,Windows提供了ItemIDList这样的一个结构。





 



  • EnumIDList,一个文件夹下所有的对象(文件和文件夹),形成了一个有序链表。对这个链表进行遍历即可找到所有的文件。链表的每个节点就是上面的ItemIDList

可以以这样的树状结构来看上述概念:






每个实际的文件夹对应一个IShellFolder,每个IShellFolder可以获得一个EnumIDList,遍历每个EnumIDList可以获得每个ItemIDList,每个ItemIDList就已经与文件一一对应。


 


基础知识


Windows中的目录可以理解为是一个树型结构,树的根是“桌面”,“桌面”中一般拥有“我的电脑”、“网上邻居”、“回收站”等文件夹。这个我们称它为命名空间。物理上呢,“桌面”一般位于“C:/Documents and Settings/用户名称/桌面”。


IShellFolder接口用于管理文件夹,所有Shell命名空间中的文件夹对象都暴露这个接口。我们可以通过SHGetDesktopFolder方法获得“桌面”的IShellFolder接口。当然,最后不使用的时候要调用IShellFolder的Release方法释放接口。


通过调用“桌面”的IShellFolder接口的EnumObjects方法获得IENUMIDLIST接口的指针。IENUMIDLIST接口用于遍历IShellFolder接口表示的文件夹下的所有对象(这里的对象是指文件或者文件夹)。通过IENUMIDLIST接口可以遍历子对象的ITEMIDLIST数组。ITEMIDLIST数组表示一个对象的绝对或者相对路径。当前可以将ITEMIDLIST数组理解为给Shell使用的,代替我们常用的“WINDOWS/system32”这样的路径表示形式。而这里通过IENUMIDLIST接口遍历获得的IENUMIDLIST数组是一个相对路径,相对于当前IShellFolder的路径。调用IShellFolder的BindToObject方法,并传递IENUMIDLIST数组的相对路径,可以获得IENUMIDLIST数组表示的子文件夹的IShellFolder接口。这样我们可以通过递归或者循环遍历以“桌面”开始的整个逻辑目录树。


Shell命名空间


简介


下面详细介绍一下上面提到的Shell使用的路径。Shell管理的文件和文件夹有存储在磁盘上的,也有不存储在磁盘上的,如“网络打印机”、“网络邻居”、“控制面板”、“回收站”等。这些不存储在磁盘上的文件或文件夹成为虚拟对象。像“网络打印机”这样的虚拟对象,根本不需要存储在磁盘上,它只存储几个网络打印机的链接。而像“回收站”这样的虚拟对象,它位于磁盘上,但需要进行与普通文件或文件夹不同的操作。例如,虚拟对象可能在Explorer中显示的是两个对象,但它们可能被存储在同一个磁盘文件中。


      在文件系统的命名空间中,包含两种对象:文件夹对象和文件对象。文件夹对象是树的节点,它包含文件和子文件夹。文件对象是树的叶子,它可能是一个磁盘文件也可能是一个虚拟对象。如果一个文件夹不是文件系统的一部分,它通常被称为虚拟文件夹。


标识命名空间中的对象


在使用命名空间中的对象前,我们必须先标识它。由于在文件系统中文件名是可以重复使用的,所以我们使用完整限定名(完整路径),如:“C:/MyDocs/MyFile.htm”。但是这无法表示虚拟对象。所以Shell使用一种替代的标识,这个标识能够表示命名空间中所有的对象。


Item IDs


在一个文件夹中,每一个对象都有一个item ID,它等价于文件或文件夹名称的功能。item ID实际上是一个SHITEMID结构:

      typedef struct _SHITEMID

      {

            USHORT cb;

            BYTE abID[1];

      } SHITEMID, * LPSHITEMID;

      其中abID成员是对象的标识符。abID的长度没有定义。它的值由包含它的文件夹来探测。abID的大小是可变的,所以cb成员存储SHITEMID结构的字节数。


      因为item ID不是用于显示,所以包含它的文件夹通常为它分配一个“显示名称”。这个“显示名称”由Windows Explorer用来显示一个文件夹的内容。


Item ID 列表


Item ID很少单独使用,它通常是item ID列表中的一部分。item ID 列表与系统路径意义相同。但item ID 列表不是一个字符串,而是一个ITEMIDLIST结构,这个结构是一序列的item ID(一个或者多个),并由2个字节的NULL表示结束。item ID 列表中的每一个item ID 都对应命名空间中的一个对象。它们的次序表示命名空间中的路径,这很像文件系统路径。下面的图表显示了对应于“C:/MyDocs/MyFile.htm”的ITEMIDLIST的结构:




PIDLs


命名空间对象通常由ITEMIDLIST结构的指针来标识,或者指向一个item ID 列表的指针(PIDL)。为了方便,以后使用PIDL表示ITEMIDLIST结构,而不是item ID 列表的指针。上面图表显示的PIDL被称为“全的”或“完整的”PIDL。一个全的PIDL是由“桌面”开始,包含所有中间的路径的item ID。


      全PIDL不常被使用。很多函数和方法使用相对PIDL。相对PIDL的根是一个文件夹,不是“桌面”。虽然它不是一个对象的唯一标识符,但是它要比全PIDL短,并且对于某些应用来说它能够充分说明该对象。


      最常见的相对PIDL是单层PIDL,它相对于这个对象的父文件夹。它仅包含这个对象的item ID以及NULL结束符。多层的PIDL通常包含两个或更多的item ID,并且表示出了从父文件夹到这个对象的路径,这个路径中会包含中间的一些子文件夹。注意,单层PIDL也可能是一个全PIDL(如“我的电脑”相对“桌面”的相对PIDL)。特殊的,“桌面”对象是“桌面”的子文件夹。


分配PIDL


虽然PIDL与系统路径很相似,但是它们还是有一些不同。主要的不同是如何分配和销毁它们的内存。在应用中,通常是系统分配PIDL使用的保持item ID的内存,而用户释放它。


      所以,我们必须使用IMalloc接口来分配和释放PIDL。可以调用SHGetMalloc来获取IMalloc接口指针,调用IMalloc::Alloc方法来分配内存,IMalloc::Free方法来释放内存。最后调用IMalloc::Release释放指针。


 


  
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
用Delphi实现Windows文件夹管理树
如何获取资源管理器窗口的信息
VC弹出选择“文件路径”和选择“文件夹路径”对话框
引用 关于BROWSEINFO结构 - leremy163的日志 - 网易博客
文件夹浏览(SHBrowseForFolder)
VB6.0 浏览文件夹对话框 选择文件保存路径
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服