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






4.59/5 (25投票s)
2005 年 1 月 18 日
6分钟阅读

166679

3320
本文介绍如何使用 C# 为 Windows 资源管理器中的文件夹分配图标。
引言
本文讨论了一个简单的类,该类可用于为在 Windows 资源管理器中显示的文件夹分配图标。
背景
在我与一位 UI 工程师的讨论过程中,他提到他发现了一种为 Windows 资源管理器中的文件夹创建图标的方法(选择文件夹:属性:自定义选项卡:更改图标...),我开始想,“一定有一种方法可以以编程方式实现这一点”。
事实证明,不仅有一种方法可以做到这一点,而且这项任务还相当容易处理。我们当时关于这个话题的讨论是一个更大项目的组成部分,而这将是另一篇文章的来源。然而,要实现最终目标,首先需要解决的问题是如何为文件夹分配图标——这本身似乎是一个足够有趣的话题,可以写一篇文章。
使用代码
如果您只想试用示例应用程序,只需打开 FolderIcons.sln 解决方案文件,然后在 Visual Studio IDE 中生成或运行它。
讨论
为文件夹分配图标基本上涉及两个步骤(如果算上创建文件夹,则可能为三个步骤)
- 在要创建图标的文件夹(“目标文件夹”)中创建一个 desktop.ini 文件。
- 将目标文件夹的属性设置为“系统”。
为了完成这些步骤,我创建了两个类。第一个名为 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 中的一些设置时,这可以成为一项非常有用的功能。在此之前,我将保持秘密。
参考文献
以下参考资料对我的项目和文章的创建很有帮助,所以我认为应该给予它们适当的认可。
- 我如何更改 Delphi 中的文件夹图标?,作者:Borland Developer Support Staff,Borland Developer Network,2001 年 7 月 13 日。
- .NET 的 INI 类,作者:Adam Woods (aejw),The Code Project,2004 年 2 月 6 日。
历史
- 2005 年 1 月 15 日 - v1.0,作者:Evan Stone。