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

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

关于 Windows 外壳的基本概念,我这里不做详细介绍,不了解的朋友,可以看看 姜伟华 的 Windows外壳名字空间的浏览。

好,现在让我们从基础学起,早日做出一个强大的资源管理器软件。(偶也是初学者,多多指教)

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

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

在C#中,我们这样定义 IShellFolder 接口:

IShellFolder.cs

当然,这个接口还没有列出细节函数。我们要做的仅仅是从最基础开始。

首先我们必须了解,在外壳编程中,要使用 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(1, out 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(1, out pidlSub, out celtFetched) == 0 && celtFetched == API.S_FALSE)
                {
                    string name = API.GetNameByPIDL(pidlSub);
                    lvFile.Items.Add(name, 0);
                }
            }

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

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

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

转载于:https://www.cnblogs.com/xumaojun/p/8547391.html

(C#)Windows Shell 外壳编程系列1 - 基础,浏览一个文件夹相关推荐

  1. (C#)Windows Shell 外壳编程系列6 - 执行

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列5 - 获取图标 执行 许多人都知道 ShellExecute ,用于执行 ...

  2. (C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令...

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 上一节说到如 ...

  3. (C#)Windows Shell 外壳编程系列总结

    http://www.cnblogs.com/lemony/category/88555.html 原文见上面链接中的1-9系列 1.基础,浏览一个文件夹 在win32中是以外壳名字空间的形式来组织文 ...

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

    (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹 原文 (C#)Windows Shell 编程系列1 - 基础,浏览一个文件夹 (本系列文章由柠檬的(lc_mtt)原创,转载 ...

  5. #TCGA系列#利用perl提取一个文件夹中的多个文件夹里的注释文本

    我们里用gdc下载TCGA数据时,下载到一个压缩文件包.解压后,会发现里面有多个文件夹,而且最烦人的是:有的文件夹里有annotations.txt,而有的没有. miRNA注释文档有9列 我们利用p ...

  6. Windows 10系统中,如何重命名用户文件夹

    免责声明 该方法不适用于所有情况,可能导致数据丢失.计算机无法重启等问题,请提前保护好数据! 背景 许多Windows用户总是喜欢将文件放在用户文件夹(C:\Users\username)下,但有时候 ...

  7. .classpath文件有什么用_干货分享:Windows目录结构剖析,C盘目录常见文件夹都有什么用?...

    我们天天和文件夹打交道,但是有好多的碍眼的文件夹我们能不能删除呢,来看看今天的文章. 先问一个问题,你对你电脑的文件系统了解多少? 很多人只管用,但是有些时候,想要自己清理一下文件的时候,不太敢删除, ...

  8. android 遍历sdcard,Android编程读取Assets所有文件(遍历每一个文件夹)并存入sdcard的方法...

    本文实例讲述了Android编程读取Assets所有文件(遍历每一个文件夹)并存入sdcard的方法.分享给大家供大家参考,具体如下: private void CopyAssets(String a ...

  9. 服务器下最大能容量多少文件,windows下一个文件夹下面最多可以放多少文件(ntfs格式略过)...

    那么怎么来测试这样一个问题呢,很显然我们一个个的去建立文件是不现实的,没那么多时间,而且这个方法也太笨了.这里我们会用到批处理命令,新建一个bat文件,然后将"for /l %%a in ( ...

最新文章

  1. RHEL 6上KVM的安装配置及使用-将物理接口桥接到桥接器
  2. WCF系列之.net(4.0) 在网站使用Js调用Wcf Rest
  3. PHP不能精确表达小数 PHP除法结果不准确 php 为什么数字除法不准确 PHP浮点数运算不准确的问题...
  4. 洛谷3933 Chtholly Nota Seniorious 二分答案+贪心
  5. matlab怎么显示bfm模型的纹理模型,BFM模型介绍及可视化实现(C++)
  6. Crust Network将于1月14日12点开始暂停HTTP版本应用
  7. Python,OpenCV制作全透明图,简单的图片
  8. 2、解读中台 -- 中台的作用
  9. Python入门(二) part1 列表
  10. c语言如何判断当前是 空字符,c语言如何判断字串中没有没有某个字元?
  11. 电信行业大数据应用的四个方向
  12. excel分析数据的工具有哪些?
  13. [数据结构]线性表——顺序存储
  14. Dessert(dfs)
  15. my_RIO实现小车避障
  16. mothur trim.seqs 去除PCR引物
  17. c 语言 int 转字符串,C++ 字符串string和整数int的互相转化操作
  18. android设备rs232数据格式,如何通过rs232 android进行串口通讯?(How to do serial communication via rs232 android?)...
  19. 网络货运办理流程指引
  20. 刷同样多数学题,你的成绩还是不如我(来自网络)

热门文章

  1. 创业项目-互联网全媒体广告
  2. python windows程序自动化_Windows GUI程序自动化之pywinauto
  3. Easyexcel写操作
  4. Codeforces Round #634 (Div. 3)ABCD
  5. 这个岗位国内人才缺口超30万,突破职场瓶颈,薪资飙升。
  6. 如何有效降低采购成本?
  7. 关于django中form action的跳转问题
  8. php获取基站,基站查询API接口_免费数据接口 - 极速数据
  9. java使用xquery_如何使用Java XQuery
  10. 怕什么路途遥远,进一步自有一步的欢喜