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

.NET Shell Extensions - Shell Icon Overlay Handlers (图标叠加处理程序)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (30投票s)

2013 年 2 月 13 日

CPOL

7分钟阅读

viewsIcon

203992

downloadIcon

6833

使用 .NET 创建 Shell 图标覆盖处理程序!

引言

Shell 图标覆盖处理程序可以非常有用。它们允许您在 Shell 对象上显示一个图标覆盖,以提供额外的信息。像 Dropbox 这样的程序就使用这些覆盖来显示图标是否已同步。在本文中,我将向您展示如何使用 SharpShell 轻松创建 Shell 图标覆盖处理程序!

下面是我们创建的示例的屏幕截图 - 它在只读文件上显示一个锁形图标。

上图:文件夹中的一些文本文件。安装此 Shell 图标扩展后,只读文件将带有锁形覆盖图标。

系列文章

本文是 '.NET Shell Extensions' 系列的一部分,该系列包括

  1. .NET Shell Extensions - Shell Context Menus (右键菜单扩展)
  2. .NET Shell Extensions - Shell Icon Handlers (图标处理程序)
  3. .NET Shell Extensions - Shell Info Tip Handlers (信息提示处理程序)
  4. .NET Shell Extensions - Shell Drop Handlers (拖放处理程序)
  5. .NET Shell Extensions - Shell Preview Handlers (预览处理程序)
  6. .NET Shell Extensions - Shell Icon Overlay Handlers (图标叠加处理程序)
  7. .NET Shell Extensions - Shell Thumbnail Handlers (缩略图处理程序)
  8. .NET Shell Extensions - Shell Property Sheets (属性表处理程序)

入门

Shell 扩展通常用 C 或 C++ 编写。在 .NET Framework 4 发布之前,无法使用 .NET 可靠地创建 Shell 扩展。现在您可以了。使用 SharpShell 库,所有 COM 样板代码都已为您处理,您只需创建一个扩展类,用一些属性对其进行装饰,并重写一些函数。

为了展示这有多么容易,让我们看看只读文件图标覆盖处理程序的完整代码。

我们的目标

这是只读覆盖处理程序的完整代码。它非常精简——现在我们已经完整地看到了它,我将逐步介绍如何创建自己的扩展。

/// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
[ComVisible(true)]
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler
{
    /// <summary>
    /// Called by the system to get the priority, which is used to determine
    /// which icon overlay to use if there are multiple handlers. The priority
    /// must be between 0 and 100, where 0 is the highest priority.
    /// </summary>
    /// <returns>
    /// A value between 0 and 100, where 0 is the highest priority.
    /// </returns>
    protected override int GetPriority()
    {
        //  The read only icon overlay is very low priority
        return 90;
    }
 
    /// <summary>
    /// Determines whether an overlay should be shown for the shell item 
    /// with the path 'path' and
    /// the shell attributes 'attributes'
    /// </summary>
    /// <param name="path">The path for the shell item. This is not necessarily the path
    /// to a physical file or folder.</param>
    /// <param name="attributes">The attributes of the shell item.</param>
    /// <returns>
    ///   <c>true</c> if this an overlay should be shown for the specified item; 
    ///  otherwise, <c>false</c>.
    /// </returns>
    protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
    {
        try
        {
            //  Get the file attributes
            var fileAttributes = new FileInfo(path);
 
            //  Return true if the file is read only, meaning we'll show the overlay
            return fileAttributes.IsReadOnly;
        }
        catch (Exception)
        {
            return false;
        }
    }
 
    /// <summary>
    /// Called to get the icon to show as the overlay icon
    /// </summary>
    /// <returns>
    /// The overlay icon
    /// </returns>
    protected override System.Drawing.Icon GetOverlayIcon()
    {
        //  Return the read only icon
        return Properties.Resources.ReadOnly;
    }
} 

这大部分是注释——所以您可以看到,使用 SharpShell 创建覆盖处理程序非常简单!

步骤 1:创建项目

首先,创建一个新的 C# 类库项目。

提示:您可以使用 Visual Basic 而不是 C# - 在本文中,源代码是 C#,但创建 Visual Basic Shell Extension 的方法是一样的。

在此示例中,我们将项目命名为 'ReadOnlyFileIconOverlayHandler'。

提示:如果您通过 Nuget 添加 SharpShell 的引用,下方的引用将自动添加。

现在添加以下引用

  1. System.Windows.Forms
  2. System.Drawing

将 'Class1.cs' 文件重命名为 'ReadOnlyFileIconOverlayHandler.cs'。

步骤 2:引用 SharpShell

现在我们需要添加对核心 SharpShell 库的引用。你可以通过几种不同的方式做到这一点:

添加引用

下载文章顶部的 'SharpShell Library' zip 文件,并添加对下载的 SharpShell.dll 文件的引用。

提示:本文的下载在撰写时是正确的——如果您需要最新版本,请使用 Nuget(如下所述)或从 sharpshell.codeplex.com 获取库。

使用 Nuget

如果您安装了 Nuget,只需快速搜索 SharpShell 并直接安装它 - 或在 https://nuget.net.cn/packages/SharpShell 获取包详细信息。

使用 CodePlex

与其从本页面获取库(可能不是最新版本),您还可以随时从 CodePlex 获取最新版本的库——在 SharpShell 主页上,网址是 sharpshell.codeplex.com。Nuget 始终拥有最新稳定版本——CodePlex 可能有测试版,而 CodeProject 文章将拥有撰写时可用的版本。

步骤 3:继承自 SharpIconOverlayHandler

现在事情变得有趣了。让您的 ReadOnlyFileIconOverlayHandler 类继承自 SharpIconOverlayHandler

/// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler

现在我们必须实现该类的抽象成员。右键单击该行的 SharpIconOverlayHandler 部分,然后选择 '实现抽象类'。这将创建我们必须提供的函数的空实现。

 /// <summary>
/// The ReadOnlyFileIconOverlayHandler is an IconOverlayHandler that shows
/// a padlock icon over files that are read only.
/// </summary>
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler
{
    protected override int GetPriority()
    {
        throw new NotImplementedException();
    }
 
    protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
    {
        throw new NotImplementedException();
    }
 
    protected override System.Drawing.Icon GetOverlayIcon()
    {
        throw new NotImplementedException();
    }
}

下面是对这些函数的描述以及如何使用它们

GetPriority

此函数必须返回处理程序的优先级。当一个文件有两个图标覆盖时,将使用优先级最高者。为了混淆视听,最高优先级是 0——最低优先级是 100。

CanShowOverlay

每次显示 Shell 项时,都会调用此函数。Shell 项的路径在 path 参数中提供。还提供了 FILE_ATTRIBUTE 标志(例如 FILE_ATTRIBUTE_DIRECTORY 这样的属性)。如果要为指定的*.文件显示图标覆盖,请返回 true

GetOverlayIcon

此函数必须返回一个标准的 .NET System.Drawing.Icon 对象,该对象是要使用的覆盖图标。

步骤 3:实现函数

我们对这些函数的实现将如下所示。首先,GetPriority

protected override int GetPriority()
{
    //  The read only icon overlay is very low priority.
    return 90;
}

此覆盖是有用的,但不如 TortoiseSVN 的状态图标等重要,因此我们将其优先级设置得较低。

现在,CanShowOverlay

protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
{
    try
    {
        //  Get the file attributes
        var fileAttributes = new FileInfo(path);
 
        //  Return true if the file is read only, meaning we'll show the overlay
        return fileAttributes.IsReadOnly;
    }
    catch (Exception)
    {
        return false;
    }
} 

我们只在能够获取文件属性而不引发异常,并且这些属性指示只读时返回 true(显示覆盖)。(为什么我不使用 FILE_ATTRIBUTE_READONLY?嗯,显然它对目录不起作用。)

最后一个函数,GetOverlayIcon

protected override System.Drawing.Icon GetOverlayIcon()
{
    //  Return the read only icon
    return Properties.Resources.ReadOnly;
}

在项目中,我向资源添加了一个名为 'ReadOnly' 的图标——它只是返回该图标。

步骤 4:处理 COM 注册

只剩下几件事情要做。首先,我们必须向类添加 COMVisible 属性。

[ComVisible(true)]
public class ReadOnlyFileIconOverlayHandler : SharpIconOverlayHandler

接下来,我们必须为程序集指定一个强名称。有办法绕过此要求,但通常这是最佳方法。为此,右键单击项目并选择 '属性'。然后转到 '签名'。选择 '签名程序集',为密钥指定 '新建',然后选择一个密钥名称。您可以为密钥设置密码,但这并非必需。

调试 Shell Extension

Shell 扩展将托管在 Windows 资源管理器中——由于 .NET COM 服务器加载方式的曲折性,几乎不可能将调试器附加到进程中并逐步调试托管代码。但是,有一种方法可以快速调试您的扩展。SharpShell 附带了一些工具,可以更轻松地处理 SharpShell COM 服务器,其中之一是服务器管理器。我们可以使用此工具调试我们的扩展。打开服务器管理器,然后加载扩展。选择 '安装',然后选择 '注册',现在打开测试 Shell 并选择 'Shell 打开对话框'——现在当您在文件系统中移动时,您的扩展中的断点应该会被命中。

上图:服务器管理器

上图:测试 Shell

安装和注册 Shell Extension

有几种方法可以安装和注册 SharpShell Shell 扩展。在本节中,我将详细介绍所有这些方法。

regasm 工具

您可以使用 'regasm' 工具安装和注册 Shell 扩展。在使用 regasm 时,Shell 扩展将安装到注册表中(即,COM 服务器的类 ID 将放入 COM 服务器类部分,并与实际服务器文件的路径关联),它还将注册关联。

服务器管理器工具

服务器管理器工具是我安装/卸载和注册/注销的首选方法,至少在开发过程中,因为它允许您将安装和注册作为单独的步骤。它还可以让您指定是在 32 位还是 64 位模式下安装/卸载等。

手动注册表操作

通常是一种糟糕的方法,但如果绝对有必要,那么 MSDN 文档中描述了手动注册 COM 服务器或托管 COM 服务器必须对注册表进行的更改。文档列在“有用资源”部分。

备忘单

以下是一些使用 SharpShell 和图标覆盖处理程序的有用技巧。

  • 您的覆盖似乎不起作用?打开 regedit 并检查路径
    HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayHandlers
    Windows 只支持有限数量的处理程序——按字母顺序排列。可能安装了太多。
  • 如果您需要记录事件,请以管理员身份运行服务器管理器,然后选择 '诊断 > 启用 SharpShell 日志'。您现在可以使用函数
    Log
    LogError
    LogWarning
    在您的服务器类中,这些消息将被写入 Windows 事件日志(在“应用程序”下)。

历史

  • 2013 年 9 月 14 日:初始版本
© . All rights reserved.