在开发项目时,常常会在添加中添加各种各样的资源,比如图片文件、图标文件、光标文件等。在这些文件被添加到当前项目中后,它们会被放到项目中的 Resources 目录下,通过适当的方法,我们就可以在程序中访问这些文件,本文旨在介绍如何访问这些资源。
在说明如何调用这些资源之前,需要先阐明一个问题,就是为什么要将这些文件添加到项目的资源中呢?因为只要把所需要的文件复到在项目的生成目录下,我在程序中直接调用这些文件也可以达到同样的效果。
这样做肯定是有它的好处的,第一,它可以防止不必要的异常或者防止资源被别人修改。假如现在有一程序,其主界面的背景是一张很漂亮的风景图片,而它正是通过 Image.FromFile("这张图片的相对路径") 来获取的,那么,如果用户不小心或者故意将这张图片从硬盘中删掉。很明显,这样就会引发 FileNotFoundException;另外一种情况,假如用户没有删除,而是将其换成另外一张图片,那么他的操作等于变相地修改了您的程序。
而将这些文件添加到项目中,则会被编译到项目的输出文件中( exe文件 或 dll文件),这样就完全杜绝了上述隐患。
第二个好处是,它可以减少程序的 IO 的访问。在文件被编译进程序的情况下,在程序启动时,这些资料就会同时被载入到内存中,这样,就减少了对 IO 的操作。
好了,言归正传。如果访问项目资源呢?首先说明,我把项目资源分为两类:项目内资源与项目外资源。所谓项目内资源就是资源被编译在本项目中并且也在本项目中被访问;而项目外资源则是指资源被编译在一个项目中,却在其它项目中被访问。
访问项目内资源
在 VB.NET 中访问项目内资源是十分方便的,这是因为有 My 命名空间的存在。使用 My.Resources.资源名 即可访问,如:
'b_71FE6A8F3E197492是一张图片文件的资源名称
Me.BackgroundImage = My.Resources.b_71FE6A8F3E197492
访问项目外资源
为了减少项目输出文件的体积,可以将资源文件与代码独立出来,即,将项目使用的资源文件编译到另外一个项目。这里假设有以下四种类型的资源文件:文件文件(Txt)、图标文件、图片文件、Audio 文件(Wav)。
首先建立一个类库项目(命名为 MyFiles),把这四个文件添加进来。方法:右击“解决方案管理器”中项目的名称,选择“属性”,之后在“资源”选项卡,把这四个文件分别添加进来,之后编译。这时需要记下这个项目的“根命名空间”(在“应用程序选项卡”上):
打开生成目录(bin 下的 Debug 或 Release),找到生成后的文件 MyFiles.dll 。
再建立一个 Window 应用程序项目。打开“项目”菜单,选择“添加现有文件”,找到刚才的 MyFiles.dll,将它添加到新的项目中。这时,在右侧的“解决方案管理器”中,找到它,在其属性窗口中,将“复制到输出目录”属性设置为“总是复制”。在默认窗体 Form1 的代码中添加代码:
Imports System.Resources
Imports System.Reflection
Public Class Form1
Dim fileDllPath As String = String.Format("{0}\MyFiles.dll", Application.StartupPath)
Dim ass As Assembly = Assembly.LoadFrom(fileDllPath)
Dim rm As New ResourceManager("NBWD.MyFiles.Resources", ass)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'文本文件
Me.TextBox1.Text = rm.GetString("天蝎座")
'图片文件
Me.PictureBox1.Image = CType(rm.GetObject("b_71FE6A8F3E197492"), Image)
'图标文件
Me.Icon = CType(rm.GetObject("Icon_131"), System.Drawing.Icon)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Audio WAV 文件,点击该按钮可播放 WAV 资源文件
My.Computer.Audio.Play(rm.GetStream("oppo"), AudioPlayMode.BackgroundLoop)
End Sub
End Class
程序运行,结果如下:
对上述代码需要说明以下几点:
1.由于先前生成的项目资源文件实质上是一个程序集,所以在访问时,需要知道它的命名空间,并且需要使用 Assembly 类的 LoadFrom 方法将其载入。
2. ResourceManager 对象负责进行资源访问,它接收两个参数,第一个参数是资源的命名路径,即“项目的根命名空间.Resources”;第二个参数是一个程序集,即这些资源是从哪个程序集中调用。
3. 通过ResourceManager 对象的各种以 Get 开头的方法就可以访问相关类型的资源,如 GetObject、GetSring 、GetStream 等。它们都接收一个字符串参数,就是该资源的名称。