取得文件夾內容信息(使用IShellFolder接口)


翻譯自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 。這些方法可用於枚舉文件夾內容。

枚舉文件夾內容的基本過程是:

  1. 調用 EnumObjects 方法獲取枚舉對象的 IEnumIDList 接口
  2. 調用 IEnumIDList 的 Next 方法,傳入一個未分配的PIDL。 Next 會為PIDL分配內存,但須由調用方釋放分配的內存。 Next 返回的PID只含有對象的item ID和表示結束的NULL字符。也就是說,返回的是相對於所在文件夾的單層PIDL,不是全限定PIDL。
  3. 重復步驟2直到 Next 方法返回 S_FALSE ,這表示所有內容條目已經枚舉完成。
  4. 調用 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>
#include <shlwapi.h>
#include <iostream.h>
int main()
{
    LPMALLOC pMalloc = NULL;
    IShellFolder *psfParent = NULL;
    LPITEMIDLIST pidlSystem = NULL;
    LPCITEMIDLIST pidlRelative = NULL;
    STRRET strDispName;
    TCHAR szDisplayName[MAX_PATH];
    HRESULT hr;


    hr = SH GetMalloc_r(&pMalloc);
    hr = SH GetFolderLocation_r(NULL, CSIDL_SYSTEM, NULL, NULL, &pidlSystem);
    hr = SHBindToParent(pidlSystem, IID_IShellFolder, (void **) &psfParent, &pidlRelative);
    if(SUCCEEDED(hr))
    {
        hr = psfParent-> GetDisplayNameOf_r(pidlRelative, SHGDN_NORMAL, &strDispName);
        hr = StrRetToBuf(&strDispName, pidlSystem, szDisplayName, sizeof(szDisplayName));
        cout << "SHGDN_NORMAL - " <<szDisplayName << '/n';
    }
    psfParent->Release();
    pMalloc->Free(pidlSystem);
    pMalloc->Release();
    return 0;
}


   應用程序首先獲取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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM