嵌入式图像提取器:.NET程序中的图像资源提取工具

在.NET程序开发中,经常需要将图像、图标和光标等资源嵌入到程序的汇编文件中。这样做的好处包括简化部署(减少需要管理的文件数量)、简化资源消耗(运行时文件不会丢失)等。本文将介绍一个名为“嵌入式图像提取器”的工具,它允许用户方便地查看、保存和复制嵌入在.NET程序中的图像资源。

在深入了解嵌入式图像提取器的工作方式之前,先来回顾一下什么是嵌入式资源。当创建一个程序的汇编文件时,可以在其中存储任意文件,比如BMP图像、XML文件等,这些文件被称为嵌入式资源。将资源嵌入到汇编文件中有几个好处,比如简化部署和资源消耗。

在Visual Studio.NET中,可以通过以下步骤轻松地将图像嵌入到程序的汇编文件中:

  1. 将图像文件添加到项目中。
  2. 在解决方案资源管理器中,右键点击图像文件,然后选择“属性”。
  3. 在属性窗口中,将“构建操作”属性设置为“嵌入式资源”。
  4. 编译项目,将其编译成汇编文件。

.NET框架为程序化检索嵌入式资源提供了支持。本文稍后将探讨这一功能的实现方式。

使用工具

使用嵌入式图像提取器工具需要四个基本步骤:

  1. 运行“Embedded Image Grabber.exe”。
  2. 点击“打开”按钮,定位包含想要提取的图像的汇编文件。
  3. 通过窗口顶部的“BindingNavigator”导航到感兴趣的图像。
  4. 点击“保存”或“复制”按钮,将图像保存到磁盘或剪贴板。

提示:步骤1和2可以通过将目标汇编文件拖放到“Embedded Image Grabber.exe”上来合并。

  • 保存选项:在保存嵌入式图标或光标时,可以选择将其保存为原始文件类型或位图。“另存为”对话框将默认使用与嵌入式资源原始类型对应的扩展名。
  • 通过拖放打开:除了可以通过将汇编文件拖放到“Embedded Image Grabber.exe”上来打开应用程序外,还可以在应用程序运行时通过拖放加载汇编文件。只需将汇编文件拖放到表单上,它包含的嵌入式图像就会被加载。
  • “所有图像”标签:提供了程序中每个图像的网格视图,使搜索图像变得更快。
  • 属性视图:一个“PropertyGrid”,显示当前图像的详细信息。点击工具栏上最右边的按钮来显示/隐藏这个视图。
  • 上下文菜单:提供快速访问保存、复制或显示/隐藏图像属性的选项。
  • 查看选项:当选择“单个图像”标签时,工具栏会有一个组合框,允许更改当前图像的渲染方式(例如放大、居中等)。

工作原理

负责从汇编文件中提取图像并在用户界面中显示的主要方法是LoadImagesFromAssembly。

private void LoadImagesFromAssembly(string assemblyPath) { // 尝试加载指定位置的汇编。 Assembly assembly = this.LoadAssembly(assemblyPath, true); if (assembly == null) return; this.currentAssembly = assembly; // 如果有正在显示的图像,释放它们。 if (this.bindingSource.DataSource != null) foreach (ImageInfo imgInfo in this.bindingSource.DataSource as List) imgInfo.Dispose(); // 绑定到汇编中嵌入的每个图像的列表。 this.bindingSource.DataSource = this.ExtractImagesFromAssembly(this.currentAssembly); }

如上方法所示,ImageGrabberForm使用BindingSource组件来协调数据绑定。BindingNavigator、DataGridView、PropertyGrid和PictureBox都绑定到绑定源,这使得GUI的同步图像导航功能非常容易实现。

private List ExtractImagesFromAssembly(Assembly assembly) { List imageInfos = new List(); foreach (string name in assembly.GetManifestResourceNames()) { using (Stream stream = assembly.GetManifestResourceStream(name)) { // 将资源视为图标。 try { Icon icon = new Icon(stream); imageInfos.Add(new ImageInfo(icon, name)); continue; } catch (ArgumentException) { stream.Position = 0; } // 将资源视为光标。 try { Cursor cursor = new Cursor(stream); imageInfos.Add(new ImageInfo(cursor, name)); continue; } catch (ArgumentException) { stream.Position = 0; } // 将资源视为图像。 try { Image image = Image.FromStream(stream); // 如果图像是动画GIF,则不要将其添加到集合中,因为Image类无法处理它们,并且在显示图像时会抛出异常。 FrameDimension frameDim = new FrameDimension(image.FrameDimensionsList[0]); bool isAnimatedGif = image.GetFrameCount(frameDim) > 1; if (!isAnimatedGif) imageInfos.Add(new ImageInfo(image, name)); else image.Dispose(); continue; } catch (ArgumentException) { stream.Position = 0; } // 将资源视为资源文件。 try { // 流中的嵌入式资源不是图像,所以通过ResourceReader读取它并从中提取值。 using (IResourceReader reader = new ResourceReader(stream)) { foreach (DictionaryEntry entry in reader) { if (entry.Value is Icon) { imageInfos.Add(new ImageInfo(entry.Value, name)); } else if (entry.Value is Image) { imageInfos.Add(new ImageInfo(entry.Value, name)); } else if (entry.Value is ImageListStreamer) { // 使用ImageListStreamer加载ImageList,并存储它包含的每个图像的引用。 using (ImageList imageList = new ImageList()) { imageList.ImageStream = entry.Value as ImageListStreamer; foreach (Image image in imageList.Images) imageInfos.Add(new ImageInfo(image, name)); } } } } } catch (Exception) { } } } return imageInfos; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485