关联图标图像控件






3.92/5 (9投票s)
2005年5月30日
5分钟阅读

114954

867
一个显示与给定文件或文件扩展名关联的图标的 Web 控件。
引言
此自定义服务器控件显示与给定文件扩展名当前关联的图标。文件图标关联由操作系统维护,只需一次 Win32 API 调用即可检索。
当您只需要显示一个众所周知的图标,或者当您想显示带有相应图标的文件列表时,可以使用此控件。
使用代码
文章下载包含一个 VS.NET 2003 项目,这是一个 ASP.NET 应用程序示例。该应用程序包含两个包含代码重要部分的文件。这些文件是 AssociatedIcon.cs 和 IconExtractor.cs。
我建议您不要直接解压压缩文件中的整个项目,而是使用您自己的 Visual Studio .NET 安装创建一个名为 AssociatedIcons 的新 C# ASP.NET 项目。在您的应用程序中添加两个文件夹:Controls 和 IconStubs。删除默认的 Webform1.aspx 文件,并添加一个名为 TestPage 的新 WebForm。
为了节省大量打字时间,只需获取 IconExtractor.cs 文件并将其放入项目中的 Controls 文件夹。在同一个 Controls 文件夹中添加一个名为 AssociatedIcon
的新类。这个类将是我们的自定义控件。
完成所有这些之后,您的项目应该看起来像下面的图片
将以下代码添加到您刚刚创建的 AssociatedIcon.cs 文件中
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
namespace AssociatedIcons.Controls
{
[ToolboxData("<{0}:AssociatedIcon
runat=server></{0}:AssociatedIcon>")]
public class AssociatedIcon : Image
{
/*****
* This control accepts a file name or file extension,
* determines the associated icon, and displays it on the page
* ***/
/// <summary>
/// Gets or sets a file name or extension (including the dot)
/// to display the associated icon
/// </summary>
public string ExtensionOrFile
{
get
{
string s = (string)ViewState["ExtensionOrFile"];
if(s == null) return "";
return s;
}
set{ ViewState["ExtensionOrFile"] = value; }
}
/// <summary>
/// Determines if the icon size will be 16x16 or 32x32 pixels
/// </summary>
public bool LargeIcon
{
get
{
object obj = ViewState["LargeIcon"];
if(obj == null) return false;
return (bool)obj;
}
set
{
ViewState["LargeIcon"] = value;
}
}
public override string ImageUrl
{
get{ return base.ImageUrl;}
set{ throw new
InvalidOperationException("The ImageUrl cannot be set.");}
}
protected override void OnLoad(EventArgs e)
{
if(!Page.IsPostBack)
base.ImageUrl =
IconExtractor.GetUrlToIcon(ExtensionOrFile, LargeIcon);
}
}
}
因为我们将在 IconStubs 文件夹中写入文件,所以您需要为 ASPNET 用户在该文件夹中授予*写*权限。如果您以前从未做过,这个过程很简单。在任何 Windows 资源管理器窗口中,找到 IconStubs 文件夹,右键单击它并选择*属性*。转到*安全*选项卡。如果选中了*允许继承的权限 [...]*复选框,请取消选中它。使用*添加*按钮将 ASPNET 用户添加到列表中(如果它尚未在列表中)。在列表中选择 ASPNET 用户,然后仅选择*允许写入*复选框。请参见下图。完成后,单击确定即可。
此控件的工作原理
正如您从上面的代码中可以看到的,我们的控件是 System.Web.UI.WebControls.Image
服务器控件的一个相当简单的扩展。我们添加了一个属性来保存所需的文件扩展名(或文件名),另一个属性来指定所需的图标是小(16 x 16 像素)还是大(32 x 32 像素)版本。我们还禁止直接设置 ImageUrl
属性,以免任何人无意中更改它。
您也可以注意到,这个控件的代码中并没有太多东西。实际的进程由 IconExtractor
类实现。
IconExtractor 类
图标提取过程的核心是调用 SHGetFileInfo
Shell32 Windows API。此 API 除了其他功能外,还可以为给定文件提供关联图标(小或大)的句柄。之后,代码会将图标保存为具有透明背景的 PNG 图像,并存放在 IconStubs 文件夹中。下次请求相同的扩展名图标时,将返回已存在的图像文件的 URL,而无需创建新文件。一段时间后,您应该会发现您的 IconStubs 文件夹中充满了您使用的所有图标的图像,如下所示
注意:IE(至少我拥有的版本:6.0.2800.1106)在透明 PNG 渲染方面存在缺陷,导致透明区域渲染为灰色。代码中包含注释,可帮助您将实现从 PNG 更改为 GIF,但会丢失透明背景。
注意:在 .NET 中实现 GIF 图像的透明背景非常复杂,涉及*不安全*的代码块,因此为了简洁(如果您希望我诚实地说,也可以说是懒惰 :) ),我决定不将其包含在此示例中。
测试控件
要查看控件的工作原理,让我们在 TestPage.aspx 中添加一些内容。首先,让我们使用我们的 Controls
命名空间注册一个标签前缀。将以下内容添加到页面 ASPX 的顶部
<%@ Register Tagprefix="SP"
Namespace="AssociatedIcons.Controls" Assembly="AssociatedIcons" %>
现在,让我们在页面中添加一些我们的控件实例,如下所示
<form id="TestPage" method="post" runat="server">
<br>
<SP:AssociatedIcon id="file1" runat="server"
ExtensionOrFile=".doc" largeIcon="True" />
MyDocument.doc
<br>
<SP:AssociatedIcon id="file2" runat="server"
ExtensionOrFile="file.bmp" largeIcon="false" />
MyIcon.bmp
<br>
<SP:AssociatedIcon id="Associatedicon1" runat="server"
ExtensionOrFile="file.jpg" largeIcon="true" />
MyIcon.jpg
<br>
<SP:AssociatedIcon id="Associatedicon2" runat="server"
ExtensionOrFile="file.gif" largeIcon="false" />
MyIcon.gif
<br>
<SP:AssociatedIcon id="Associatedicon3" runat="server"
ExtensionOrFile="file.mp3" largeIcon="true" />
MyIcon.mp3
<br>
<asp:Button ID=test Runat=server Text=test />
</form>
当您保存、编译并运行此页面时,您应该会看到类似于下图的内容。图标可能会因您将哪些程序与文件扩展名关联而异。
增强建议
与任何示例一样,本文中的代码远非完美,并且充满了新功能或增强功能的可能性(可能还存在一些错误)。一些我想到的改进此代码的想法是
- 使用配置值来确定图标图像文件的物理路径和虚拟路径。这样,您就可以在多个应用程序中使用此控件,并共享同一文件夹中的同一组图标。
- 实现 GIF 的背景透明。将代码更改为生成 GIF 而不是 PNG(同时 IE 尚未修复透明 PNG 错误),并将背景颜色设为透明。这里有两个不错的参考资源可以帮助您:Eric Johnson 的使用 GDI+ 实现透明背景(新闻组帖子)和 Bob Powell 的GDI+ FAQ。
参考文献
- PInvoke.net - 在没有这个很棒的 Wiki 和贡献者的帮助下,我无法避免使用 Win32 API。
- Bob Powell 的GDI+ FAQ 关于 GIF 透明度。
- Eric Johnson 的“使用 GDI+ 实现透明背景”。如果链接失效,只需在 microsoft.public.dotnet.framework.drawing 新闻组中搜索标题即可。
历史
- 2005 年 5 月 29 日 - 代码已提交。