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

FilterBuilder

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.55/5 (13投票s)

2009 年 9 月 4 日

CPOL

11分钟阅读

viewsIcon

58250

downloadIcon

701

FilterBuilder 是一个简单的实用程序,允许您轻松创建对话框过滤器。

目录

引言

FilterBuilder 是一个简单的实用工具,可让您轻松创建对话框过滤器。它不仅包含 135 种最常见的文件过滤器,而且 FilterBuilder 还允许您创建无限组合的文件过滤器,而无需维护冗长的过滤器 string

背景

我编写 FilterBuilder 是因为我不喜欢为我使用的每个打开/保存对话框编写冗长的过滤器 string。我需要一种快速、简单的方法来将过滤器添加到标准的打开和保存文件对话框中。

我的一些要求是:

  • 该实用工具必须具有许多预设过滤器。
  • 该实用工具还必须接受自定义过滤器。
  • 该实用工具必须能够轻松添加/删除过滤器。
  • 该实用工具必须能够生成完整的过滤器 string

Using the Code

要使用代码,请首先引用 FB.dll 库。它位于 Bin/Release 文件夹中。

添加一个 Imports 语句,如下所示:

Imports FB

创建 FilterBuilder 类的实例。要添加过滤器,请调用实例的 Add 方法,并传入 FilterBuilder.Filters enum 中的值或自定义过滤器,如下所示:

'Add a text files filter
FilterBuild.Add(FilterBuilder.Filters.TextFiles)

'Add a custom filter
FilterBuild.Add("Foo Files", "foo")

要删除过滤器,请调用 Remove 方法。

'Remove rich text files filter
FilterBuild.Remove(FilterBuilder.Filters.RichTextFiles)

要获取完整的过滤器 string,请调用 ToString 方法。

'Get filter string
OpenFileDialog1.Filter = FilterBuild.ToString()

工作原理

编写对话框过滤器的标准方法如下:

"Plain Text Files (*.txt)|*.txt"

而在 FilterBuilder 中,可以使用这种方式实现相同的功能:

FilterBuild.Add(FilterBuilder.Filters.TextFiles)

毫无疑问,第二个示例使用起来要容易得多,并且在不同的对话框之间也建立了一致性。

FilterBuilder 使用 List(Of String)StringBuilder 来跟踪过滤器,并返回完整的过滤器 string

为了简单起见,我选择不让 FilterBuilder 直接继承自 List(Of T),而是将其用作内部组件。我认为 List(Of T) 暴露了许多 FilterBuilder 实际需要的功能和属性。

通过 Add 方法添加的所有过滤器都会添加到内部 List 中,反之,通过 Remove 方法删除的过滤器也会从 List 中移除。

就是一个普通的列表。简单吧?

如果将 enum 值传递给 Add 方法(有关更多信息,请参阅“示例”部分),则该值将通过 private ReturnFilterAsString 方法转换为 string 值,然后添加到 List 中。如果传入两个 string 值,则过滤器 string 将在关联的 Add 方法中构建,并添加到 List 中。

最棒的部分实际上是获取所需的过滤器 string - 用于打开和保存文件对话框。如“使用代码”部分所述,这是通过 ToString 方法完成的。ToString 方法使用 For Each 循环迭代 List(Of String) 中的所有当前项,并将每个项与“|”字符连接起来。之后,结果 string 将从两端修剪掉空格(“ ”)和“|”字符。最终结果是一个已准备好在对话框中使用的过滤器 string

FilterGroups

到底什么是 FilterGroup?嗯,我不知道是否有关于如下内容的官方术语:

"Documents (*.html,*.rtf,*.txt)|*.html;*.rtf;*.txt"

……所以,我创造了“FilterGroup”这个术语。

正如您在上面看到的,这是一个多项过滤器 string ,允许显示 HTML、RTF 和 TXT 文件。但是,使用 FilterBuilder ,您不应该期望手动编写冗长的过滤器 string

这是实现上面示例相同结果的新方法:

Dim docsGroup As New FilterGroup("Documents")

'Add the filters in this group
With docsGroup
	.Add(FilterBuilder.Filters.HTML_Files)
	.Add(FilterBuilder.Filters.RichTextFiles)
	.Add(FilterBuilder.Filters.TextFiles)
End With

好的,让我解释一下发生了什么。

  • 第一行是创建一个 FilterGroup 类的新实例(它接受一个参数 - 组的名称)。
  • .Add”语句正在向组添加过滤器。Add 语句与 FilterBuilder 类中的语句相同,因此您可以传入在使用 FilterBuilder 正常使用时相同的过滤器。

那么,这与 FilterBuilder 本身有什么关系呢?

FilterBuilder 包含一个额外的 Add 方法,它只接受一个 FilterGroup 作为参数。所以,这意味着在完成创建 FilterGroup 后,您可以像这样将其传递给 FilterBuilder

FilterBuild.Add(docsGroup)

摘要

  • 创建一个 FilterGroup,其名称将显示在“打开/保存”对话框中(例如,“Documents”)。
  • 使用组的 Add 方法,添加将包含在此组中的过滤器。
  • 使用您的 FilterBuilder 实例的 Add 方法将 FilterGroup 添加到主过滤器列表中。
  • 像往常一样调用 ToString 方法以获取最终的过滤器 string

注意:有关更高级的示例,请查看演示项目下载中的示例 #6。

系统文件类型

如果您还没有被我刚才读到的内容说服,那么我向您保证,这一定会引起您的注意。

系统文件类型 - 只需知道扩展名即可添加对话框过滤器的功能。没有描述,没有研究,只有一个简单的文件扩展名。

所以,这个

"dll"

变成了这个

"Application Extensions (*.dll)|*.dll"

问题:好的,那么这个小小的扩展名是如何变成一个完整的内部过滤器字符串的?

  • FilterBuilder 从计算机的注册表中获取正确的描述。对于这一步,我使用了与 Man Vuong 的文章 此处 [^] 中概述的完全相同的方法,我建议您阅读一下。
  • 获取描述后,FilterBuilder 会将其与扩展名连接起来,并添加“*”、“.”和“|”字符。

问题:我如何通过知道其扩展名来添加过滤器?

'Add the filter
FilterBuild.Add("dll")

与通常添加过滤器的方式几乎相同。只是将 string 扩展名传递给 Add 方法。

注意:您可以选择在扩展名前加上点(例如,“.dll”,而不是“dll”)。两种方式都可以。

问题:Add 方法的可选复数参数呢?

'Add the filter (first way)
FilterBuild.Add("dll")

'Add the filter (second way)
FilterBuild.Add("dll", False)

当我第一次创建 Filters enum 时,我将描述设置为复数形式,以考虑可以选择多个文件。因此,默认情况下,当从注册表中检索系统文件描述时,会对其进行检查和修改,以确保它们是复数形式(即,“Files”而不是“File”)。如果您不希望这些描述是复数形式,则将“False”值作为此重载 Add 方法的第二个参数传递(如上所示)。

附加信息

您可以通过调用 GetSystemFileTypes() 方法来获取所有系统文件类型扩展名的列表。

Dim l As List(Of String) = FilterBuild.GetSystemFileTypes()

结论

当您不知道扩展名的描述,或者希望在注册表中的值更改时自动更新时,系统文件类型非常有用。

摘要

就是这样!
只需调用 Add 方法 - 传入文件的 string 扩展名。如果该文件存在于用户的系统中,它将被添加到过滤器字符串中。

系统文件类型图标

作为上述主题的延续,本节将介绍 FilterBuilder 如何支持获取计算机注册表中任何文件类型的系统文件类型图标。

下面是一个获取预设过滤器(来自 FilterBuilder.Filters enum 的一个)文件类型图标的示例:

Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon( _
FilterBuilder.Filters.RichTextFiles)

现在是一个获取系统文件类型(非 enum 中的)文件类型图标的示例:

Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon("rtf")

注意:文件类型图标返回的是(不出所料地)Icon 格式,但可以像下面的完整示例那样更改为位图。

完整示例

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim picIconView As New System.Windows.Forms.PictureBox()

'Get the icon for XML files
Dim icon As System.Drawing.Icon = _
FilterBuild.GetSystemFileTypeIcon( _
FilterBuilder.Filters.XML_Files)

'Convert icon to bitmap and set as image
picIconView.Image = icon.ToBitmap()

附加信息

要更改返回图标的大小,您可以修改 FileTypeIconSize 属性。它是一个 16x16 像素或 32x32 像素的图标。

摘要

就是这样!
要获取文件类型的关联系统图像,只需调用 GetSystemFileTypeIcon 方法 - 传入预设过滤器(来自 Filters enum)或文件类型的 string 扩展名。

自定义过滤器

FilterBuilder 的一个很棒的功能是,它不仅允许您使用预设过滤器的任何组合,还允许您包含自定义过滤器。这特别有用,如果您像我一样,在您的应用程序中使用自己的文件类型。继续阅读,了解如何在只有一行代码的情况下添加自定义过滤器……

到目前为止,您可能已经理解了,过滤器是通过重载的 Add 方法添加的。其中一个 Add 方法接受两个 String 参数。让我们以下面的示例为例:

FilterBuild.Add("Foo Files", "foo")

在此示例中,我添加了一个自定义过滤器,它只允许扩展名为 .foo 的文件显示。这与 string

"Foo Files (*.foo)|*.foo"

注意:您可以选择在扩展名前加上点(例如,“.foo”,而不是“foo”)。两种方式都可以。

摘要

就是这样!
要添加自定义过滤器,只需调用 Add 方法 - 传入文件的描述和文件的扩展名。

示例

以下是一些展示 FilterBuilder 中可用方法的示例。更多示例包含在附加的“演示项目”下载中。

注意:如果需要,您可以创建一个 Filters 数组,然后只需将数组传递给重载的 Add 方法。这在第二个示例中显示。

示例 #1 -- 文本、RTF 和 HTML 文件过滤器

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Add the filters
FilterBuild.Add(FilterBuilder.Filters.TextFiles)
FilterBuild.Add(FilterBuilder.Filters.RichTextFiles)
FilterBuild.Add(FilterBuilder.Filters.HTML_Files)

With ofd

	'Set the filter
	.Filter = FilterBuild.ToString()

	'Set filter index to the first item
	.FilterIndex = 1

	'Get the file extension of text files
	.DefaultExt = FilterBuild.GetFileExtension( _
	FilterBuilder.Filters.TextFiles)

	.ShowDialog()

End With

正如您在上例中可能注意到的,我使用了 GetFileExtension 方法 - 它返回 FilterBuilder.Filters enum 的任何预设值的关联文件扩展名(在本例中为“.txt”)。

示例 #2 -- 许多常见音乐文件过滤器

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Make an array of filters
Dim filters() As FilterBuilder.Filters = { _
FilterBuilder.Filters.MP3_AudioFiles, _
FilterBuilder.Filters.AAC_Files, _
FilterBuilder.Filters.WAVE_AudioFiles, _
FilterBuilder.Filters.MPEG2_AudioFiles, _
FilterBuilder.Filters.RealAudioFiles, _
FilterBuilder.Filters.MIDI_Files}

'Add the "filters" array - the add method is overloaded
FilterBuild.Add(filters)

With ofd

	'Set the filter
	.Filter = FilterBuild.ToString()

 	'Sets the selected item in the filter box to MP3 files
 	.FilterIndex = FilterBuild.GetFilterIndex( _
 	FilterBuilder.Filters.MP3_AudioFiles)

	'Set the default extension
	.DefaultExt = ".mp3"

	.ShowDialog()

End With

您可以使用 GetFilterIndex 方法(如上所示)来获取相关的 FilterIndex,您可以将其分配给 OpenFileDialog/SaveFileDialogFilterIndex 属性。

示例 #3 -- 自定义和系统过滤器

'Declarations
Dim FilterBuild As New FilterBuilder()
Dim ofd As New OpenFileDialog()

'Add the Custom filters
FilterBuild.Add("Foo Files", "foo")
FilterBuild.Add("Custom Files", "custm")
FilterBuild.Add("My Random Files", "rndm")

'System File Types
FilterBuild.Add("xml")
FilterBuild.Add("dll")
FilterBuild.Add("bat")

With ofd

        'Set the filter
        .Filter = FilterBuild.ToString()

        'Sets the filter index to the first item
        .FilterIndex = 1

        'Set the default extension
        .DefaultExt = ".foo"

        .ShowDialog()

End With

在上面的最后一个示例中,我正在添加六个文件类型,前三个是自定义的(由程序员创建),最后三个是从注册表中获取的已知文件类型。有关更多信息,请参阅本文前面的“自定义过滤器”“系统文件类型”部分。

关注点

在编写重载的 Add 方法时,我遇到了一些特别奇怪的事情。最初,我写了两个 Add 方法来接受 FilterBuilder.Filters enumParamArray 值以便于使用,但在 IDE 中测试 Add 方法时,我发现输入“.Add(”后,enum 值没有显示 Intellisense。也许 Intellisense 不会与 ParamArrays 一起显示?

我通过修改两个 Add 方法来接受 FilterBuilder.Filters 类型的 Arrays(而不是 ParamArrays)来解决了这个问题。请参阅上面的“示例”部分。

致谢

感谢 Man Vuong 和他的文章 C# 中获取注册文件类型及其关联图标 [^]。我修改了他的一些源代码并将其转换为 VB.NET,以提供系统文件类型支持。

历史

2009 年 10 月 25 日 - 版本 1.25

  • FilterBuilder.Filters enum 中添加了“WindowsIcons”和“EXIF_ImageFiles”过滤器。
  • 添加了 GetFileDescription() 方法。
  • 添加了 ReadOnly Count() 属性。
  • 添加了 GetFileDescription()GetFileExtension()GetFilterIndex() 方法的新重载,它们只接受过滤器字符串作为参数。

    支持系统文件类型

  • 添加了 GetSystemFileTypeDescription() 方法。
  • 添加了 GetSystemFileTypeIcon() 方法。
  • 添加了 GetSystemFileTypeInfo() 方法。
  • 添加了 GetSystemFileTypes() 方法。
  • 修改了 FilterGroup class 以支持新的系统文件类型(请参阅本文前面的“系统文件类型”部分)。
  • FilterBuilderFilterGroup 类中添加了“Add”方法的新重载,它只接受一个 string 参数(扩展名),并从用户的计算机获取文件描述。
  • FilterBuilder class 中添加了“Contains”和“Remove”方法的新重载,以支持新的系统文件类型。
  • 添加了 FileTypeIconSize() 属性。
  • 添加了 ImageSize enum
  • 修改了本文中的示例 #3,以包含系统文件类型示例。
  • 在附加的演示下载中添加了示例 #7。此示例演示了与系统文件类型交互时使用的方法。
  • 更改了演示下载的用户界面,以包含系统文件类型的交互式示例。立即下载新的演示版,查看更改!

2009 年 9 月 6 日 - 版本 1.10

  • FilterBuilder.Filters enum 中添加了“All Files”过滤器。
  • 更改了 Add 方法的 string 重载。它最初接受一个 string 参数(自定义过滤器 string),但感谢 Kschuler 的建议,它现在接受两个 string 参数,即文件类型的描述和扩展名。请参阅本文前面的“自定义过滤器”部分。
  • 添加了 FilterGroup 类,并修改了源代码以适应新的 FilterGroups。请参阅本文前面的“FilterGroups”部分。
  • 从下载文件中删除了“obj”文件夹。感谢 pimb2 提供此提示。

2009 年 9 月 - 版本 1.00

© . All rights reserved.