Windows 窗体的胶片控件






4.73/5 (29投票s)
一篇关于 C# 设计的 Windows 窗体胶片控件的文章

目录
引言
虽然网络应用程序似乎有许多功能丰富的幻灯片控件,但用于普通 Windows Forms 应用程序的却少得可怜。我确实阅读了rahulparthe 的文章,但那并没有提供所需的功能。因此,我在这里的努力是在没有任何其他灵感的情况下从头开始开发的。
Using the Code
该控件内置在其自己的 dll (Filmstrip.dll) 中,并使用 Filmstrip
命名空间。您可以添加对已编译 dll 的引用,也可以将源文件直接复制到项目中的文件夹。代码目前设计为您可以直接复制源文件,它不需要任何额外的资源。(这意味着可显示的字符串被硬编码为常量,而不是像它们应该的那样在字符串表中。)添加引用后,确保它出现在工具箱中,然后简单地将控件拖到窗体上。
特点
Filmstrip 控件具有以下功能:
- 动态添加一张或多张图像。
- 动态删除单张图像,或清除整个控件。
- 动态清除控件中的选择。
- 随着控件大小的调整,缩略图显示会自动更新。
- 用户定义缩略图条的位置。
- 用户定义整个控件的配色方案。
- 自动滚动 - 将鼠标悬停在导航按钮上会在可配置的延迟时间后使缩略图向相应方向滚动。
- 工具提示 - 每个缩略图都显示其描述及其在集合中的索引。
- 可编辑的描述 - 双击主图像将显示一个简单的窗体,允许修改其描述。
- 完全键盘访问 - 由于每个缩略图都是一个按钮,用户可以使用
Tab
键在每个缩略图之间切换,并使用Space
键进行选择。还支持Home
、End
、PageUp
和PageDown
键。显示编辑描述窗体的加速键组合也可以自定义。 - 通过选择或选定图像的描述更改时触发的事件,提供控件活动的反馈。
- 向导航按钮添加自定义图像。
- 设计时支持。
快速入门
- 向您的项目添加对 Filmstrip.dll 的引用。
- 将
FilmstripControl
拖到窗体上。 - 在设计器中设置所需的控件属性。
- 根据需要,在窗体的 OnLoad 处理程序或其他地方添加所需的图像。(请注意,所有图像都必须与数字 ID 值关联。)示例应用程序显示了 3 种不同的方法...
// Using the AddImage overloads filmstripControl.AddImage( new FilmstripImage(Properties.Resources.Zugspitze as Image, "Zugspitze, Germany")); filmstripControl.AddImage(Properties.Resources.ChobeSunset as Image, "Sunset at Chobe National Park, Zambia"); // Or adding many images, chosen from an OpenFileDialog... if (DialogResult.OK == openFileDialog.ShowDialog()) { List<FilmstripImage> images = new List<FilmstripImage>(); foreach (String file in openFileDialog.FileNames) { Image thisImage = Image.FromFile(file); FilmstripImage newImageObject = new FilmstripImage(thisImage, file); images.Add(newImageObject); } filmstripControl.AddImageRange(images.ToArray()); }
- 通过使用事件处理程序和适当的属性,实现使用 Filmstrip 控件中选定图像所需的任何特定功能。
- 呃.....就这些。
公共属性
Filmstrip 控件有许多公共属性。这些属性可以分为两个方面:视觉和功能。
视觉属性用于修改/自定义控件的视觉外观和感觉。可以更改整个控件的背景颜色(以及选定高光的颜色),用自定义图像替换左右导航按钮,以及指定缩略图条显示的位置等等。
属性 | 只读? | 描述 |
ControlBackground |
否 | 指定幻灯片控件上所有项目的背景颜色。默认值为“Control”。 |
EditDescriptionAccelerator |
否 | 设置用于显示当前选定图像的编辑描述窗体的加速键组合。默认值为 Ctrl+D。 |
ImageNavLeft |
否 | 指定用于左导航按钮的图像。如果未指定图像,则按钮文本将为“<”。 |
ImageNavLeftLayout |
否 | 如果存在图像,则指定用于左导航按钮图像的图像布局。默认值为“Stretch”。 |
ImageNavRight |
否 | 指定用于右导航按钮的图像。如果未指定图像,则按钮文本将为“>”。 |
ImageNavRightLayout |
否 | 如果存在图像,则指定用于右导航按钮图像的图像布局。默认值为“Stretch”。 |
MainImageLayout |
否 | 指定主显示区域中选定图像的图像布局。默认值为“Center”。 |
ScrollHoverDelay |
否 | 指定鼠标悬停在导航按钮上时,在滚动缩略图视图之前使用的延迟间隔(以毫秒为单位)。默认值为 500 毫秒。 |
SelectedHighlight |
否 | 指定所选缩略图图像周围高光的颜色。默认值为“DarkBlue”。 |
ThumbsStripLocation |
否 | 指定缩略图条的位置,可以是“Top”或“Bottom”。默认值为“Bottom”。 |
功能属性与控件使用的数据有关。
属性 | 只读? | 描述 |
ImagesCollection |
否 | 图像集合。设置此属性将删除当前集合中的所有图像。 |
SelectedImage |
是 | 控件中当前选定的图像。 |
SelectedImageDescription |
否 | 控件中当前选定图像的描述。 |
SelectedImageID |
否 | 指定控件中当前选定图像的图像 ID。 |
公共方法
该控件只有几个公共方法。这些方法被保持在最小限度,以保持简单和易用。
AddImage |
此方法向控件添加单个图像。新图像添加到控件内部集合的末尾。(3 个重载。) |
AddImageRange |
此方法向控件添加多个图像。新图像添加到控件内部集合的末尾。 |
ClearAllImages |
此方法从控件中删除所有图像。 |
ClearSelection |
此方法从控件中删除任何选择,以便没有图像被选中。 |
EnsureThumbIsVisible |
此方法确保指定图像的缩略图在缩略图条中可见。它不影响当前选择。 |
RemoveImage |
此方法从控件中删除指定的图像。 |
注意:目前,AddImage
(所有重载)、AddImageRange
和 RemoveImage
都会导致整个缩略图列表重新填充,这会引起轻微的闪烁。建议在控件首次显示之后(即不在 OnLoad 处理程序中)添加许多图像时,使用 AddImageRange
方法,因为这只会导致缩略图列表重新填充一次。
公共事件
控件触发 2 个不同的事件。
SelectionChanged |
当控件中选定的图像发生变化时,会触发此事件。 |
SelectedImageDescriptionChanged |
当控件中选定图像的描述发生变化时,会触发此事件。 |
控件内部结构
Filmstrip.dll 程序集包含以下公共“对象”:
FilmstripControl |
实际的幻灯片控件。 |
FilmstripControl.StripLocation |
一个简单的枚举,用于指定缩略图条在控件上的位置。它目前只有“Top”和“Bottom”两个值。 |
FilmstripImage |
一个简单的类,用于封装控件内部的图像。 |
控件架构
添加到控件的每个图像都作为 FilmstripImage
对象存储在标准 Dictionary
中。每个 FilmstripImage
都有自己的 ID - 这是必需的,并且是一个整数。如果未指定图像 ID,则在 AddImage
调用期间生成一个 ID 并返回给调用方。图像 ID 的唯一无效值是 -1:这由静态类成员 NO_SELECTION_ID
指定。
开发该控件最具挑战性的方面是确保缩略图集合的构建、填充和正确渲染,尤其是在调整控件大小时。
缩略图条是根据控件集合中的图像数量和控件的当前大小动态创建的。整个缩略图条,包括导航按钮,都包含在一个面板上,这样它就可以移动到控件上的所需位置。在缩略图条本身上,缩略图位于另一个面板上,该面板夹在两个导航按钮之间。导航按钮具有固定的大小和位置——即它们相对于控件的侧面保持其位置。通过这种方式,包含缩略图的面板随控件增长或缩小。该控件维护一个当前使用的所有缩略图按钮对象的集合——thumbnailControls
成员。

鉴于每个缩略图面板和按钮都是固定大小的,因此可以计算出在任何给定时间可以放入父面板的缩略图数量。无论何时控件宽度改变,它都会检查是否正在显示可能的最大缩略图数量,然后根据需要添加或删除缩略图。在这两种情况下,我们都必须考虑到托管窗体的窗口可能已被最大化或“未最大化”,因此我们可能需要一次添加或删除多个缩略图。所有这些都在 AdjustThumbnails
函数中完成。因此,当控件变大时
// Did we get bigger, and we have't yet created thumbs for all the images we have?
while ((thumbnailControls.Count < ThumbsForWidth())
&& (thumbnailControls.Count < imagesCollection.Count))
{
// Get the image id of the current last one
int imageIDOfLast = -1;
if (thumbnailControls.Count > 0)
{
imageIDOfLast =
Convert.ToInt32(thumbnailControls[thumbnailControls.Count - 1].Tag.ToString());
}
// Add a new one
int newIndex = PushThumbnail();
// If we're already at the right hand end, we need to shift all the images across
// (as if the left navigation button was clicked)
if ((imageIDOfLast > -1) && (keys[keys.Count - 1] == imageIDOfLast))
{
MoveThumbnailsLeft();
}
else
{
// Set the image on this new thumb
PopulateThumbnail(newIndex);
}
}
但幸运的是,当控制变小时,代码要简单得多
while (thumbnailControls.Count > ThumbsForWidth())
{
PopThumbnail();
}
示例应用程序

提供的示例应用程序演示了如何轻松地将 Filmstrip 控件集成到窗体中。它提供了以下功能:
- 如何添加图像(加载时和加载后动态添加)。
- 如何删除图像。
- 如何清除控件。
- 它允许动态更改许多(但不是所有)视觉属性。
- 它仅使用控件提供的信息显示控件中当前选定图像的详细信息。
- 如何设置控件选择。
- 如何更新选定图像的描述。
示例应用程序中有几点需要注意:
- 默认图像内置在示例应用程序中,其初始描述是硬编码的。
- 图像 ID 有一个内部计数器。它从 1 开始,每添加一个新图像就会递增。
- 使用“添加...”按钮添加新图像时。完整文件名将设置为每个图像的描述。
- 该应用程序使用第三方控件用于颜色选择器组合框。该控件位于 OfficePickers.dll 程序集中,其详细信息可在文章中找到:Office 2003 颜色选择器。
技术说明
所有代码均使用 Visual Studio 2005 Professional 和 Express 版本在 Windows XP (Home & Professional) 上开发。由于我无法访问其他版本的 Visual Studio、.Net 框架或其他操作系统,因此尚未对其进行全面测试。(尽管在 Windows 2000 和 Windows 2003 Server 上对早期版本进行了有限的测试。)
修订历史
- 2008 年 6 月 17 日 - v.1.0 - 首次公开发布。
- 2008 年 6 月 18 日 - v.1.1
- 内部命名空间使用更正。
- 添加了工具箱图像。
- 公共事件命名略有更改(删除了开头的“On”)。
- 添加了设计时支持。
- 使
EnsureThumbIsVisible
方法公开。
- 2008 年 6 月 27 日 - v.1.2
- 一些代码重组和重构。
- 添加了对
Home
、End
、PageUp
和PageDown
键的键盘处理。 SelectedImageDescription
属性现在可写。- 修改了图像 ID 的使用。现在可以在添加图像时省略它们,并且内部会分配一个图像 ID。因此,创建了一个新的
AddImage
重载,以及FilmstripImage
类的新重载构造函数。此外,所有AddImage
方法现在都返回所添加图像的图像 ID。如果需要,图像 ID 现在可以是负数。唯一无效的值是 -1,由静态成员NO_SELECTION_ID
指定。