詳細解釋一下 Shell 編程中最基本的一些函數、結構體和枚舉。
SHGetDesktopFolder
擷取案頭的 IShellFolder 介面
[DllImport("shell32.dll")]
public static extern Int32 SHGetDesktopFolder(out IntPtr ppshf);
要使用這個函數,必須先定義一個 IntPtr 指標。然後通過指標,使用 GetObjectForIUnknown 返回通過指向 COM 物件的 IShellFolder 介面的指標執行個體。於是需要編寫以下函數:
代碼
public static IShellFolder GetDesktopFolder(out IntPtr ppshf) {
SHGetDesktopFolder(out ppshf);
Object obj = Marshal.GetObjectForIUnknown(ppshf);
return (IShellFolder)obj;
}
ParseDisplayName
獲得對象的PIDL,即便對象在分類樹中處於目前的目錄下一層或更多層。例如,對於檔案對象來說,它的解析名就是它的路徑,我們用檔案系統對象的完全路徑名來調用案頭的IshellFolder介面的 ParseDisplayName 方法,它會返回這個對象的完全PIDL。定義:
代碼
void ParseDisplayName(
IntPtr hwnd,
IntPtr pbc,
[MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
out uint pchEaten,
out IntPtr ppidl,
ref uint pdwAttributes);
裡面最重要的參數就是 out IntPtr ppidl 了,它返回 pszDisplayName 指定路徑對應的 PIDL。然而僅僅是 PIDL 並不能讓你做更多的事情。這時候還需要調用 BindToObject 來返回 IShellFolder 介面。
BindToObject
根據 PIDL 建立和初始化 IShellFolder 對象。定義:
void BindToObject(
IntPtr pidl,
IntPtr pbc,
[In()] ref Guid riid,
out IShellFolder ppv);
裡面有一個 [In()] ref Guid riid 參數,表示介面的介面標識符 (IID)。GUID其實就是一個唯一的標識符。世界上的任何兩台電腦都不會產生重複的 GUID 值。GUID 主要用於在擁有多個節點、多台電腦的網路或系統中,分配必須具有唯一性的標識符。我們這裡使用 IID_IShellFolder 表示它擷取的是一個 IShellFolder 介面。
public static Guid IID_IShellFolder = new Guid("{000214E6-0000-0000-C000-000000000046}");
另外介紹 IEnumIDList 介面。IEnumIDList 介面使資源管理員獲得檔案夾包含的全部對象的PIDL,PIDL然後可以用來獲得這些對象的資訊。
因此,我們使用 EnumObjects 函數返回的將是 IEnumIDList 的指標:
int EnumObjects(IntPtr hWnd, SHCONTF flags, out IntPtr enumIDList);
其中 flags 是 SHCONTF 枚舉類型,它決定了枚舉的內容:
代碼
public enum SHCONTF {
FOLDERS = 0x20,
NONFOLDERS = 0x40,
INCLUDEHIDDEN = 0x80,
INIT_ON_FIRST_NEXT = 0x100,
NETPRINTERSRCH = 0x200,
SHAREABLE = 0x400,
STORAGE = 0x800
}
因此,我們可以通過 flags 的不同來分別列舉子檔案和子目錄。這裡會遇到一個問題,怎麼擷取 PIDL 對象的名稱呢。這裡編寫了2個函數,可以通過 PIDL 或者 IShellFolder 返回對象的名稱。