Windows Shell programming, that is, Windows Shell programming. The resource manager and the entire desktop are a Shell.
We know that in win32, a file system is organized in the form of a shell namespace. Every object in the shell namespace (Note) implements an IShellFolder interface, through this interface, we can directly query or indirectly obtain other related interfaces.
Run the following program to browse folders:
In C #, we define the IShellFolder interface as follows:
Code
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("000214E6-0000-0000-C000-000000000046")]
public interface IShellFolder {
void ParseDisplayName(
IntPtr hwnd,
IntPtr pbc,
[MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
out uint pchEaten,
out IntPtr ppidl,
ref uint pdwAttributes);
[PreserveSig]
int EnumObjects(IntPtr hWnd, SHCONTF flags, out IntPtr enumIDList);
void BindToObject(
IntPtr pidl,
IntPtr pbc,
[In()] ref Guid riid,
out IShellFolder ppv);
void BindToStorage(
IntPtr pidl,
IntPtr pbc,
[In()] ref Guid riid,
[MarshalAs(UnmanagedType.Interface)] out object ppv);
[PreserveSig()]
uint CompareIDs(
int lParam,
IntPtr pidl1,
IntPtr pidl2);
void CreateViewObject(
IntPtr hwndOwner,
[In()] ref Guid riid,
[MarshalAs(UnmanagedType.Interface)] out object ppv);
void GetAttributesOf(
uint cidl,
[In(), MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
ref SFGAO rgfInOut);
IntPtr GetUIObjectOf(
IntPtr hwndOwner,
uint cidl,
[MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,
[In()] ref Guid riid,
out IntPtr rgfReserved);
void GetDisplayNameOf(
IntPtr pidl,
SHGNO uFlags,
IntPtr lpName);
IntPtr SetNameOf(
IntPtr hwnd,
IntPtr pidl,
[MarshalAs(UnmanagedType.LPWStr)] string pszName,
SHGNO uFlags);
}
The desktop is the top-level folder, and other items in the shell namespace can be represented by PIDL starting from the desktop.
You can use the API shgetjavastopfolder to obtain the pidl and its IShellFolder interface of "desktop:
Code
public static IShellFolder GetDesktopFolder(out IntPtr ppshf) {
SHGetDesktopFolder(out ppshf);
Object obj = Marshal.GetObjectForIUnknown(ppshf);
return (IShellFolder)obj;
}
The following code calls a program:
Code
Private void Form1_Load (object sender, EventArgs e ){
// Obtain the desktop PIDL
IntPtr implements topptr;
IShellFolder desktop = API. getjavastopfolder (out of memory topptr );
// Obtain PIDL of drive C
String FolderPath = @ "C :\";
IntPtr Pidl = IntPtr. Zero;
IShellFolder Root;
Uint I, j = 0;
Desktop. ParseDisplayName (Handle, IntPtr. Zero, FolderPath, out I, out Pidl, ref j );
Desktop. BindToObject (Pidl, IntPtr. Zero, ref Guids. IID_IShellFolder, out Root );
Marshal. ReleaseComObject (desktop );
// Search PIDL of files/folders under drive C in a loop
IEnumIDList fileEnum = null;
IEnumIDList folderEnum = null;
IntPtr fileEnumPtr = IntPtr. Zero;
IntPtr folderEnumPtr = IntPtr. Zero;
IntPtr pidlSub;
Int celtFetched;
// Obtain subfolders
If (Root. EnumObjects (this. Handle, SHCONTF. FOLDERS | SHCONTF. INCLUDEHIDDEN, out fileEnumPtr) = API. S_ OK)
{
FileEnum = (IEnumIDList) Marshal. GetObjectForIUnknown (fileEnumPtr );
While (fileEnum. Next (1, out pidlSub, out celtFetched) = 0 & celtFetched = API. S_FALSE)
{
// Obtain the display name
String name = API. GetNameByPIDL (pidlSub );
LvFile. Items. Add (name, 1 );
}
}
// Obtain the sub-File
If (Root. EnumObjects (this. Handle, SHCONTF. NONFOLDERS | SHCONTF. INCLUDEHIDDEN, out folderEnumPtr) = API. S_ OK)
{
FolderEnum = (IEnumIDList) Marshal. GetObjectForIUnknown (folderEnumPtr );
While (folderEnum. Next (1, out pidlSub, out celtFetched) = 0 & celtFetched = API. S_FALSE)
{
String name = API. GetNameByPIDL (pidlSub );
LvFile. Items. Add (name, 0 );
}
}
Marshal. ReleaseComObject (Root );
}
The following figure shows the effect after running: