存储Windows窗体图像集的最佳方法

时间:2011-09-03 17:33:50

标签: c# .net winforms visual-c#-express-2010 system.graphics

我正在开发一个Windows窗体应用程序,我将使用多组图像(想想图标)。根据主题,必须选择不同的图像集(我稍后将使用Bitmap绘制它们。)

我在考虑将图像存储在单独的文件中(存档文件?dll?),然后在运行时从主应用程序加载它们。最有效的方法是什么?

感谢您的阅读。

3 个答案:

答案 0 :(得分:3)

我会在几个场景中回答这个问题。

  1. 此图片经常更改吗?然后转到基于目录的approcach,将其存储在目录中并加载它。也许你可以拥有一个xml来加载这些文件的名称。因此,在文件(图像)中更改名称,只需更改xml。

  2. 这些文件永远不会改变?然后只是将它们作为资源嵌入,这种方式将嵌入到你的exe / dll中,没有人可以破坏图像。

  3. 通常我见过人们没有嵌入。

答案 1 :(得分:0)

您是否考虑过使用resx文件(资源文件)?这样,您可以嵌入任何图像(图标)或任何您喜欢的图像,并决定仅加载基于您的主题所需的资源文件(资源文件可以根据您的主题名称命名)。似乎在本地化时遇到同样的问题,不是吗?但是要知道它是否是最佳方式(性能,记忆等),我无法分辨。

答案 2 :(得分:0)

不确定你是否得到了你想要的答案。以下是创建资源dll的逐步步骤

  1. 在visual studio中创建一个新项目,类库
  2. 将您的资源(图片)添加到项目中(添加现有项目)
  3. 对于每个资源,在属性窗口中,将Build Action设置为Embedded resource
  4. 编译库,生成一个dll
  5. 在winforms应用程序中,您现在可以在运行时加载此程序集(代码#1)
  6. 加载所需的资源流并将其保存到Bitmap对象(代码#2)
  7. 代码#1

    Assembly ambly = Assembly.LoadFile(pathToDll);
    

    代码#2

    BitMap bitMap;
    // where "ns" is the default namespace of the resource project    
    using (Stream resourceStream = ambly.GetManifestResourceSream("ns.image.jpg"))
    {
          bitMap = BitMap.FromStream(resourceStream);
    }
    

    这些是用于嵌入资源并在运行时加载它们的基本技术。

    现在,由于您正在考虑使用不同的主题,并将每个主题的资源存储在不同的库中,因此您应该有一个接口,指定在主应用程序中定义的某种资源管理器。

    一个例子

    interface IThemeResourceProvider
    {
         Stream LoadBigLogo();
         Stream LoadSmallLogo();
    } 
    

    然后在资源库中实现该接口

    public class ThemeResourceProvider : IThemeResourceProvider
    {
        public Stream LoadBigLogo()
        {
             Assembly ambly = Assembly.GetExecutingAssembly();
             return ambly.GetManifestResourceStream("namespace.image.jpg");
        }
    
        (...)
    }
    

    最后,不是直接在主应用程序中加载资源,而是实例化资源库中的IThemeResourceProvider

     Assembly assembly = Assembly.LoadFile(pathToDll);
    
     var results = from type in assembly.GetTypes()
                   where typeof(IThemeResourceProvider).IsAssignableFrom(type)
                   select type;
    

    现在,该列表中有IEnumerable<Type>。通常,您只有一个,但使用此方法您还可以托管多组资源,并在同一资源dll中实现多个IThemeResourceProviders。你可以,例如使用名称标识每个IThemeResourceProvider,作为属性,或在各种实现中使用自定义[Attribute]装饰。我会把剩下的留给你来弄清楚。

    但是这里是如何在列表中实例化IThemeResourceProviders

    foreach (var providerType in results)
    {
         var constructorInfo = providerType.GetConstructor(Type.EmptyTypes);
         IThemeResourceProvider provider = constructorInfo.Invoke(null);
    }
    

    最后,使用其中一个提供程序获取位图:

    BitMap bitMap;
    using (Stream resourceStream = provider.LoadBigLogo())
    {
          bitMap = BitMap.FromStream(resourceStream);
    }