共用方式為


取得資料夾內容的相關信息

取得資料夾識別碼 一節討論了取得命名空間物件指標至專案標識碼清單 (PIDL) 的兩種方法。 一個明顯的問題是:一旦您有 PIDL,可以用它做些什麼呢? 相關問題是:如果方法都無法運作,或不適合您的應用程式,該怎麼辦? 這兩個問題的解答需要進一步瞭解命名空間的實作方式。 關鍵是 IShellFolder 介面。

使用 IShellFolder 介面

在此文件的前面部分,命名空間資料夾被稱為物件。 雖然在這一點上,這個詞在鬆散的意義上被使用,但實際上在嚴格的意義上也是真的。 每個命名空間資料夾都會以元件物件模型 (COM) 物件表示。 每個資料夾物件都會公開許多介面,這些介面可用於各種不同的工作。 某些選擇性的介面可能不會由所有資料夾公開。 不過,所有資料夾都必須公開基本介面,IShellFolder

使用資料夾物件的第一步是取得其 IShellFolder 介面的指標。 除了提供物件其他介面的存取權之外,IShellFolder 也會公開一組處理一些常見工作的方法,本節會討論其中幾個工作。

若要擷取命名空間物件的 IShellFolder 介面指標,您必須先呼叫 SHGetDesktopFolder。 此函式會傳回命名空間根目錄(即桌面)的 IShellFolder 介面的指標。 一旦您擁有桌面的 IShellFolder 介面,有各種不同的方式可以繼續進行。

如果您已經有您感興趣的資料夾 PIDL,例如藉由呼叫 SHGetFolderLocation,您可以呼叫桌面的 IShellFolder::BindToObject 方法來擷取其 IShellFolder 介面。 如果您有文件系統對象的路徑,您必須先呼叫桌面的 IShellFolder::P arseDisplayName 方法,然後呼叫 IShellFolder::BindToObject來取得其 PIDL。 如果這兩種方法都不適用,您可以使用其他 IShellFolder 方法來巡覽命名空間。 如需詳細資訊,請參閱 瀏覽命名空間

列舉資料夾的內容

您通常想要使用資料夾做的第一件事是找出其包含的內容。 您必須先呼叫資料夾的 IShellFolder::EnumObjects 方法。 資料夾會建立標準 OLE 列舉物件,並傳回其 IEnumIDList 介面。 此介面會公開四個標準方法:CloneNextResetSkip,可用來列舉文件夾的內容。

列舉資料夾內容的基本程式為:

  1. IShellFolder::EnumObjects 方法呼叫資料夾,以擷取列舉物件的 IEnumIDList 介面指標。
  2. 將未分配的 PIDL 傳遞至 IEnumIDList.Next下一個 負責配置 PIDL,但應用程式必須在不再需要時解除分配。 當 Next 傳回時,PIDL 只會包含物件的項目ID和終止 NULL 字元。 換句話說,它是相對於資料夾的單層 PIDL,而不是完整 PIDL。
  3. 重複步驟 2,直到 Next 傳回 S_FALSE,表示所有項目都已列舉。
  4. 呼叫 IEnumIDList::Release 來釋放列舉物件。

注意

請務必追蹤您使用的是完整或相對 PIDL。 某些函式和方法會接受其中一種,但其他函式只會接受其中一個或另一個函式。

 

其餘三個 IEnumIDList 方法(ResetSkipClone)在您需要重複列舉資料夾時很有用。 它們可讓您重設列舉、略過一或多個物件,並建立列舉對象的複本來保留其狀態。

判斷顯示名稱和其他屬性

列舉資料夾所包含的所有 PIDL 之後,您就可以找出它們所代表的物件類型。 IShellFolder 介面提供一些實用的方法,其中兩個會在這裡討論。 稍後會討論其他 IShellFolder 方法和其他 Shell 資料夾介面。

其中一個最有用的屬性是對象的顯示名稱。 若要擷取對象的顯示名稱,請將其 PIDL 傳遞給 IShellFolder::GetDisplayNameOf。 雖然物件可以位於命名空間中父資料夾下方的任何位置,但其 PIDL 必須相對於資料夾。

IShellFolder::GetDisplayNameOf 會傳回顯示名稱,做為 STRRET 結構的一部分。 因為從 STRRET 結構擷取顯示名稱可能會有些麻煩,Shell 提供了兩個函式協助您完成這項工作:StrRetToStrStrRetToBuf。 這兩個函式都會採用 STRRET 結構,並將顯示名稱傳回為一般字串。 它們只會在字串的配置方式上有所不同。

除了其顯示名稱之外,物件還可以有數個屬性,例如是否為資料夾或是否可以移動。 您可以藉由將 PIDL 傳遞至 IShellFolder::GetAttributesOf來擷取對象的屬性。 屬性的完整清單相當龐大,因此您應查閱參考資料來獲取詳情。 請注意,您傳遞給 GetAttributesOf 的 PIDL 必須是單一層級。 特別是,IShellFolder::GetAttributesOf 會接受 IEnumIDList::Next所傳回的 PIDL。 您可以傳入 PIDL 陣列,GetAttributesOf 會傳回陣列中所有物件通用的屬性。

如果您有物件的完整路徑或 PIDL,SHGetFileInfo 提供簡單的方式來擷取物件的資訊,足以滿足許多需求。 SHGetFileInfo 接受完整路徑或 PIDL,並返回關於該物件的多種信息,包括:

  • 對象的顯示名稱
  • 對象的屬性
  • 對象圖示的句柄
  • 系統映像清單的控制代碼
  • 包含物件圖示的檔案路徑

取得子資料夾的 IShellFolder 介面指標

您可以呼叫 IShellFolder::GetAttributesOf,並檢查是否已設定SFGAO_FOLDER旗標,以判斷資料夾是否包含任何子資料夾。 如果物件是資料夾,您可以綁定至該資料夾,從而獲得其 IShellFolder 介面的指標。

若要系結至子資料夾,請呼叫父資料夾的 IShellFolder::BindToObject 方法。 這個方法會採用子資料夾的 PIDL,並傳回其 IShellFolder 介面的指標。 擁有此指標之後,您可以使用 IShellFolder 方法來列舉子資料夾內容、判斷其屬性等等。

判斷物件的父資料夾

如果您有某個物件的 PIDL,您可能需要指標來獲取其父資料夾所提供的其中一個介面。 例如,如果您想要使用 IShellFolder::GetDisplayNameOf來判斷與 PIDL 相關聯的顯示名稱,必須先從物件的父物件擷取 IShellFolder 介面。 使用上一節所討論的技術,可以執行這項作。 不過,最簡單的方法是使用Shell函式,SHBindToParent。 此函式會接收物件的完整 PIDL,並傳回父資料夾中指定的介面指標。 選擇性地,它也會傳回項目的單一層級 PIDL,以用於 IShellFolder::GetAttributesOf等方法。

下列範例控制台應用程式會擷取 System 特殊資料夾的 PIDL,並傳回其顯示名稱。

#include <shlobj.h>
#include <shlwapi.h>
#include <iostream.h>
#include <objbase.h>

int main()
{
    IShellFolder *psfParent = NULL;
    LPITEMIDLIST pidlSystem = NULL;
    LPCITEMIDLIST pidlRelative = NULL;
    STRRET strDispName;
    TCHAR szDisplayName[MAX_PATH];
    HRESULT hr;

    hr = SHGetFolderLocation(NULL, CSIDL_SYSTEM, NULL, NULL, &pidlSystem);

    hr = SHBindToParent(pidlSystem, IID_IShellFolder, (void **) &psfParent, &pidlRelative);

    if(SUCCEEDED(hr))
    {
        hr = psfParent->GetDisplayNameOf(pidlRelative, SHGDN_NORMAL, &strDispName);
        hr = StrRetToBuf(&strDispName, pidlSystem, szDisplayName, sizeof(szDisplayName));
        cout << "SHGDN_NORMAL - " <<szDisplayName << '\n';
    }

    psfParent->Release();
    CoTaskMemFree(pidlSystem);

    return 0;
}

應用程式會先使用 SHGetFolderLocation 來擷取 System 資料夾的 PIDL。 然後它會呼叫 SHBindToParent,這會傳回父資料夾 IShellFolder 介面的指標,以及系統資料夾的 PIDL(相對於其父資料夾)。 然後,它會使用父資料夾的 IShellFolder::GetDisplayNameOf 方法來擷取 System 資料夾的顯示名稱。 因為 getDisplayNameOf 會傳回 STRRET 結構,StrRetToBuf 用來將顯示名稱轉換成一般字串。 顯示名稱之後,介面指標會被釋放,系統 PIDL 也會被清除。 請注意,您不得釋放 SHBindToParent所返回的相對 PIDL。