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

.NET Shell Extensions - Shell Property Sheets (属性表处理程序)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (18投票s)

2013年4月6日

CPOL

7分钟阅读

viewsIcon

102878

downloadIcon

3152

使用 .NET 快速构建 Shell 属性表

引言

在本文中,我将向您展示如何使用 SharpShell 快速创建 Shell 属性表扩展。这些扩展为文件、网络共享、文件夹等 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 属性表扩展

从技术上讲,Shell 属性表扩展是一个 COM 服务器,它导出一个实现 IShellPropSheetExt 接口的对象。此扩展允许我们执行两项操作 - 向 Shell 属性表添加属性页,或替换它们。

现在,通常在托管环境中处理像这样的老式 API 会非常困难。您需要进行大量互操作,需要从 Win32 API 导入函数来创建属性页、创建消息循环等。我们将使用 SharpShell 库来处理所有底层工作,从而让我们轻松地创建属性页并将其添加到我们的扩展类中。

现在我们知道了什么是属性表扩展,就可以开始实现一个了。

步骤 1:创建项目

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

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

在此示例中,我们将项目命名为“FileTimesPropertySheet”。

现在添加以下引用

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

将“Class1.cs”重命名为“FileTimesPropertySheet.cs”。

步骤 2:引用 SharpShell

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

使用 Nuget

如果您安装了 Nuget,只需快速搜索 SharpShell 并直接安装它 - 或者在 https://nuget.net.cn/packages/SharpShell 获取包详细信息。这是最好的方法 - 您将始终获得最新版本的库,它会自动添加任何依赖项。

添加引用

在文章顶部下载“SharpShell Core Library”zip 文件,并引用下载的 SharpShell.dll 文件。

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

使用 CodePlex

与从本页面获取可能不是最新版本的库不同,您始终可以从 CodePlex - SharpShell 主页 sharpshell.codeplex.com 获取最新版本的库。Nuget 将始终具有最新的稳定版本 - CodePlex 可能有可用的 Beta 版本,而 Code Project 文章将具有撰写时可用的版本。

步骤 3:继承自 SharpPropertySheet

我们必须有一个继承自 SharpPropertySheet 的类 - 这将是主扩展类。让我们采用我们命名的文件“FileTimesPropertySheet”并立即继承自 SharpPropertySheet

public class FileTimesPropertySheet : SharpPropertySheet

现在我们将不得不创建两个抽象函数的实现

CanShowSheet

此函数返回一个 bool。如果结果为 true,那么我们将显示我们创建的属性表页面,否则我们将不显示它们。这是我们的实现

protected override bool CanShowSheet()
{
    //  We will only show the resources pages if we have ONE file selected
    return SelectedItemPaths.Count() == 1;
} 

因为我们继承自 SharpPropertySheet,所以我们有一个名为“SelectedItemPaths”的属性 - 这是一个 string 的可枚举集合,存储了用户在调用属性表时选择的路径。在我们的示例中,我们只会在只选择了一个文件的情况下显示页面。

CreatePages

此函数返回一组 SharpPropertyPage 对象 - 这些是我们即将添加到 Shell 属性表的实际属性页。

这是我们的实现将如何显示

protected override IEnumerable<SharpPropertyPage> CreatePages()
{
    //  Create the property sheet page
    var page = new FileTimesPropertyPage();
 
    //  Return the pages we've created
    return new[] {page};
}

在我们创建“FileTimesPropertyPage”类之前,这不会起作用,我们很快就会做到这一点!

步骤 4:创建关联

我们需要定义此扩展将用于哪些 Shell 对象。这是通过使用 COMServerAssociation 属性来装饰扩展来完成的。以下是我们如何将此扩展应用于所有文件。

[COMServerAssociation(AssociationType.AllFiles)]
public class FileTimesPropertySheet : SharpPropertySheet 

我们可以进行多种不同的关联 - 我们可以与文件、文件夹、具有特定扩展名的文件等进行关联。这里有一个更完整的指南,地址是 COM Server Associations 页面。

步骤 5:创建属性表页面

您可以根据需要多次执行此步骤 - 一个属性表扩展可以添加任意数量的页面。

首先,向您的类库添加一个 UserControl,并将其命名为“FileTimesPropertyPage”。现在打开该控件的代码隐藏文件,并将父类从“UserControl”更改为“SharpPropertyPage”。

这是我们可以做的第一件事 - 设置属性页的标题

/// <summary>
/// The FileTimesPropertyPage class
/// </summary>
public partial class FileTimesPropertyPage : SharpPropertyPage
{
    /// <summary>
    /// Initializes a new instance of the <see cref="FileTimesPropertyPage"/> class
    /// </summary>
    public FileTimesPropertyPage()
    {
        InitializeComponent();
 
        //  Set the page title
        PageTitle = "File Times";
 
        //  Note: You can also set the icon to be used:
        //  PageIcon = Properties.Resources.SomeIcon;
    }

我们通过设置 PageTitle 属性来设置页面的标题。我们还可以通过设置 PageIcon 属性来选择性地设置页面的图标。

现在 SharpPropertyPage 中有一系列虚拟函数,我们可以选择重写它们。在这里,我将介绍关键函数。

OnPropertyPageInitialised

当页面创建并即将显示给用户时,会调用此函数。如果显示了属性表,但用户没有点击此特定页面,则不会调用此函数。任何初始化都应在此处完成。在此函数中,您将获得父 SharpPropertySheet 对象,其中包含选定的文件路径。

private string filePath;
 
/// <summary>
/// Called when the page is initialized
/// </summary>
/// <param name="parent">The parent property sheet.</param>
protected override void OnPropertyPageInitialised(SharpPropertySheet parent)
{
    //  Store the file path
    filePath = parent.SelectedItemPaths.First();
 
    //  Load the file times into the dialog
    LoadFileTimes();
}

在我们的示例中,我们存储选定的文件路径,然后通过(LoadFileTimes 函数)从文件时间更新 UI。

我们还应该实现哪些其他函数?好吧,几乎总是,我们将希望处理“确定”和“应用

OnPropertySheetOK 和 OnPropertySheetApply

/// <summary>
/// Called when apply is pressed on the property sheet, or the property
/// sheet is dismissed with the OK button
/// </summary>
protected override void OnPropertySheetApply()
{
    //  Save the changes
    SaveFileTimes();
}
 
/// <summary>
/// Called when OK is pressed on the property sheet
/// </summary>
protected override void OnPropertySheetOK()
{
    //  Save the changes
    SaveFileTimes();
}

这里没有什么太复杂的 - 在这个类中,我们只会保存用户所做的任何更改。

属性表页面快速参考

这是属性表页面的快速参考。

函数 用法
OnPropertyPageInitialised 在页面必须初始化时调用。
OnPropertyPageSetActive 当页面即将呈现给用户时调用。这总是在 OnPropertyPageInitialised 之后调用。
OnPropertyPageKillActive 当页面即将被取消选择时调用。
OnPropertySheetApply 按下“应用”按钮时调用。
OnPropertySheetOK 按下“确定”按钮时调用。
OnPropertySheetCancel 按下“取消”按钮时调用。
OnPropertySheetClose 按下对话框右上角的“x”时调用。
SetPageDataChanged 调用此函数以启用“应用”按钮。

步骤 6:暴露给 COM

现在我们需要做几件事来让 Shell 创建我们的类。

首先,我们必须将 COMVisible 属性添加到我们的类

[ComVisible(true)]
[COMServerAssociation(AssociationType.AllFiles)]
public class FileTimesPropertySheet : SharpPropertySheet 

现在我们必须签名程序集。要做到这一点,右键单击项目并选择“属性”。然后转到“签名”。选择“签名程序集”,为密钥指定“新建”并选择一个密钥名称。如果您愿意,可以为密钥设置项目密码,但这不是必需的

调试 Shell Extension

Shell 扩展可以通过以下方式进行调试

  1. 从源代码运行“Server Manager”项目。
  2. 打开您构建的服务器,选择它,选择“安装”,然后选择适合您处理器架构的“注册”。
  3. 现在按“打开 Shell 对话框”按钮。
  4. 这将显示 Shell 打开对话框。如果您右键单击文件并选择属性,则会显示扩展,并且任何已启用的断点都将成功运行,因为 Shell 窗口位于我们附加了调试器的地址空间中。
  5. 调试完成后,您可以关闭 Shell 打开对话框并注销/卸载它。

安装和注册 Shell Extension

有关注册 SharpShell 扩展的指南,请参阅文章 Shell Context Menus

历史

  • 2013年4月8日:初始版本
© . All rights reserved.