翻譯自MSDN 2005 -> Win32 和 COM 開發 -> User Interface -> Windows User Experience -> Windows Shell -> Shell Programmer's Guide -> Shell Basics -> Shell Basics: Programming the Shell -> Getting Information About the Contents of a Folder
Getting a Folder's ID 討論了兩種獲取Shell對象PIDL的方法。一個顯然的問題是:獲取PIDL后,可以用它做什么?一個相關問題是:哪種方法可以用於你的程序,或者適合 你的程序?要回答這兩個問題需要更深入考察下名字空間是如何實現的。名字空間實現的關鍵是IShellFolder接口。
使用IShellFolder接口
前面的文檔中,名字空間文件夾被稱作“對象”。這個術語的使用好像不太嚴格,但實際上從嚴格意義上講,這個術語也是合適的,因為每個名字空間文件夾都由一 個COM對象表示。每個文件夾對象實現了很多可以用於各種任務的接口。有些接口是可選的,不是每個文件夾都實現了,但每個文件夾都必須實現基本接口IShellFolder 。
要使用文件夾,首先需要獲取其IShellFolder 接口指針。IShellFolder接口指針除了可以提供對對象其他接口的訪問外,還提供了處理很多通常任務的方法,本文將討論某些通常任務。
要獲取Shell對象的IShellFolder 接口指針,首先調用SHGetDesktopFolder ,它會返回名字空間根,即桌面的IShellFolder 接口指針。獲取了桌面對象的IShellFolder接口指針后,有很多方法進行下一步。
如果已經有要處理的文件夾的PIDL了(比如說,通過SHGetFolderLocation 獲取的),可以用桌面對象的(IShellFolder接口指針的)BindToObject 方法獲取文件夾的IShellFolder 接口指針。如果已經有文件系統對象的路徑了,可以先用桌面對象的ParseDisplayName 方法獲取其PIDL,然后再調用BindToObject 。如果這兩種方法都不可用,可以用IShellFolder 的其他方法瀏覽名字空間(並定位到要處理的文件夾),詳情請參考Navigating the Namespace 。
枚舉文件夾內容
文件夾處理的第一件事通常是看看它包含什么內容,這時可以先調用文件夾的EnumObjects 方法。方法會創建標准OLE枚舉對象並返回其IEnumIDList 接口。枚舉接口含有4個標准方法:Clone 、Next 、Reset 、Skip 。這些方法可用於枚舉文件夾內容。
枚舉文件夾內容的基本過程是:
-
調用 EnumObjects 方法獲取枚舉對象的 IEnumIDList 接口
-
調用 IEnumIDList 的 Next 方法,傳入一個未分配的PIDL。 Next 會為PIDL分配內存,但須由調用方釋放分配的內存。 Next 返回的PID只含有對象的item ID和表示結束的NULL字符。也就是說,返回的是相對於所在文件夾的單層PIDL,不是全限定PIDL。
-
重復步驟2直到 Next 方法返回 S_FALSE ,這表示所有內容條目已經枚舉完成。
-
調用 IEnumIDList::Release 釋放枚舉對象。
注意:要注意當前使用的是相對PIDL還是全限定PIDL。某些函數可以接受兩種類型的PIDL,但是有些卻只能接受一種類型的。IEnumIDList的另外3個方法可用於重復枚舉文件夾內容。這3個方法可以復位枚舉過程、跳過一個或者多個對象、制作枚舉對象的副本以保存其狀態。
確定顯示名和其他屬性
在枚舉了文件夾包含的所有PIDL后,就可以發現它們所代表的對象類型。IShellFolder 接口提供了很多有用的方法,這里只討論兩個。IShellFolder 接口的其他方法和其他Shell文件夾接口在本系列后面的文章中討論。
顯示名是對象的最重要屬性之一。要獲取對象的顯示名,把PIDL傳遞給GetDisplayNameOf 即可。對象可以位於名字空間中父文件夾以下的任何地方,但PIDL必須是相對於父文件夾的。
GetDisplayNameOf 把顯示名作為STRRET 對象的一部分返回。因為從STRRET 結構取出顯示名需要一點技巧,所以Shell為你提供了兩個函數,StrRetToStr 和StrRetToBuf 。這兩個函數都需要一個STRRET 結構體,把顯示名作為普通字符串返回。它們的不同在於字符串是如何分配的。
除了顯示名外,對象還可以有很多其他屬性,比如說,對象是否是文件夾,是否可以被移動。把對象的PIDL傳給GetAttributesOf 就可以獲取其屬性。完整的屬性列表很長,細節可以參考相關文檔。注意傳遞給GetAttributesOf 的PIDL必須是單層的。特別是,GetAttributesOf 可以接受Next 返回的PIDL。可以傳入一個PIDL數組,GetAttributesOf 會返回數組中所有對象共有的屬性。
如果有對象的全限定路徑名或者PIDL,SHGetFileInfo 提供了一種獲取足夠用於多種目的的對象信息的簡單方法。SHGetFileInfo 返回的信息包括:
-
對象的顯示名
-
對象屬性
-
對象圖標句柄
-
系統圖像列表句柄
-
包含對象圖標的文件的路徑
獲取子文件夾的IShellFolder接口指針
調用GetAttributesOf ,檢查SFGAO_FOLDER 標志是否已設置就可以確定文件夾是否含有子文件夾。如果對象是文件夾,就可以綁定到它,這可以提供對象的IShellFolder 接口。
要綁定到文件夾,調用父文件夾的BindToObject 方法。方法要求傳入子文件夾的PIDL,並返回其IShellFolder 接口指針。有了這個指針后,就可以枚舉文件夾的內容,確定其屬性等。
確定對象的父文件夾
如果已有某對象的PIDL,可能需要其父文件夾暴露的某個接口。比如說,如果想用GetDisplayNameOf 確定父文件夾的顯示名,必須先獲取父對象的IShellFolder 接口。可以用上一節討論的技術來達到目的,但有一種更簡單的方法,就是使用SHBindToParent 方法。這個方法要求傳入對象的全限定PIDL,並且返回父文件夾的特定接口指針。SHBindToParent 還可以返回對象的單層PIDL以用於GetAttributesOf 等方法。
下面的示例控制台應用程序獲取系統特別文件夾的PIDL,並且返回其顯示名。
#include <shlobj.h>
|
應用程序首先獲取Shell分配器的 IMalloc 接口指針,並且用 SHGetFolderLocation 獲取系統文件夾的PIDL。然后程序調用 SHBindToParent 獲取系統文件夾父文件夾的 IShellFolder 接口,以及相對於父文件夾的PIDL。然后使用父文件夾的 GetDisplayNameOf 方法獲取系統文件夾的顯示名。
對於GetDisplayNameOf返回的STRRET結構體,可以用StrRetToBuf把顯示名轉換成普通字符串。在顯示了顯示名后,接口指針和系統PIDL都被釋放。注意不能釋放SHBindToParent返回的相對PIDL。
本文轉載自:http://blog.sina.com.cn/s/blog_56dee71a0100frhy.html
http://blog.csdn.net/akof1314/article/details/5490985