共用方式為


實作基本資料夾物件介面

實作命名空間擴充的程序類似於所有其他於進程內的元件物件模型(COM)物件的實作程序。 所有擴充功能都必須支援三個主要介面,以提供 Windows 檔案總管在樹視圖中顯示延伸模組資料夾所需的基本資訊。 不過,若要充分利用 Windows 檔案總管的功能,您的延伸模組也必須公開一或多個選擇性介面,以支援更複雜的功能,例如快捷功能表或拖放功能,並提供資料夾檢視。

本文件討論如何實作 Windows Explorer 呼叫的主要和選擇性介面,以取得擴充功能內容的相關信息。 如需如何實作資料夾檢視以及如何自定義 Windows 檔案總管的討論,請參閱 實作資料夾檢視

基本實作和註冊

作為同進程 COM 伺服器,您的 DLL 必須公開數個標準函式和介面:

這些函式和介面的實作方式與大部分其他 COM 物件相同。 如需詳細資訊,請參閱 COM 檔

註冊延伸模組

如同所有 COM 物件,您必須為延伸模組建立類別識別碼 (CLSID) GUID。 藉由在HKEY_CLASSES_ROOT\CLSID 中,創建一個以擴充功能的 CLSID 命名的子機碼來註冊物件。 DLL 應該註冊為進程內伺服器,並且應該指定套間線程模型。 您可以將各種子機碼和值新增至延伸模組的 CLSID 索引鍵,以自定義延伸模組根資料夾的行為。

其中數個值僅適用於具有虛擬連接點的延伸模組。 這些值不適用於其連接點為檔案系統資料夾的延伸模組。 如需進一步的討論,請參閱 指定命名空間延伸模組的位置。 若要修改具有虛擬連接點的延伸模組行為,請將下列一或多個值新增至延伸模組的 CLSID 索引鍵:

  • WantsFORPARSING。 具有虛擬連接點之延伸模組的剖析名稱通常會有格式 ::{GUID}。 此類型的擴充功能通常包含虛擬物品。 不過,有些延伸模組,例如「我的檔」,實際上會對應至文件系統資料夾,即使它們具有虛擬連接點也一樣。 如果您的延伸模組以這種方式代表文件系統物件,您可以設定 WantsFORPARSING 值。 接著,Windows 檔案總管會呼叫資料夾物件的 IShellFolder::GetDisplayNameOf 方法,將 uFlags 設定為 SHGDN_FORPARSING,並將 pidl 設定為專案標識符清單 (PIDL) 的單個空指標,以要求根資料夾的剖析名稱。 空的 PIDL 僅包含一個終止符。 然後,您的方法應該會傳回根資料夾的 ::{GUID} 剖析名稱。
  • HideFolderVerbs。 在 HKEY_CLASSES_ROOT Folder 底下註冊的\動詞通常與所有延伸模塊相關聯。 它們會出現在延伸模組的快捷方式功能表上,而且可由ShellExecute叫用 若要防止這些動詞與您的擴充功能產生關聯,請設定HideFolderVerbs值。
  • HideAsDelete。 如果使用者嘗試刪除您的延伸模組,Windows 檔案總管會改為隱藏延伸模組。
  • HideAsDeletePerUser。 這個值的效果與HideAsDelete相同,但作用於每個用戶。 只有嘗試刪除延伸模組的使用者才會隱藏。 所有其他使用者都可以看到延伸模組。
  • QueryForOverlay。 將此值設定為表示根資料夾的圖示可以有圖示重疊。 資料夾對象必須支援 IShellIconOverlay 介面。 在 Windows 檔案總管顯示根資料夾的圖示之前,它會透過呼叫 IShellIconOverlay 方法其中一個,並將 pidlItem 設定為空白 PIDL,來請求疊加圖示。

其餘值和子機碼會套用至所有擴充元件。

  • 若要指定延伸模組連接點資料夾的顯示名稱,請將延伸模組 CLSID 子機碼的預設值設定為適當的字串。
  • 當游標停留在資料夾上方時,通常會顯示描述資料夾內容的資訊提示。 若要提供延伸模組根資料夾的資訊提示,請為延伸模組的 CLSID 索引鍵建立 InfoTip REG_SZ 值,並將其設定為適當的字串。
  • 若要為擴充功能的根資料夾指定自訂圖示,請在擴充功能的 CLSID 子機碼下建立名為 DefaultIcon 的子機碼。 將 DefaultIcon預設值設定為REG_SZ值,其中包含包含圖示的檔名,後面接著逗號,後面接著減號,後面接著該檔案中圖標的索引。
  • 根據預設,擴充功能根資料夾的捷徑功能表會包含定義於 HKEY_CLASSES_ROOT\Folder 之下的項目。 如果您已設定適當的SFGAO_XXX旗標,則會新增 [刪除]、[重新命名] 和 [屬性] 專案。 您可以將其他項目新增到根資料夾的捷徑功能表,或覆寫現有項目,就像對檔案類型所做的那樣。 在擴充功能的 CLSID 索引鍵下建立 Shell 子鍵,並按照擴展快捷方式選單中的討論定義命令。
  • 如果您需要更有彈性的方式來處理根資料夾的快捷方式功能表,您可以實 作快捷方式選單處理程式。 若要註冊右鍵選單處理程式,請在延伸模組的 CLSID 鍵下建立 ShellEx 鍵。 註冊處理常式的 CLSID,就像傳統 建立殼層擴充處理常式 一樣。
  • 若要將頁面新增至根資料夾的 Properties 屬性表,請為資料夾 提供SFGAO_HASPROPSHEET 屬性並實作 屬性表處理程式。 若要註冊屬性表處理程式,請在延伸模組的 CLSID 索引鍵下建立 ShellEx 索引鍵。 註冊處理程式的 CLSID,就像傳統的 建立 Shell 擴充處理程式 一樣。
  • 若要指定根資料夾的屬性,請將ShellFolder 子機碼新增至擴展的 CLSID 子機碼。 建立一個 Attributes 值,並將其設定為適當的 SFGAO_XXX 旗標組合。

下表列出根資料夾的一些常用屬性。

旗標 說明
SFGAO_FOLDER 0x20000000 擴充功能的根資料夾包含一或多個項目。
SFGAO_HASSUBFOLDER 0x80000000 延伸模組的根資料夾包含一或多個子資料夾。 Windows 檔案總管會在資料夾圖示旁邊加上加號 (+)。
SFGAO_CANDELETE 0x00000020 用戶可以刪除延伸模組的根資料夾。 資料夾的捷徑選單將會有 刪除 項目。 這個旗標應該針對置於其中 一個虛擬資料夾下的連接點設定。
SFGAO_CANRENAME 0x00000010 延伸模組的根資料夾可由使用者重新命名。 資料夾的捷徑選單中將有一個重新命名選項
SFGAO_HASPROPSHEET 0x00000040 延伸模組的根資料夾具有 Properties 屬性表。 資料夾的快捷方式選單將會有 [屬性] 專案。 若要提供屬性表,您必須實 作屬性表處理程式。 如先前所述,在延伸模組的CLSID金鑰下註冊處理程式。

 

下列範例顯示一個擴充功能的 CLSID 註冊項目,其顯示名稱為 MyExtension。 此延伸模組具有自定義圖示,其包含在擴充功能的 DLL 中,其索引為 1。 SFGAO_FOLDERSFGAO_HASSUBFOLDERSFGAO_CANDELETE 屬性已設定。

HKEY_CLASSES_ROOT
   CLSID
      {Extension CLSID}
         (Default) = MyExtension
         InfoTip = Some appropriate text
      DefaultIcon
         (Default) = c:\MyDir\MyExtension.dll,-1
      InProcServer32
         (Default) = c:\MyDir\MyExtension.dll
         ThreadingModel = Apartment
      ShellFolder
         Attributes = 0xA00000020

處理 PIDL

Shell 命名空間中的每個項目都必須有唯一的 PIDL。 Windows 檔案總管會將 PIDL 指派給根資料夾,並在初始化期間將值傳遞至延伸模組。 接著,您的擴充功能會負責將正確建構的 PIDL 指派給每個物件,並依要求將這些 PIDL 提供給 Windows 檔案總管。 當 Shell 使用 PIDL 來識別您的延伸模組中的一個物件時,您的延伸模組必須能夠解譯 PIDL 並識別特定的物件。 您的擴充功能也必須將顯示名稱剖析名稱指派給每個物件。 因為幾乎每個資料夾介面都會使用 PIDL,擴充功能通常會實作單 一 PIDL 管理員 來處理所有這些工作。

PIDL 一詞是 ITEMIDLIST 結構或指向這類結構的指標的縮寫,具體依情境而定。 如宣告,ITEMIDLIST 結構具有單一成員,為 SHITEMID 結構。 物件的 ITEMIDLIST 結構實際上是兩個或多個 SHITEMID 結構的封裝數位。 這些結構的順序會透過命名空間定義路徑,與 c:\MyDirectory\MyFile 透過文件系統定義路徑的方式大致相同。 一般而言,物件的 PIDL 將包含一系列的 SHITEMID 結構,這些結構會對應至定義命名空間路徑的資料夾,後面接著物件的 SHITEMID 結構,後面接著終止符。

終止符是 SHITEMID 結構,cb 成員設定為 NULL 終止符是必要的,因為物件 PIDL 中的 SHITEMID 結構數目取決於 Shell 命名空間中物件的位置,以及路徑的起點。 此外,各種 SHITEMID 結構的大小可能會有所不同。 當您收到 PIDL 時,您沒有簡單的方法來判斷其大小,甚至是 SHITEMID 結構的總數。 相反地,您必須依結構來「逐步遍歷」包裝的陣列,直到到達終止符為止。

若要建立 PIDL,您的應用程式必須:

  1. 為每個物件建立 SHITEMID 結構。
  2. 將相關的 SHITEMID 結構組合成 PIDL。

建立 SHITEMID 結構

物件的 SHITEMID 結構可唯一識別其資料夾中的物件。 事實上,許多 IShellFolder 方法所使用的 PIDL 類型只包含物件的 SHITEMID 結構,後面接著終止符。 SHITEMID 結構的定義是:

typedef struct _SHITEMID { 
    USHORT cb; 
    BYTE   abID[1]; 
} SHITEMID, * LPSHITEMID;

abID 成員是對象的標識碼。 由於abID 的長度未定義且可能會有所不同,cb 成員會被設定為 SHITEMID 結構的大小(以位元組為單位)。

因為abID的長度和內容都未標準化,因此您可以使用任何您想要將abID值指派給物件的配置。 唯一的需求是,您不能在相同資料夾中有兩個具有相同值的物件。 不過,基於效能考慮,您的 SHITEMID 結構應對齊 DWORD 換句話說,您應該建構 abID 值,讓 cb 是 4 的整數倍數。

一般而言, abID 會指向延伸模組定義的結構。 除了對象的識別碼,此結構通常用來保存各種相關信息,例如對象的類型或屬性。 然後,延伸模組的資料夾物件可以快速地從 PIDL 擷取資訊,而不必查詢資訊。

注意

設計 PIDL 數據結構最重要的層面之一是讓結構可保存且可傳輸。 在 PIDL 的內容中,這些詞彙的意義如下:

  • 可持久化 系統經常將 PIDL 放在各種類型的長期記憶體中,例如快捷方式檔案。 然後,它可以稍後從記憶體復原這些 PIDL,可能是在系統重新啟動之後。 從存儲復原的 PIDL 仍然對擴充套件有效且有意義。 例如,這項需求表示您不應該在 PIDL 結構中使用句柄或指標。 當系統稍後從記憶體復原這些數據時,包含此數據類型的 PIDL 通常毫無意義。
  • 可攜帶的 從一部計算機傳輸到另一部計算機時,PIDL 必須保持有意義。 例如,PIDL 可以寫入快捷方式檔案、複製到磁碟片,並傳輸至另一部計算機。 該 PIDL 對於執行在另一台計算機上的擴充功能應該仍然有意義。 例如,若要確保您的 PIDL 可傳輸,請明確使用 ANSI 或 Unicode 字元。 避免數據類型,例如 TCHARLPTSTR。 如果您使用這些數據類型,在執行延伸模組 Unicode 版本的電腦上建立的 PIDL 將無法由在不同電腦上執行之該延伸模組的 ANSI 版本讀取。

 

下列宣告顯示數據結構的簡單範例。

typedef struct tagMYPIDLDATA {
  USHORT cb;
  DWORD dwType;
  WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;

cb 成員會設定為 MYPIDLDATA 結構的大小。 這個成員會使 MYPIDLDATA 成為本身的有效 SHITEMID 結構。 其餘成員相當於 SHITEMID 結構的 abID 成員,並保存私人數據。 dwType 成員是一個擴充定義的值,表示對象的類型。 在此範例中, dwType 會針對資料夾設定為 TRUE否則為 FALSE 。 例如,這個成員可讓您快速判斷物件是否為資料夾。 wszDisplayName 成員包含對象的顯示名稱。 由於您不會將相同的顯示名稱指派給相同資料夾中的兩個不同的物件,因此顯示名稱也會做為物件識別碼。 在此範例中, wszDisplayName 設定為 40 個字元,以確保 SHITEMID 結構會對 齊 DWORD。 若要限制 PIDL 的大小,您可以改用可變長度字元陣列,並據以調整 cb 的值。 以足夠的 『\0』 字元填補顯示字串,以維持結構的 DWORD 對齊方式。 在結構中放置可能很有用的其他成員,例如物件的大小、屬性或解析名稱。

建構 PIDL

定義物件的 SHITEMID 結構之後,您就可以使用這些結構來建構 PIDL。 PIDL 可以針對各種用途建構,但大部分的工作都使用兩種 PIDL 類型的其中一種。 最簡單的單層 PIDL 會識別相對於其父資料夾的物件。 許多 IShellFolder 方法都使用這種類型的 PIDL。 單一層級 PIDL 包含物件的 SHITEMID 結構,後面接著終止符。 完整的 PIDL 定義了從桌面到物件的名稱空間層次結構的路徑。 這種類型的 PIDL 會從桌面開始,並針對路徑中的每個資料夾包含一個 SHITEMID 結構,後面接著 對象和終止符。 完全合格的 PIDL 可唯一識別整個 Shell 命名空間內的物件。

建構 PIDL 最簡單的方式是直接使用 ITEMIDLIST 結構本身。 建立 ITEMIDLIST 結構,但配置足夠的記憶體來保存所有 SHITEMID 結構。 此結構的位址會指向初始 SHITEMID 結構。 定義這個初始結構的成員值,然後依適當順序附加許多額外的 SHITEMID 結構。 下列程式概述如何建立單一層級 PIDL。 它包含兩個SHITEMID結構——MYPIDLDATA結構,後面接著一個終止符。

  1. 使用 CoTaskMemAlloc 函式來配置 PIDL 的記憶體。 為私有數據和一個USHORT(兩個字節)終止符配置足夠的記憶體。 將結果轉換成 LPMYPIDLDATA。
  2. 將第一個 MYPIDLDATA 結構的 cb 成員設定為該結構的大小。 在此範例中,您會將 cb 設定為 sizeof(MYPIDLDATA)。 如果您想要使用可變長度結構,則必須計算 cb 的值
  3. 將適當的值指派給私人數據成員。
  4. 計算下一個 SHITEMID 結構的位址。 將目前 MYPIDLDATA 結構的位址轉換為 LPBYTE,並將該值新增至步驟 3 中決定的 cb 值。
  5. 在此情況下,下一個 SHITEMID 結構是終止符。 將結構的 cb 成員設定為零。

針對較長的 PIDLs,請配置足夠的記憶體,並針對每個額外的 SHITEMID 結構重複步驟 3-5。

下列範例函式接收物件的類型和顯示名稱,並傳回物件的單一層級 PIDL。 函式假設顯示名稱包括其終止的null字元,不會超過MYPIDLDATA結構宣告的字元數目。 如果該假設被證明是錯誤的, StringCbCopyW 函式將會截斷顯示名稱。 g_pMalloc 變數,是在其他地方創建的 IMalloc 指標,然後儲存在全域變數中。

LPITEMIDLIST CreatePIDL(DWORD dwType, LPCWSTR pwszDisplayName)
{
    LPMYPIDLDATA   pidlOut;
    USHORT         uSize;

    pidlOut = NULL;

    //Calculate the size of the MYPIDLDATA structure.
    uSize = sizeof(MYPIDLDATA);

    // Allocate enough memory for the PIDL to hold a MYPIDLDATA structure 
    // plus the terminator
    pidlOut = (LPMYPIDLDATA)m_pMalloc->Alloc(uSize + sizeof(USHORT));

    if(pidlOut)
    {
       //Assign values to the members of the MYPIDLDATA structure
       //that is the PIDL's first SHITEMID structure
       pidlOut->cb = uSize;
       pidlOut->dwType = dwType;
       hr = StringCbCopyW(pidlOut->wszDisplayName, 
                          sizeof(pidlOut->wszDisplayName), pwszDisplayName);
       
       // TODO: Add error handling here to verify the HRESULT returned 
       // by StringCbCopyW.

       //Advance the pointer to the start of the next SHITEMID structure.
       pidlOut = (LPMYPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);

       //Create the terminating null character by setting cb to 0.
       pidlOut->cb = 0;
    }

    return pidlOut;

完整的 PIDL 必須具有每個物件從桌面到您物件的 SHITEMID 結構。 當 Shell 呼叫 IPersistFolder::Initialize 時,您的延伸模組會收到根資料夾的完整 PIDL。 若要建構物件的完整 PIDL,請取得 Shell 指派給根資料夾的 PIDL,並將從根資料夾至物件路徑上的必要 SHITEMID 結構附加上去。

解譯 PIDL

當 Shell 或應用程式呼叫您的擴充功能之一的介面來請求物件資訊時,通常會透過 PIDL 識別該物件。 某些方法,例如 IShellFolder::GetUIObjectOf,使用相對於父資料夾的 PIDLs,而且很容易解譯。 不過,您的延伸模組可能也會收到完整限定的 PIDL。 然後,您的 PIDL 管理者必須判斷哪一個物件是 PIDL 所參考的。

使物件與完整 PIDL 產生關聯的工作複雜,在於 PIDL 中一或多個初始 SHITEMID 結構可能屬於位於 Shell 命名空間中延伸模組外部的物件。 您無法解譯這些結構之 abID 成員的意義。 延伸模組必須執行的唯一工作是「遍歷」SHITEMID 結構清單,直到到達對應至根資料夾的結構為止。 接著,您將瞭解如何解譯 SHITEMID 結構中的資訊。

若要遍歷 PIDL,請取得第一個 cb 值,並將它加到 PIDL 的位址上,以將指標移動到下一個 SHITEMID 結構的開頭。 然後,它會指向該結構的 cb 成員,您可以使用該成員將指標前進到下一個 SHITEMID 結構的開頭等等。 每次推進指標時,請檢查 SHITEMID 結構,以判斷您是否已到達延伸模組命名空間的根目錄。

實作主要介面

與所有 COM 對象一樣,實作擴充功能主要是實作介面集合的問題。 本節討論所有延伸模組必須實作的三個主要介面。 它們用於初始化及向 Windows 檔案總管提供擴充功能內容的基本資訊。 這些介面加上 資料夾檢視,都是功能延伸模組所需的所有介面。 不過,為了完全利用 Windows 檔案總管的功能,大部分的擴充功能也會實作一或多個選擇性介面。

IPersistFolder 介面

呼叫 IPersistFolder 介面來初始化新的資料夾物件。 IPersistFolder::Initialize 方法會將完整的 PIDL 指派給新的物件。 儲存此 PIDL 以供稍後使用。 例如,資料夾對象必須使用這個 PIDL 來建構物件子系的完整 PIDL。 資料夾物件的建立者也可以呼叫 IPersist::GetClassID 來要求物件的 CLSID。

一般而言,資料夾物件是由其父資料夾的 IShellFolder::BindToObject 方法所建立和初始化。 不過,當使用者流覽至延伸模組時,Windows 檔案總管會建立並初始化延伸模組的根資料夾物件。 根資料夾物件透過 IPersistFolder::Initialize 接收的 PIDL 包含從桌面到根資料夾的路徑,這是您在為擴充模組建構完整 PIDL 時所需的。

IShellFolder 介面

Shell 會將延伸模組視為資料夾物件的階層式排序集合。 IShellFolder 介面是任何擴充實作的核心。 它代表資料夾物件,並提供 Windows 檔案總管顯示資料夾內容所需的大部分資訊。

IShellFolder 通常是直接由資料夾物件公開的 IPersistFolder 以外的唯一資料夾介面。 雖然 Windows 檔案總管使用各種不同的必要和選擇性介面來取得資料夾內容的相關信息,但它會透過 IShellFolder 取得這些介面的指標。

Windows 資源管理器會以各種方式取得擴充功能根資料夾的 CLSID。 如需詳細資訊,請參閱 指定命名空間延伸模組的位置顯示命名空間延伸模組的獨立檢視。 Windows 檔案總管接著會使用該 CLSID 來建立和初始化根資料夾的實例,並查詢 IShellFolder 介面。 您的延伸模組會建立資料夾物件來代表根資料夾,並傳回物件的 IShellFolder 介面。 擴充功能與 Windows 檔案總管之間的互動大部分接下來會透過 IShellFolder 進行。 Windows 檔案總管會呼叫 IShellFolder 來:

  • 要求可以列舉根資料夾內容的物件。
  • 取得根資料夾內容的各種類型資訊。
  • 請求一個能公開某個可選介面的物件。 接著可以查詢這些介面以取得其他資訊,例如圖示或快捷功能表。
  • 請求一個資料夾物件來表示根資料夾下的子資料夾。

當用戶開啟根資料夾的子資料夾時,Windows 檔案總管會呼叫 IShellFolder::BindToObject 您的延伸模組會建立並初始化新的資料夾物件來表示子資料夾,並傳回其 IShellFolder 介面。 Windows 檔案總管接著會呼叫此介面以取得各種類型的資訊,等等,直到使用者決定在Shell命名空間中的其他位置巡覽,或關閉 Windows 檔案總管為止。

本節的其餘部分簡短討論較重要的IShellFolder方法,以及如何實現它們。

EnumObjects

在樹視圖中顯示資料夾的內容之前,Windows 檔案總管必須先呼叫 IShellFolder::EnumObjects 方法來判斷資料夾包含的內容。 這個方法會建立標準 OLE 列舉物件,該物件會公開 IEnumIDList 介面,並傳回該介面指標。 IEnumIDList 介面可讓 Windows 檔案總管取得資料夾包含之所有物件的 PIDL。 然後,這些 PIDL 會用來取得資料夾所包含之物件的相關信息。 如需進一步的詳細數據,請參閱 IEnumIDList 介面

注意

IEnumIDList::Next 方法應該只傳回相對於父資料夾的 PIDL。 PIDL 應該只包含物件的 SHITEMID 結構,後面接著終止符。

 

CreateViewObject

在顯示資料夾內容之前,Windows 檔案總管會呼叫此方法以請求指向 IShellView 介面的指標。 Windows 檔案總管會使用此介面來管理資料夾檢視。 建立資料夾檢視物件,並傳回其 IShellView 介面。

也會呼叫 IShellFolder::CreateViewObject 方法,以請求資料夾本身的其中一個選用介面,例如 IContextMenu。 這個方法的實作應該建立對象來公開要求的介面,並傳回介面指標。 如果 Windows 檔案總管需要資料夾中某個物件的可選介面,它會呼叫 IShellFolder::GetUIObjectOf

GetUIObjectOf

雖然資料夾內容的基本資訊可透過 IShellFolder 方法取得,但您的延伸模組也可以提供 Windows 檔案總管各種其他資訊。 例如,您可以指定資料夾或物件快捷方式功能表內容的圖示。 Windows 檔案總管會呼叫 IShellFolder 的 GetUIObjectOf 方法,嘗試擷取資料夾中包含物件的其他資訊。 Windows 檔案總管會指定它想要信息的物件,以及相關介面的 IID。 資料夾對象接著會建立物件,該物件會公開要求的介面,並傳回介面指標。

如果您的延伸模組允許使用者使用拖放或剪貼簿傳送物件,Windows 檔案總管會呼叫 IShellFolder::GetUIObjectOf 來要求 IDataObject IDropTarget 介面。 如需詳細資訊,請參閱 使用拖放和剪貼簿來傳輸殼層物件

當 Windows Explorer 想要與資料夾本身相同的資訊時,會呼叫 IShellFolder::CreateViewObject

BindToObject

當使用者嘗試開啟其中一個延伸模組的子資料夾時,Windows 檔案總管會呼叫 IShellFolder::BindToObject 方法。 如果 riid 設定為 IID_IShellFolder,您應該建立並初始化代表子資料夾的資料夾物件,並傳回物件的 IShellFolder 介面。

注意

目前,Windows 檔案總管只會呼叫此方法來要求 IShellFolder 介面。 不過,請勿假設這一律會是這種情況。 在繼續之前,您應該一律檢查 riid 的值。

 

GetDisplayNameOf

Windows Explorer 會 呼叫 IShellFolder::GetDisplayNameOf 方法,將其中一個資料夾物件的 PIDL 轉換成名稱。 該 PIDL 必須與物件的父資料夾相對。 換句話說,它必須包含單一非 NULL SHITEMID 結構。 因為命名物件的方法不止一種,Windows 檔案總管會藉由在 uFlags 參數中設定一或多個 SHGDNF 旗標來指定名稱類型。 其中一個值 SHGDN_NORMALSHGDN_INFOLDER 將被設定,用於指定名稱是相對於資料夾還是相對於桌面。 這三個值之一:SHGDN_FOREDITINGSHGDN_FORADDRESSBARSHGDN_FORPARSING,可以設置以指定名稱的用途。

您必須以 STRRET 結構的形式返回名稱。 如果未 設定SHGDN_FOREDITINGSHGDN_FORADDRESSBARSHGDN_FORPARSING ,則傳回對象的顯示名稱。 如果 SHGDN_FORPARSING 旗標已設定,Windows 檔案總管將要求剖析名稱。 剖析名稱會傳遞至 IShellFolder::ParseDisplayName 以取得物件的 PIDL,即使它可能位於命名空間階層中當前資料夾的下方的一或多個層級。 例如,檔案系統物件的剖析名稱是其路徑。 您可以將文件系統中任何物件的完整路徑傳遞至桌面的 IShellFolder::P arseDisplayName 方法,並傳回該物件的完整 PIDL。

雖然名稱在解析時是文字字串,但不必一定包含顯示名稱。 您應該根據最有效率的方法來指派剖析名稱,當呼叫IShellFolder::ParseDisplayName時。 例如,許多Shell的虛擬資料夾不是文件系統的一部分,而且沒有完整的路徑。 相反地,每個資料夾都會指派 GUID,剖析名稱的格式為 ::{GUID}。 無論您使用何種方案,它都應該能夠可靠地實現「往返」。例如,如果呼叫者將剖析名稱傳遞給 IShellFolder::ParseDisplayName 以取得物件的 PIDL,然後將該 PIDL 傳遞給 IShellFolder::GetDisplayNameOf,並設置 SHGDN_FORPARSING 旗標,呼叫者應該能夠恢復原始的剖析名稱。

GetAttributesOf

Windows 檔案總管會 調用 IShellFolder::GetAttributesOf 方法來判斷資料夾物件所包含項目的一或多個屬性。 cidl 的值會提供查詢中的項目數,而 aPidl 會指向其 PIDL 清單。

由於測試某些屬性可能很耗時,因此 Windows 檔案總管通常會藉由在 rfgInOut 中設定其值,將查詢限制為可用旗標的子集。 您的方法應該只測試那些旗標是在 rfgInOut設定的屬性。 保留有效的旗標設定,並清除其餘部分。 如果查詢中包含一個以上的專案,請只設定套用至所有專案的旗標。

注意

必須將屬性正確地設定,才能正確顯示項目。 例如,如果專案是包含子資料夾的資料夾,您必須設定 SFGAO_HASSUBFOLDER 標誌。 否則,Windows 檔案總管將不會在樹狀檢視中顯示項目圖示旁的 + 。

 

ParseDisplayName(解析顯示名稱)

IShellFolder::ParseDisplayName 方法在某種程度上是 IShellFolder::GetDisplayNameOf 的鏡像。 這個方法最常見的用途是將物件的解析名稱轉換成相關聯的 PIDL。 解析名稱可以參考名稱空間階層中資料夾下的任何物件。 傳回的 PIDL 相對於公開 方法的資料夾物件,而且通常不是完整。 換句話說,雖然 PIDL 可以包含數 個 SHITEMID 結構,但第一個結構會是物件本身或路徑中從資料夾到物件的第一個子資料夾。 呼叫端必須將此 PIDL 附加至資料夾的完整 PIDL,才能取得物件的完整 PIDL。

您也可以呼叫 IShellFolder::P arseDisplayName 來要求對象的屬性。 因為判斷所有適用的屬性可能很耗時,因此呼叫端只會設定代表 呼叫者感興趣的資訊SFGAO_XXX 旗標。 您應該判斷哪些屬性對於該物件為真,並清除其他的旗標。

IEnumIDList 介面

當 Windows 檔案總管需要列舉資料夾所包含的物件時,它會呼叫 IShellFolder::EnumObjects 資料夾對象必須建立列舉對象來公開 IEnumIDList 介面,並傳回該介面指標。 然後,Windows 檔案總管通常會使用 IEnumIDList 列舉資料夾包含之所有物件的 PIDL。

IEnumIDList 是標準 OLE 列舉介面,並以一般方式實作。 不過,請記住,您傳回的 PIDL 必須相對於資料夾,且只包含物件的 SHITEMID 結構和終止符。

實作選擇性介面

擴充功能的資料夾物件可以支援多種可選擇的 Shell 介面。 其中許多專案,例如 IExtractIcon,可讓您自定義用戶檢視延伸模組的各種層面。 其他專案,例如 IDataObject,可讓您的延伸模組支援拖放等功能。

任何選擇性介面都不會由資料夾物件直接公開。 相反地,Windows Explorer 會呼叫兩 個 IShellFolder 方法的其中一個來要求介面:

為了提供資訊,資料夾物件會建立對象來公開要求的介面,並傳回介面指標。 然後,Windows 檔案總管會呼叫該介面來擷取所需的資訊。 本節討論最常用的選擇性介面。

IExtractIcon

Windows 檔案總管會先要求 IExtractIcon 介面,再顯示資料夾的內容。 介面可讓您的延伸模組指定資料夾所包含物件的自訂圖示。 否則,將會使用標準檔案和資料夾圖示。 若要提供自訂圖示,請建立一個圖示擷取物件,該物件需公開 IExtractIcon 並傳回指向該介面的指標。 如需進一步的討論,請參閱 IExtractIcon 參考檔或建立圖示處理程式

IContextMenu

當使用者以滑鼠右鍵按兩下物件時,Windows 檔案總管會要求 IContextMenu 介面。 若要提供物件的快捷功能表,請建立功能表處理程式物件並傳回其 IContextMenu 介面。

建立功能表處理程式物件的程式與用來建立功能表處理程式殼層延伸模組的程式非常類似。 如需詳細資訊,請參閱建立操作功能表處理程式IContextMenuIContextMenu2 IContextMenu3 參考。

IQueryInfo

Windows 檔案總管會 呼叫 IQueryInfo 介面來擷取資訊提示文字字串。

IDataObject 和 IDropTarget

當 Windows 檔案總管顯示您的物件時,資料夾物件無法直接知道使用者何時嘗試剪下、複製或拖曳物件。 相反地,Windows 檔案總管會要求 IDataObject 介面。 若要允許傳送物件,請建立數據物件,並傳回其 IDataObject 介面的指標。

同樣地,使用者可能會嘗試將數據物件拖放到 Windows 檔案總管中表示您物件之一的介面上,例如圖示或網址列路徑。 Windows 檔案總管接著會要求 IDropTarget 介面。 若要允許拖放資料物件,請建立一個公開 IDropTarget 介面並傳回介面指標的物件。

處理數據傳輸是寫入命名空間延伸模組的其中一個棘手層面。 如需詳細討論,請參閱 使用拖放和剪貼簿傳輸殼層物件

使用預設 Shell 資料夾檢視實作

使用預設 Shell 資料夾檢視物件 (DefView) 的資料來源必須實作這些介面:

如果需要,他們也可以實作IPersistFolder3