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

使用 C# 为 Windows 资源管理器中的文件夹创建图标

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (25投票s)

2005 年 1 月 18 日

6分钟阅读

viewsIcon

166679

downloadIcon

3320

本文介绍如何使用 C# 为 Windows 资源管理器中的文件夹分配图标。

FolderIcons demo screenshot

引言

本文讨论了一个简单的类,该类可用于为在 Windows 资源管理器中显示的文件夹分配图标。

背景

在我与一位 UI 工程师的讨论过程中,他提到他发现了一种为 Windows 资源管理器中的文件夹创建图标的方法(选择文件夹:属性:自定义选项卡:更改图标...),我开始想,“一定有一种方法可以以编程方式实现这一点”。

事实证明,不仅有一种方法可以做到这一点,而且这项任务还相当容易处理。我们当时关于这个话题的讨论是一个更大项目的组成部分,而这将是另一篇文章的来源。然而,要实现最终目标,首先需要解决的问题是如何为文件夹分配图标——这本身似乎是一个足够有趣的话题,可以写一篇文章。

使用代码

如果您只想试用示例应用程序,只需打开 FolderIcons.sln 解决方案文件,然后在 Visual Studio IDE 中生成或运行它。

讨论

为文件夹分配图标基本上涉及两个步骤(如果算上创建文件夹,则可能为三个步骤)

  1. 在要创建图标的文件夹(“目标文件夹”)中创建一个 desktop.ini 文件。
  2. 将目标文件夹的属性设置为“系统”。

为了完成这些步骤,我创建了两个类。第一个名为 FolderIcon,它负责协调这些步骤。第二个名为 IniWriter,它只有一个名为 WriteValue() 的静态方法,该方法包装了 WritePrivateProfileString() Win32 API 函数(为了简单起见,当然——如果您希望将该方法重写为纯托管代码例程,请便;从我的角度来看,这主要是一个概念验证项目,尽管我可能会为生产环境重写该方法)。

正如您可能从屏幕截图中注意到的,有一个小的对话框充当简单的用户界面,允许浏览或输入文件夹路径(如果文件夹不存在,则会创建它),选择图标(图标文件必须存在),以及输入将在您将鼠标指针悬停在 Windows 资源管理器中的文件夹上时出现的 InfoTip 中显示的描述。当用户单击“创建图标”按钮时,将创建一个 FolderIcon 对象,将其文件夹路径传递给其构造函数,然后调用其 CreateFolderIcon() 方法。

private void btnCreateIcon_Click(object sender, System.EventArgs e)
{
    ...
            
    FolderIcon myFolderIcon = new FolderIcon(txtFolderPath.Text);
    myFolderIcon.CreateFolderIcon(txtIconPath.Text, txtInfoTip.Text);
    myFolderIcon = null;
    
    ... 
}

CreateFolderIcon 方法

深入 CreateFolderIcon() 方法

public void CreateFolderIcon( string iconFilePath, string infoTip )
{
    if ( CreateFolder() )
    {
        CreateDesktopIniFile(iconFilePath, infoTip);
        SetIniFileAttributes();
        SetFolderAttributes();
    }
}

首先,CreateFolderIcon() 尝试创建文件夹,然后调用方法来创建 desktop.ini 文件,将 .ini 文件属性设置为隐藏和系统,然后将目标文件夹的属性设置为系统。各个方法将在以下各节中进行描述。

CreateDesktopIniFile 方法

CreateDesktopIniFile() 方法有两种形式。由上面的 CreateFolderIcon 方法调用的那一个有两个参数:图标的路径和要在 InfoTip(又名 ToolTip)中显示的文件夹描述。CreateDesktopIniFile() 的简单版本调用 CreateDesktopIniFile() 的另一种形式,该形式具有稍微冗长的签名。

private bool CreateDesktopIniFile( string iconFilePath, 
                   bool getIconFromDLL, int iconIndex, string infoTip )
{
    ...
        
    this.IniPath = this.FolderPath + "desktop.ini";
    IniWriter.WriteValue(".ShellClassInfo", "IconFile", 
                         iconFilePath, this.IniPath);
    IniWriter.WriteValue(".ShellClassInfo", "IconIndex", 
                         iconIndex.ToString(), this.IniPath);
    IniWriter.WriteValue(".ShellClassInfo", "InfoTip", 
                         infoTip, this.IniPath);

    return true;
}

CreateDesktopIniFile() 使用 IniWriter 类的 WriteValue() 方法在目标文件夹中创建 desktop.ini 文件,并且由于 WriteValue() 方法是静态的,因此无需实例化 IniWriter 类即可使用它。WriteValue() 方法基本上只是 WritePrivateProfileString() Win32 API 函数的包装器,并且参数直接对应。您要做的就是传递节名称、键名、键的值以及 desktop.ini 文件的路径。

要显示文件夹的图标,desktop.ini 必须包含一个名为“.ShellClassInfo”的部分,其中包含两个键:“IconFile”——您希望分配给此文件夹的 .ico 文件的路径,以及“IconIndex”——对于图标文件,它应该设置为零。InfoTip 是可选的,但它是一种轻松创建文件夹用途更完整描述的方法。

调用上面的三个 WriteValue() 行后,您将得到类似以下内容的内容:

[.ShellClassInfo]
IconFile=C:\Graphics\Icons\MyIcon.ico
IconIndex=0
InfoTip=Test is the greatest folder ever!

上面列出的设置是显示图标所需的设置。您可能可以从 .ini 文件中的“IconIndex”键(以及 CreateDesktopIniFile() 方法上的相应 iconIndex 参数)推断出,该方法支持设置 .ini 文件以处理嵌入在 DLL 和 EXE 中的图标。您将 IconFile 设置为指向相关 DLL,并将 IconIndex 设置为引用 DLL 中图标的索引。要查看其工作原理,您可以尝试 Windows 中的“更改图标...”功能,然后打开生成的 desktop.ini 文件。这对您的应用程序意味着什么?您可以提供一组嵌入在 DLL 中的图标,然后将这些图标分配给文件夹以指示文件夹的各种用途,这类似于 Windows 对某些目录所做的。

SetIniFileAttributes 方法

下一步是将 desktop.ini 文件的属性设置为隐藏和系统。

private bool SetIniFileAttributes()
{
    ... 
    
    // Set ini file attribute to "Hidden"
    if ((File.GetAttributes(this.IniPath) & FileAttributes.Hidden) 
           != FileAttributes.Hidden) 
    {
        File.SetAttributes(this.IniPath, File.GetAttributes(this.IniPath) 
                           | FileAttributes.Hidden);
    }
    
    // Set ini file attribute to "System"
    if ((File.GetAttributes(this.IniPath) & FileAttributes.System) 
           != FileAttributes.System) 
    {
        File.SetAttributes(this.IniPath, File.GetAttributes(this.IniPath) 
                            | FileAttributes.System);
    }

    return true;
    
}

顺便说一句,根据我进行的初步测试,我的理解是这一步并非完全必要——您可以创建一个 desktop.ini 文件而不去修改其文件属性,它也能正常工作。但是,如果您通过 Windows 资源管理器文件夹属性执行这些步骤,它会将属性设置为隐藏和系统,所以我只是认为与 Windows 的功能保持一致会更好。

SetFolderAttributes 方法

不仅 desktop.ini 的属性需要设置为系统,目标文件夹的属性也需要设置为系统。

private bool SetFolderAttributes()
{
    ...
    
    // Set folder attribute to "System"
    if ((File.GetAttributes(this.FolderPath) & FileAttributes.System) 
           != FileAttributes.System) 
    {
        File.SetAttributes(this.FolderPath, File.GetAttributes 
                          (this.FolderPath) | FileAttributes.System);
    }

    return true;
    
}

desktop.ini 文件的设置不同,文件夹的系统设置是*必需*的。您可能想知道的是,用于获取和设置文件夹属性的类和方法与文件(即使用 File 类的静态方法 GetAttributes()SetAttributes())是相同的。老实说,当我在研究这个功能部分时,这让我感到困惑,因为在我看来,将 SetAttributes() 方法放在 Directory 类中似乎更自然、更直接。

关注点

正如我在文章前面提到的,这个项目只是封装了(无双关语)一个两部分系列的第一部分,该系列将展示文件夹图标分配功能的一个半实际应用。下次,我将从这一点开始,并稍微阐述一下当您玩弄 Microsoft Office 中的一些设置时,这可以成为一项非常有用的功能。在此之前,我将保持秘密。

参考文献

以下参考资料对我的项目和文章的创建很有帮助,所以我认为应该给予它们适当的认可。

历史

  • 2005 年 1 月 15 日 - v1.0,作者:Evan Stone。
© . All rights reserved.