原文 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. Nio Server

    package org.fxc.nio.server; import java.io.FileInputStream; import java.io.IOException; import java. ...

  2. window.external.JavaScriptCallCpp

    方案2: 1.编写html <html> <head> </head> <body> <script language="javascr ...

  3. Ajax 调用方式

    function wds_generatecss() { var txt = $.trim($("#TxtText").val()); if (txt == "" ...

  4. Oracle 查询时间在当天的数据

    要实现这个功能需要用到trunc这个函数对时间的操作 select trunc(sysdate) from dual --2014-12-27 今天的日期为2014-12-27 select trun ...

  5. Linux系统学习笔记之 1 一个简单的shell程序

    不看笔记,长时间不用自己都忘了,还是得经常看看笔记啊. 一个简单的shell程序 shell结构 1.#!指定执行脚本的shell 2.#注释行 3.命令和控制结构 创建shell程序的步骤 第一步: ...

  6. 基于linux c的mysql操作——幼儿园数据管理系统

    上周对于mysql进行了简单的学习,利用c对mysql进行操作,主要用到了以下几个函数: mysql_init(); mysql_real_connect(数据库变量指针,网络地址,用户名,登录密码, ...

  7. php错误 mysql_query():supplied argument is not a valid MySQL result resource

    出现这种错误,原因是出现该错误的函数的参数出现了问题 参数出现问题有多种情况: 1.sql查询语句有问题,可能多了一个逗号,少了一个逗号,多了括号之类的: 2.与数据库连接的参数有问题,用户名.密码. ...

  8. android小知识之圆角ListView

    有些东西看多了,就厌烦了:extjs对我这种感觉最为强烈.甚至,有时觉得设计之殇是审美疲劳.直角看多了,就想看看圆角,不知何时,这几年刮起了一阵阵的圆角设计风:CSS新标准纳入圆角元素,iphone中 ...

  9. Genymotion配置及使用教程(最新最完整版附各部分下载地址)

    Genymotion配置及使用教程(最新最完整版附各部分下载地址) FROM:http://blog.csdn.net/beiminglei/article/details/13776013 早都听说 ...

  10. BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1103 [题目大意] 给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, ...