原文 C#)Windows Shell 编程系列5 - 获取图标

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

接上一节:(C#)Windows Shell 编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令

有关 PIDL

  PIDL亦有“绝对路径”与“相对路径”的概念。表示“相对路径”的PIDL(本文简称为“相对PIDL”)只有一个ITEMIDLIST结构的元素,用于标识相对于父文件夹的“路径”;表示“绝对路径”的PIDL(简称为“绝对PIDL”)有若干个ITEMIDLIST结构的元素,第一个元素表示外壳名字空间根文件夹(“桌面”)下的某一子文件夹A,第二个元素则表示文件夹A下的某一子文件夹B,其余依此类推。这样绝对PIDL就通过保存一条从“桌面”下的直接子文件夹或文件的绝对PIDL与相对PIDL是相同的,而其他的文件夹或文件的相对PIDL就只是其绝对PIDL的最后一部分了。

  为什么要说这些呢?因为有些函数,必须使用绝对PIDL,例如图标,如果不使用绝对PIDL,某些图标是无法正常获得的(驱动器、控制面板等)。

但使用 EnumObjects 获得的,仅仅是相对PIDL,如果通过相对PIDL获取绝对PIDL呢?我参考了开源项目 C# FileBrowser 中的 PIDL 类


, newPidl, bytes.Length);

            return newPidl;
        }
    }
}

该类实现了 PIDL 的复制和结合功能。现在我们修改 ShellItem 类,使它带有父节点的 IShellFolder 以及提供获取绝对 PIDL 的属性:

private ShellItem m_ParentItem;

public ShellItem ParentItem
{
    get { return m_ParentItem; }
    set { m_ParentItem = value; }
}

/// <summary>
/// 绝对 PIDL
/// </summary>
public PIDL PIDLFull
{
    get
    {
        PIDL pidlFull = new PIDL(PIDL, true);
        ShellItem current = ParentItem;
        while (current != null)
        {
            pidlFull.Insert(current.PIDL);
            current = current.ParentItem;
        }
        return pidlFull;
    }
}

获取图标

言归正传,既然已经获得绝对 PIDL,那么获取图标就是很简单的事情了,我们使用的是 SHGetFileInfo 这个API:

[DllImport("shell32", EntryPoint = "SHGetFileInfo", ExactSpelling = false, 
    CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SHGetFileInfo(
    IntPtr ppidl, 
    FILE_ATTRIBUTE dwFileAttributes, 
    ref SHFILEINFO sfi, 
    int cbFileInfo, 
    SHGFI uFlags);

[DllImport("Shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(
    string Path, 
    FILE_ATTRIBUTE fileAttributes, 
    out SHFILEINFO sfi, 
    int cbFileInfo, SHGFI flags);

这里提供了一个重载,你可以选择是通过 PIDL 还是 路径 获取图标(如果是路径,那么仅仅能获取 文件夹/文件 的图标)。

, ref psfi, Marshal.SizeOf(psfi),
        SHGFI.ICON | SHGFI.PIDL | SHGFI.SMALLICON | SHGFI.SYSICONINDEX);

    return psfi.iIcon;
}

大家也许会觉得奇怪,GetSmallIconIndex 返回的是 int ,到底要怎么使用?

其实没
错,GetSmallIconIndex 仅仅是返回该图标在系统图像列表(System
ImageList)的索引(Index)而已。我们只要获取系统图像列表的指针,再把它关联到你的 TreeView 或 ListView
,即可通过 Icon Index 来显示图标了。

, out shfi, Marshal.SizeOf(typeof(SHFILEINFO)),
    SHGFI.SYSICONINDEX | SHGFI.LARGEICON | SHGFI.USEFILEATTRIBUTES);

//把系统 ImageList 关联到 TreeView 和 ListView
API.SendMessage(Tree1.Handle, API.TVM_SETIMAGELIST, API.TVSIL_NORMAL, m_ipSmallSystemImageList);
API.SendMessage(lvFile.Handle, API.LVM_SETIMAGELIST, API.LVSIL_NORMAL, m_ipLargeSystemImageList);

OK,我们修改以往的例子,就可以在 Tree 节点上显示图标了:


ShellItem shellItem=new ShellItem(pidlSub, iSub, sItem);
int imgIndex = API.GetSmallIconIndex(shellItem.PIDLFull.Ptr);
TreeNode nodeSub = new TreeNode(name, imgIndex, imgIndex);

(注:关于文中出现的一些结构体或常量,读者可以自行查阅 MSDN,精力有限实在不能一一说明。)

我们来看一下效果:

事实上,这个代码改了很多,也涉及到下一节的部分内容,因此代码将在下一节中抛出...

C#)Windows Shell 编程系列5 - 获取图标的更多相关文章

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

    原文(C#)Windows Shell 编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:( ...

  2. (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单

    原文 (C#)Windows Shell 编程系列3 - 上下文菜单(iContextMenu)(一)右键菜单 接上一节:(C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开这 ...

  3. (C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开

    原文 (C#)Windows Shell 编程系列2 - 解释,从“桌面”开始展开 (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一篇:(C#)Windows Shell 编 ...

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

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

  5. (C#)Windows Shell 外壳编程系列5 - 获取图标

    (本系列文章由柠檬的(lc_mtt)原创,转载请注明出处,谢谢-) 接上一节:(C#)Windows Shell 外壳编程系列4 - 上下文菜单(iContextMenu)(二)嵌入菜单和执行命令 有 ...

  6. [转]Windows Shell 编程 第二章 【来源:http://blog.csdn.net/wangqiulin123456/article/details/7987893】

    第二章Shell的结构  “Shell 编程”的大伞之下有大量的API函数和COM接口.这个种类繁多的‘命令’集允许你用不同的方法对Windows Shell进行编程.函数和接口并不是两种提供相同功能 ...

  7. shell编程系列10--文本处理三剑客之sed利用sed查询特定内容

    shell编程系列10--文本处理三剑客之sed利用sed查询特定内容 利用sed查找文件内容: pattern种类: .8p .,10p .,+5p ./regexp/p .,/regexp/p . ...

  8. windows编程之Windows Shell 编程

    参考书<VC++ Windows Shell Programming>   这里仅仅是记录下该资源,推荐到下文列出的连接进行查看   用VC++ 进行Windows Shell 扩展编成 ...

  9. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

随机推荐

  1. JavaScript奇技淫巧45招

    JavaScript奇技淫巧45招 撰写于 2015年1月5日 修改于 2016年6月16日 分类 翻译 标签 JavaScript 本文是一篇翻译文章,原文信息如下: 原文:45 Useful Ja ...

  2. param

    页面之间值传递用param作为参数,提高网站安全性

  3. log4j.xml配置示例

    这是log4j1.x版本讲解,log4j-1.2.16.jar    1. 一般的log4j.xml的两种配置方式: 1.Logger 完成日志信息的处理定义输出的层次和决定信息是否输出DEBUG&l ...

  4. Visual Studio之Nuget(服务器)

    一.创建空Web项目 二.安装Nuget.Server 这个时候,安装完成后,发现项目文件里多了Default.aspx等文件,因为我选择的MVC,所以最好做下小小的调整 ——在Global.asax ...

  5. poj2987 Firing

    以前只是A过很简单的最大闭合权像hdu1565之类,完全的最大流模板题.但是都完全不太懂最大闭合权的定义及其用途. 关于最大流的基础知识,大家可以自己网上搜索关键字.有点基础的哥们妹们,推荐看看胡伯涛 ...

  6. windows8 安装IIS 和 添加网站(转)

    Internet Information Services(IIS,互联网信息服务),是由微软公司提供的基于运行Microsoft Windows的互联网基本服务.最初是Windows NT版本的可选 ...

  7. Centos 7 安装Mono和Jexus 默认目录安装 (一)

    一.准备环境 yum -y install gcc gcc-c++ bison pkgconfig glib2-devel gettext make libpng-devel libjpeg-deve ...

  8. perl正则表达式第二周笔记

    1.使用正则表达式修改文本 1.使用正则表达式修改文本 正则表达式的功能不只有查询,还可以对文本进行修改,例如替换 $var=~m/regex/i $var=~s/regex/replacement/ ...

  9. 【转】说说JSON和JSONP,也许你会豁然开朗,含jQuery用例

    由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Socket通讯 ...

  10. zoj 2589 Matrix Searching 二维线段树

    题目链接 给一个n*n的矩阵, 给q个查询, 每次给出x1, y1, x2, y2, 求这个矩阵中的最小值. 代码基本上和上一题相同... #include<bits/stdc++.h> ...