65.9K
CodeProject 正在变化。 阅读更多。
Home

OSIcon

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (22投票s)

2010年1月4日

CPOL

5分钟阅读

viewsIcon

71201

downloadIcon

1872

处理和检索系统图标的库。

注意:如果您使用 Visual Studio,请使用 Packet Manager NuGet 获取库:OSIcon

如果您想获取最新源代码、贡献、派生或提出问题,请访问github OSIcon 项目

OSIcon/1.OSIcon_Explorer_MyComputer.png

OSIcon/2.OSIcon_Explorer.png

OSIcon/3.OSIcon_Explorer1.png

OSIcon/OSIcon_Explorer.png

OSIcon/OSIcon_Associations.png

OSIcon/OSIcon_Associations.png

OSIcon/OSIcon_IconExplorer.png

目录

引言

此库可以从扩展名和文件中检索图标,并提供附加信息,例如文件类型(硬盘、文件夹、PHP 脚本文件等)。该库还提供一个用于缓存图标的类,并创建一个包含所添加图标的 ImageList

Using the Code

库中的类

  • WinAPI 命名空间(包含所有 Win API 调用)
    • Shell32 static 类(所有 Shell32.dll 的 API 调用)
    • DwmApi static类(所有 Dmwapi.dll 的 API 调用)
    • User32 static 类(所有 User32.dll 的 API 调用)
    • Comctl32 static 类(所有 Comctl32.dll 的 API 调用)
    • IShellFolder 接口
  • 控件

    • FileExplorer 一个行为类似于 Windows 资源管理器的控件
  • Utilities static类(辅助函数)
  • IconReader static 类(读取、处理图标)
  • IconManager 类(带有缓存功能、自动创建 ImageListIconReader 包装器)
  • WindowsThumbnail 类用于检索任务栏上的 Windows 缩略图
  • About static 类(存储有关库、作者、网页等的一些常量)

使用 IconReader 类

使用“OSIcon.IconReader.ExtractIconFromFile(path, isLarge);”从文件中获取任何图标。

// To extract the file icon we simply can do:
// First param will be the path to file.
// Last param define icon size (true = Large, false = Small)
Icon icon = OSIcon.IconReader.ExtractIconFromFile("C:\\pathtofile.png", true);

现在,如果您想从 shell32.dll 等资源文件中提取图标,可以这样做:“OSIcon.IconReader.ExtractIconFromFile(path, iconIndex);”。

// 5, is the icon index
// http://cfs6.tistory.com/upload_control/download.blog?
// fhandle=YmxvZzEwMTUzNkBmczYudGlzdG9yeS5jb206L2F0dGFjaC8wLzAxMDAwMDAwMDAwMC5qcGc%3D
// 5 will return Open Folder image from shell32.dll
Icon icon = OSIcon.IconReader.ExtractIconFromFile("C:\\Windows\\system32\\shell32.dll", 5);

在 Windows 资源管理器、FileZilla 等中,我们可以看到文件类型(文件夹、PHP 脚本、动态链接库等)。要检索该信息,我们需要使用一些 API 调用。使用 OSIcon,这非常简单:“OSIcon.IconReader.GetFileIcon(pathOrExtension, IconReader.IconSize);”。

// NOTE: filename can be an partial extension (.png), or a full path ("C:\\file.png")
// IconInfo class store all information about the icon
IconInfo iconInfo = OSIcon.IconReader.GetFileIcon(".png", IconReader.IconSize.Large);
MessageBox.Show(string.Format("Display Name: {0}\nFile Type: {1}", 
                iconInfo.DisplayName, iconInfo.TypeName));

我们还可以从注册表检索文件扩展名并提取它们的图标,使用:“OSIcon.IconReader.GetFileTypeAndIcon();”。

// Get all available extensions
// Dictionary Key = extension, value = path to icon
Dictionary<string, string> _iconList = _iconList = 
OSIcon.IconReader.GetFileTypeAndIcon();
// Foreach each extension
foreach (KeyValuePair<string, string> list in _iconList)
// Extract icon from file
Icon icon = OSIcon.IconReader.ExtractIconFromFile(_iconList[extension], 
                              isLarge ? true : false);

使用“ExtractIconsFromFile(path, isLarge);”获取文件中的所有图标非常简单。

// From Sample Application see: "IconExplorer.cs" UserControl
filename = "C:\\Windows\\system32\\shell.dll";
Icon[] icons = IconReader.ExtractIconsFromFile(filename, true);
if(icons.Length == 0) return; // No icons found, return
// Loop through icons array
for (int i = 0; i < icons.Length; i++)
{
    // Do something here, im adding icon to an ImageList
    imageList.Images.Add(i.ToString(), icons[i]);
}

使用 IconManager 类

有时,我们需要显示文件,并且有数百个相同类型的文件,例如 .php;在这种情况下,您可以重用从第一个 PHP 文件获得的图标。(请参阅 FileExplorer 控件)

  • IconProperties
    • IconsInfo(存储图标信息和索引)Dictionary<IconReader.IconSize, IconInfo>
// If you want create a ImageList to store collected icons use true
// Small ImageList (true/false), Large ImageList (true/false)
// new OSIcon.IconManager() == new OSIcon.IconManager(true, true)
//
// Initalize Class, and create small, large, extralarge, jumbo
// Last param if set true, disable ExtraLarge or Jumbo if not supported by current OS
OSIcon.IconManager iconManager = new OSIcon.IconManager(true, true, true, true, true);
// Add some special icons to be used
// Add folder images
iconManager.AddFolder(); 
// Add Computer Drives (DVD Drive, Floppy, Hard Disk, etc.)
iconManager.AddComputerDrives(); 
 
// You also can add manualy, icons images to ImageList
// I use ":" because file path can't have ':' in name, so its a special mark
iconManager.ImageList[IconReader.IconSize.Small].Images.Add(
  ":Up-icon:", Properties.Resources.Up_icon16x16);
iconManager.ImageList[IconReader.IconSize.Large].Images.Add(
  ":Up-icon:", Properties.Resources.Up_icon32x32);
// ExtraLarge was introduced on XP so if you running XP
// or above add ExtraLarge capabilities
if (OSIcon.Utils.IsXpOrAbove())
{
    iconManager.ImageList[IconReader.IconSize.ExtraLarge].Images.Add(
                ":Up-icon:", Properties.Resources.Up_icon48x48);
}
// Jumbo was introduced on Vista so if you
// running Vista or above add Jumbo capabilities
if (OSIcon.Utils.IsVistaOrAbove())
{
    iconManager.ImageList[IconReader.IconSize.Jumbo].Images.Add(
          ":Up-icon:", Properties.Resources.Up_icon256x256);
}
// NOTE: iconManager.ImageList[IconReader.Size]
// can be assign in any control that uses ImageList

该类已初始化并可供使用;现在,我们创建一个函数来显示“我的电脑”和路径内容

void ShowMyComputer()
{
    // List all drives on computer
    foreach (string drive in Directory.GetLogicalDrives())
    {
        // Always when you add a icon to list it will return IconProperties 
        // and cache it on class
        OSIcon.IconManager.IconProperties iconProp = 
        OSIcon.iconManager.AddEx(drive, IconManager.IconSizeSupported);
        // Do something here!, sample from OSIcon Explorer:
        var item = new ListViewItem(iconProp[IconSize.Small].DisplayName)
        {
            ImageIndex = iconProp[IconSize.Small].ItemIndex
        };
        item.SubItems.Add(string.Empty);
        item.SubItems.Add(iconProp.IconsInfo[IconSize.Small].TypeName);
        item.Tag = drive;
        lvFileExplorer.Items.Add(item);
    }
}
 
// Next function will show path contents
public void ShowPathContents(string path)
{
    if (path == null)
        return;
    // Path is empty so Show MyComputer
    if (path == string.Empty)
    {
        ShowMyComputer();
        return;
    }
    try
    {
        Cursor = Cursors.WaitCursor;
        btnGoUp.Enabled = true;
        RewindManager.Add(path);
        btnGoBack.Enabled = RewindManager.CanPrevious;
        btnGoForward.Enabled = RewindManager.CanForward;
        lbSelected.Text = string.Empty;
        CurrentPath = path;
        lvFileExplorer.BeginUpdate();
        lvFileExplorer.Items.Clear();
        //CreateGoUpFolder(path);
        TotalFilesSize = 0;
        TotalFolders = 0;
        TotalFiles = 0;
        // Loop through folders inside current folder
        foreach (var folder in Directory.EnumerateDirectories(path))
        {
            // Get folder name from path
            var dirInfo = new DirectoryInfo(folder);
            // Remove system directories
            if ((dirInfo.Attributes & FileAttributes.System) == FileAttributes.System)
                continue;
            var item = new ListViewItem(Path.GetFileName(folder)) { Tag = folder };
            var iconProp = IconManager[IconManager.FolderClosed];
            item.ImageIndex = iconProp[IconSize.Small].ItemIndex;
            item.SubItems.Add(dirInfo.LastWriteTime.ToString(CultureInfo.CurrentCulture));
            item.SubItems.Add(iconProp[IconSize.Small].TypeName);
            item.SubItems.Add(string.Empty);
            lvFileExplorer.Items.Add(item);
            TotalFolders++;
        }
        // Loop through Files inside current folder
        foreach (var file in Directory.EnumerateFiles(path))
        {
            // Get some addition file information like size, name, extension, etc...
            var fi = new FileInfo(file);
            // Remove system directories
            if ((fi.Attributes & FileAttributes.System) == FileAttributes.System)
                continue;
            var iconProp = IconManager.AddEx(fi.Extension, IconManager.IconsSizeSupported);
            var item = new ListViewItem(fi.Name)
            {
                Tag = fi.FullName,
                ImageIndex = iconProp[IconSize.Small].ItemIndex
            };
            item.SubItems.Add(fi.LastWriteTime.ToString(CultureInfo.CurrentCulture));
            item.SubItems.Add(iconProp.IconsInfo[IconSize.Small].TypeName);
            item.SubItems.Add(string.Format(" {0:##.##} {1}", 
            Utilities.FormatByteSize(fi.Length), Utilities.GetSizeNameFromBytes(fi.Length, false)));
            lvFileExplorer.Items.Add(item);
            TotalFilesSize += fi.Length;
            TotalFiles++;
        }
        // Lets make some status and retrieve total folders, files and their total size
        string textToSet = string.Empty;
        if (TotalFolders > 0)
            textToSet += string.Format("{0} {1}", TotalFolders, 
            Utilities.ConvertPlural(TotalFolders, "Folder"));
        if (TotalFiles > 0)
        {
            if (textToSet != "Total:")
                textToSet += " &";
            textToSet += string.Format(" {0:##.##} {1} in {2} {3}", 
            Utilities.FormatByteSize(TotalFilesSize), Utilities.GetSizeNameFromBytes
            (TotalFilesSize, false), TotalFiles, Utilities.ConvertPlural(TotalFiles, "File"));
        }
        if (textToSet == "Total:")
            textToSet = "Empty";
        tbAddress.Text = CurrentPath;
        lbTotal.Text = textToSet;
    }
    catch (Exception ex)
    {
        MessageBox.Show(string.Format("Error on trying access: {0}\n\n{1}", path, ex.Message), 
        "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    finally
    {
        lvFileExplorer.EndUpdate();
        Cursor = Cursors.Default;
        RebuildNavigationHistory();
    }
}

ListView 仅有一个“ImageList”(应为 16 x 16px)和“LargeImageList”。如果您想显示 XP 中引入的“ExtraLarge”图标和 Vista 或更高版本中的“Jumbo”图标,您必须将“LargeImageList”更改为所需的大小,例如

/* 
* "fileExplorerList" is our ListView
* View:
* 0 = LargeIcons
* 1 = Details
* 2 = Small Icons
* 3 = List
* 4 = Title
* End View Enumeration
* 5 = ExtraLarge
* 6 = Jumbo
*/

private void ChangeListViewV(uint index)
{
    // If view is bigger than 4 means user wants ExtraLarge or Jumbo
    // To show that sizes View must be set to: View.LargeIcon
    // Also we have to change Large ImageList to the desired one
    if (index > 4)
    {
        // we change ImageList because ListView only have ImageList and LargeImageList
        switch (index)
        {
           case 5:
              fileExplorerList.LargeImageList = 
                    iconManager.ImageList[IconReader.IconSize.ExtraLarge];
              break;
           case 6:
              fileExplorerList.LargeImageList = 
                    iconManager.ImageList[IconReader.IconSize.Jumbo];
              break;
        }
        fileExplorerList.View = View.LargeIcon;
        return;
     }
     // View is under normal (small or large)
     // Get back to normal
     fileExplorerList.LargeImageList = iconManager.ImageList[IconReader.IconSize.Large];
     fileExplorerList.View = (View)index;
}

如何摆脱添加的图标?可以这样做

// I dont need .txt icon anymore, and i will not use it from ImageList
iconManager.Remove(".txt", true);
// I dont need .wav icon anymore, but i still use it from ImageList
iconManager.Remove(".wav", false);
// IconSize Small is to small and Jumbo is too big for what i want
iconManager.Remove(".exe", IconReader.IconSize.Small | 
                                     IconReader.IconSize.Jumbo, true);

您无需使用 IconManager 类进行硬编码。这是一个示例

string name = ".dll";

// Bad Way:
IconProperties iconProp = iconManager.IconList[name];
if(!iconProp.IsValid(name, IconReader.IconSize.Small))
{
    OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    iconManager.AddEx(name, IconReader.IconSize.Small, ref shfi);
}
if(!iconProp.IsValid(name, IconReader.IconSize.Jumbo))
{
    OSIcon.WinAPI.Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    iconManager.AddEx(name, IconReader.IconSize.Jumbo, ref shfi);
}

// Good Way:
IconProperties iconProp = iconManager.AddEx(name, IconReader.IconSize.Small | IconReader.IconSize.Jumbo);

历史

V3.0

  • 重写代码以提高性能和可用性
  • 添加了一个行为类似于 Windows 资源管理器的 FileExplorer 控件
  • 为库添加了强密钥
  • 库现在使用 .NET Framework 4.0 编译

V2.0

  • 添加了 About
  • 添加了更好的注释
  • 添加了更多示例
  • 更新了示例应用程序以使用新的图标大小
  • 更新了示例应用程序以使用新库
IconProperties 类
  • 添加了“Remove”函数,用于从指定大小中删除图标
    • 支持多大小标志(IconReader.IconSize.Small | IconReader.IconSize.Large
    • 返回一个包含已删除图标的 Dictionary<IconReader.IconSize, int>,其中 intImageList 中图标的索引
  • 添加了三个“IsValid”函数
    • bool IsValidEx(IconReader.IconSize size),与“IsValid(IconReader.IconSize size)”相同,但还会检查图标是否不为 NULL
    • bool IsValid(),检查该实例是否包含图标
    • bool IsValid(IconReader.IconSize size),检查该实例中是否存在指定大小的图标
  • 将“IconsInfo”类型从 struct 更改为 Dictionary<IconReader.IconSize, Shell32.SHFILEINFO>
  • 将“IconsIndex”类型从 struct 更改为 Dictionary<IconReader.IconSize, int>
  • 将“Icons”类型从 struct 更改为 Dictionary<IconReader.IconSize, Icon>
  • 实现了一个“Tag”对象
  • Disposable
  • IconProperties”现在是一个类,以前是一个 struct
IconManager 类
  • 修复了“AddEx”函数,允许添加不同大小的更多图标
  • 添加了注释
  • 添加了两个“Remove”函数,允许从缓存和 ImageList 中删除图标
    • bool Remove(string path, bool removeIconFromList),删除所有图标
    • bool Remove(string path, IconReader.IconSize iconSize, bool removeIconFromList),仅删除指定大小的图标
  • 添加了 privateAdd”函数,添加图标到列表时的常见操作(以消除冗余)
  • 添加了“IsValidEx”函数,与“IsValid”相同,但返回匹配的“IconProperties”;否则返回一个新实例
  • 添加了两个新构造函数
    • public IconManager(bool createSmallIconList, bool createLargeIconList, bool createExtraLargeIconList, bool createJumboIconList)
    • public IconManager(bool createSmallIconList, bool createLargeIconList, bool createExtraLargeIconList, bool createJumboIconList, bool optimizeToOS)
  • 将“ImageListSmall”和“ImageListLargeImageLists 替换为“IImageListDictionary<IconReader.IconSize, ImageList>
  • 添加了“IconSizeAllSupported”只读变量,包含当前操作系统支持的所有图标大小
  • 添加了“IconManager.IconSizeAll”常量,包含所有图标大小(Small | Large | ExtraLarge | Jumbo)
IconReader 类
  • 更改了所有包含“IconReader.IconSize”的函数,以支持新的图标大小(ExtraLargeJumbo
  • 添加了“ExtractIconFromResource”函数,从程序集中按名称提取图标
  • 添加了“ExtractIconsFromFile”函数,从文件中提取所有图标;返回“Icon[]
  • 添加了“ExtractIconFromFileEx”函数,与 ExtractIconFromFile 相同,但支持更大尺寸和图标信息
  • 为“IconReader.IconSize”添加了两个新图标大小
    • IconReader.Iconsize.ExtraLarge (48x48 像素),XP 或更高版本支持
    • IconReader.Iconsize.Jumbo (256x256 像素),Vista 或更高版本支持
  • 将函数“ExtractIcon”重命名为“ExtractIconFromFile
About 类
  • 添加了“ProjectAuthor”常量,我的名字
  • 添加了“ProjecWWW”常量,本页网址

V1.0.01

  • 修改以纠正严重的格式和拼写错误 - JSOP - 2010年1月3日

V1.0

  • 首次发布
© . All rights reserved.