• 关于资源文件


    现实生活中某些exe或者dll文件需要依赖其它文件得以正常运行,此时如果把该文件直接拷贝到客户端,然后程序内部用相对路径读取不一定是很好的方案(因为一旦客户删除了这些资源,程序可能出现不可预见的效果)。所以这些文件必须被嵌入exe或者dll中,和发布程序融合为一体。这时,“资源文件”往往是我们的首选。

    在.NET(C#或者VB.NET)中,我们可以使用两种大的方案创建资源文件:

    1)直接创建拷贝一个普通的文件到项目中,设定其BuildAction为"Embeded Resource"即可;此时,当编译整个工程的时候,该文件被当成一种特殊的“资源文件”(本质上是编译器解析成二进制代码,因为所有文件都可以被视为二进制代码进行读入、写入,计算机内部CPU也是只认得二进制代码的)和exe混合在一起,存放在特殊的区域中。

    要读取此类资源文件,方法是使用Assembly.GetManifestResourceStream。注意该方法有两个版本的重载函数:

    i)第一个重载函数只需要一个string(是当前工程的Namespace.[文件夹名1.……文件夹名N].被嵌入的文件名称.扩展名)。

    ii)第二个重载函数需要一个当前可执行程序的类type(接受这个参数,类似获取第i中方法的项目Namespace;后面的string就是.[文件夹名1.……文件夹名N].文件名称.扩展名)。

    【例子】

    假设我的项目如下(其中Desert.jpg已经设置为Embeded Resource,项目的Namespace和项目自身同名,为WinFormCSharp),现在要求读取并且作为Form1图片背景显示。

    思路分析:

    因为Desert.jpg在Resources文件夹中,因此直接这样写:

    [C#]

    Assembly asm = Assembly.GetExecutingAssembly();  //获取当前正在运行的Assembly
    this.BackgroundImage = Image.FromStream(asm.GetManifestResourceStream("WinFormCSharp.Resources.Desert.jpg"));
    //你也可以: 
    this.BackgroundImage = Image.FromStream(asm.GetManifestResourceStream(typeof(Form1),"Resources.Desert.jpg"));

    [VB.NET]

    Dim asm As Assembly = Assembly.GetExecutingAssembly()
    '获取当前正在运行的Assembly
    Me.BackgroundImage = Image.FromStream(asm.GetManifestResourceStream("WinFormCSharp.Resources.Desert.jpg")
    '你也可以: 
    Me.BackgroundImage = Image.FromStream(asm.GetManifestResourceStream(GetType(Form1),"Resources.Desert.jpg"))

    注意1:为确保Namespace的准确性(考虑某些项目名称和实际的Namespace不吻合),获取当前运行的项目程序Namespace的方法是
    [C#]

    string s = asm.GetName().Name;

    [VB.NET]

    Dim s As String = asm.GetName().Name

    然后使用s和示例程序进行拼接即可。

    注意2:你也可以使用GetManifestResourceNames()检查所有嵌入项目中的资源,进一步判断需要取舍哪(个、些)资源。返回结果是string数组

    [C#]

     foreach (var item in asm.GetManifestResourceNames())
    {
    MessageBox.Show(item.ToString());
    }

    [VB.NET]

    For Each item In asm.GetManifestResourceNames()
    MessageBox.Show(item.ToString())
    Next

    2)使用Resource.resx文件。默认在Properties文件夹下边就有这样一个和项目同时生成的资源文件。当然你可以通过右键点击项目,然后在弹出的“添加新项……”对话框中人为添加一个资源——注意!此时的资源仅仅是被添加到了资源文件中,并不是到exe或者dll自身,只有在编译之后才会进入exe或者dll中。
    如果我们细心的话,还会发现这种方式添加资源文件,其中有个属性“Persistance”有两个选择:

    i)Link when compiling(编译时链接)。

    ii)直接嵌入resx文件。

    有何区别呢?

    第i种情况:编译时,先根据Resources.resx(本身是一个xml文件)读取该资源的相对路径,然后根据该路径找到对应的文件(应该默认是会自动生成Resources文件夹,其中存放了若干资源文件),然后把它们转化成二进制形式,被一同编译进入了exe中。这就意味着如果另外一个项目要使用这个Resource文件,因为Resource中只存储了一个相对地址(你不把这个相对地址指向的资源文件(文件夹)拷贝过来,仅是拷贝一个资源文件,在编译的时候因为无法找到真正对应的图片,可能导致编译错误)。

    至于第ii种,直接把资源文件转化为二进制代码流嵌入到exe和Resources中。因为Resource中直接嵌入了图片元数据,因此无需真正图片了,以后如果要资源复用,只要拷贝这个Resource文件加入其它项目,然后编译引用即可

    那么如何读取Resources.resx中的资源文件呢?用第一种办法是不行的,我们要借助ResourceManager这个类:这个类构造函数有两个版本的重载:

    i)需要一个type(注意:指定的是Resources.resx这个资源文件自动生成的类,Resources.designer.cs)。

    ii)需要一个string(注意:指定的是项目的Namespace根名称.[文件夹名1.……文件夹名N].Resouce文件名称,当前Assembly)。

    【例子2】

    已知创建了一个项目,其中架构图如下:

    现在要求读取Resource文件中嵌入的图片文件(假设是Desert.jpg,Embeded in resx形式)。

    [C#]

    ResourceManager rm = new ResourceManager(typeof(Resources.Resources));
    //也可以:
    //ResourceManager rm = new ResourceManager("WinFormCSharp.Resources.Resources",Assembly.GetExecutingAssembly());
    BackgroundImage = (Bitmap)rm.GetObject("Desert");

    [VB.NET]

    Dim rm As New ResourceManager(GetType(Resources.Resources))
    '也可以:
    '
    ResourceManager rm = new ResourceManager("WinFormCSharp.Resources.Resources",Assembly.GetExecutingAssembly());
    BackgroundImage = DirectCast(rm.GetObject("Desert"), Bitmap)

    另外,更为简化的方式是使用ComponentResourceManager,只需指定一个Resouce文件的类名即可:

    [C#]

    ComponentResourceManager rm = new ComponentResourceManager(typeof(Resources.Resources));
    BackgroundImage = (Bitmap)rm.GetObject("Desert");

    [VB.NET]

    Dim rm As New ComponentResourceManager(GetType(Resources.Resources))
    BackgroundImage = DirectCast(rm.GetObject("Desert"), Bitmap)

    或许你会说——哎呀!那么多类命名空间什么的,头都大了——没有关系,其实我之所以先说这些内容,主要是让我们对Resouces有一个清楚的了解。微软早已经考虑这点了!因此最最简便的方法在于——直接

    WinFormCSharp.Resources.Resources.此处会智能感知出Resources中包含的全部资源文件,是强类型的哦!
  • 相关阅读:
    选择器
    【兼容】text
    SQL2008的数据更新跟踪测试
    拖拽文件到RichEdit的后期处理
    Web Browser 的扩展
    URL Protocol Handler
    asterisk1.6异步脚本
    CSDNER如何才能做到"最不缺的是技术"
    关于SQL语句Count的一点细节
    TG787 脚本
  • 原文地址:https://www.cnblogs.com/ServiceboyNew/p/2372979.html
Copyright © 2020-2023  润新知