(C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹

简介: 原文 (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹  (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢~)Windows Shell 编程,即 Windows 外壳编程。

原文 (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹 

(本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢~)

Windows Shell 编程,即 Windows 外壳编程。我们所看到的资源管理器以及整个桌面,都是一个 Shell。

关于 Windows 外壳的基本概念,我这里不做详细介绍,不了解的朋友,可以看看 姜伟华 的 Windows外壳名字空间的浏览
好,现在让我们从基础学起,早日做出一个强大的资源管理器软件。(偶也是初学者,多多指教)

1 - 基础,浏览一个文件夹

我们知道,在win32中是以外壳名字空间的形式来组织文件系统的,在外壳名字空间里的每一个对象(注)都实现了一个IShellFolder的接口,通过这个接口我们可以直接查询或间接得到其他相关的接口。 (注:这里的对象指的是外壳名字空间中的一个节点,对象有可能是一个文件夹,有可能是一个文件,也有可能是一个虚拟文件夹,例如:我的电脑,网上邻居,控制面板等)
在C#中,我们这样定义 IShellFolder 接口:

 

当然,这个接口还没有列出细节函数。我们要做的仅仅是从最基础开始。
首先我们必须了解,在外壳编程中,要使用 PIDL 路径代替普通路径(如果对 PIDL 不熟悉,请看Windows外壳名字空间的浏览)。
“桌面”是最顶级的文件夹,外壳名字空间中其他各项都可以用从“桌面”开始的 PIDL 加以表示。
如何获取“桌面”的 PIDL 和其 IShellFolder 接口呢,可以通过 API SHGetDesktopFolder:

[DllImport( " shell32.dll " )]          public   static   extern  Int32 SHGetDesktopFolder( out  IntPtr ppshf); /// <summary>         /// 获得桌面 Shell         /// </summary>          public   static  IShellFolder GetDesktopFolder( out  IntPtr ppshf)          {             SHGetDesktopFolder(out ppshf);             Object obj = Marshal.GetObjectForIUnknown(ppshf);             return (IShellFolder)obj;         }
// 获得桌面 PIDL             IntPtr desktopPtr;             IShellFolder desktop  =  API.GetDesktopFolder( out  desktopPtr);


好的,我们取得“桌面”的 IShellFolder 接口,就已经成功了一半。现在我需要通过“桌面”,来获取“C:/”这个路径的 PIDL 和 IShellFolder 接口,可以通过 IShellFolder 的 ParseDisplayName 和 BindToObject 函数来实现:

void  ParseDisplayName(             IntPtr hwnd,             IntPtr pbc,             [MarshalAs(UnmanagedType.LPWStr)]  string  pszDisplayName,              out   uint  pchEaten,              out  IntPtr ppidl,              ref   uint  pdwAttributes); void  BindToObject(             IntPtr pidl,             IntPtr pbc,             [In()]  ref  Guid riid,              out  IShellFolder ppv);
// 获取 C 盘的 PIDL              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);


前提是你应该保证路径存在,因为我没有做任何出错控制。这样我们就获得了一个 Root,它表示C盘。通过这个Root,我们可以用 EnumObjects 来循环获取其子项(子文件和子文件夹):

[PreserveSig]          int  EnumObjects(IntPtr hWnd, SHCONTF flags,  out  IntPtr enumIDList);

 

// 循环查找 C 盘下面的文件/文件夹的 PIDL             IEnumIDList fileEnum  =   null ;             IEnumIDList folderEnum  =   null ;             IntPtr fileEnumPtr  =  IntPtr.Zero;             IntPtr folderEnumPtr  =  IntPtr.Zero;             IntPtr pidlSub;              int  celtFetched;              // 获取子文件夹              if  (Root.EnumObjects( this .Handle, SHCONTF.FOLDERS  |  SHCONTF.INCLUDEHIDDEN,  out  fileEnumPtr)  ==  API.S_OK)              {                 fileEnum = (IEnumIDList)Marshal.GetObjectForIUnknown(fileEnumPtr);                 while (fileEnum.Next(1out pidlSub, out celtFetched) == 0 && celtFetched == API.S_FALSE)                 {                     //获取显示名称                     string name = API.GetNameByPIDL(pidlSub);                     lvFile.Items.Add(name, 1);                 }             }              // 获取子文件              if  (Root.EnumObjects( this .Handle, SHCONTF.NONFOLDERS  |  SHCONTF.INCLUDEHIDDEN,  out  folderEnumPtr)  ==  API.S_OK)              {                 folderEnum = (IEnumIDList)Marshal.GetObjectForIUnknown(folderEnumPtr);                 while (folderEnum.Next(1out pidlSub, out celtFetched) == 0 && celtFetched == API.S_FALSE)                 {                     string name = API.GetNameByPIDL(pidlSub);                     lvFile.Items.Add(name, 0);                 }             }


事实上,代码到此结束。然而我发现有太多的结构体和枚举没有介绍(以后会有更多),有兴趣的朋友可以自己查 MSDN ,否则就等待我下一节再介绍了。

最后把图和代码贴上,下一节再详细介绍。



源代码:/Files/lemony/WinShell.rar

目录
相关文章
|
2月前
|
Unix Linux Shell
【Shell 编程指南 日期命令】Date命令:显示与设置系统时间和日期
【Shell 编程指南 日期命令】Date命令:显示与设置系统时间和日期
57 0
|
6天前
|
监控 关系型数据库 Shell
Shell脚本入门:从基础到实践,轻松掌握Shell编程
Shell脚本入门:从基础到实践,轻松掌握Shell编程
|
8天前
|
存储 安全 搜索推荐
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
Windows之隐藏特殊文件夹(自定义快捷桌面程序)
|
8天前
|
存储 Shell C语言
shell脚本 编程 变量 基本入门(详解)
shell脚本 编程 变量 基本入门(详解)
|
19天前
|
API C++ Windows
windows编程入门_链接错误的配置
windows编程入门_链接错误的配置
19 0
|
20天前
|
存储 网络协议 Shell
第十章 Shell编程时常用的系统文件
第十章 Shell编程时常用的系统文件
|
27天前
|
监控 Shell 开发工具
Shell编程
Shell编程
|
27天前
|
Shell
Shell脚本编程基础
Shell脚本编程基础
|
1月前
|
Windows
Windows下文件夹映射的实现(将文件夹从一个盘映射到另一个盘)
Windows下文件夹映射的实现(将文件夹从一个盘映射到另一个盘)
48 0
|
1月前
|
Shell 开发工具 git
shell空文件夹查找
shell空文件夹查找
13 0