原文 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. Asp.Net Memcached安装配置使用、安全性

    Memcached安装配置使用  一,准备        你需要有一下软件:       VS.NET(05/08)       SQLSERVER       memcached服务器端以及客户端类 ...

  2. SQLSERVER 列名无效

    很多时候对数据库表修改字段后会出现“列名无效”,或者在查询分析器里面是红色的下划线,造成这个现象的原因是:SQL Server的intellisense(智能感知功能),没有感知到更改,需要重新整理一 ...

  3. <a>元素生成多个<a>的问题,元素标签结尾影响

    告诉我不是真的吧,<a/>和<a></a>真的有区别...

  4. (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解

    PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使用经验,总结一下. 一般对负载均衡的使用是随着网站规模的提升根据不 ...

  5. 你需要了解的JS框架

    excanvas.js/Chart.js/cubism.js/d3.js/dc.js/dx.chartjs.js/echarts.js/flot.js       用途:构建数据统计图表,兼容多浏览器 ...

  6. Mysql mysqlimport 导入数据

    在mysql 数据库中可以用 mysqlimport 工具来实现数据的导入!mysqlimport 导入数据简单,但是这个也要满足一定的条件 1.既然是把数据导入到数据库,你总有一个数据库用户账号吧 ...

  7. Jmeter 笔记

    Apache JMeter是Apache组织开发的基于Java的压力测试工具.用于对软件做压力测试,它最初被设计用于Web应用测试但后来扩展到其他测试领域. 它可以用于测试静态和动态资源例如静态文件. ...

  8. Jsoup代码解读之一-概述

    Jsoup代码解读之一-概述 今天看到一个用python写的抽取正文的东东,美滋滋的用Java实现了一番,放到了webmagic里,然后发现Jsoup里已经有了…觉得自己各种不靠谱啊!算了,静下心来学 ...

  9. CCNP路由实验(2) -- OSPF

    OSPF作为一种内部网关协议(IGP),用于在同一个AS中的路由器之间交换路由信息.OSPF的特性如下:1.可适应大规模网络2.收敛速度快3.无路由环路4.支持VLSM和CIDR5.支持等价路由6.支 ...

  10. Windows Azure 虚拟网络中虚拟机的网络隔离选项

     最近我们发布了一份<Windows网络安全白皮书>(单击此处下载),文中深入说明了客户可以如何利用该平台的本地功能,为他们的信息资产提供最好的保护. 由首席顾问Walter Myer ...