昨天突发奇想,向写一个类似于MSN 的自定义个性化窗体,今天在实践的过程中,发现在实现资源文件时就遇到了困难。

在网上找了不少的资料,将怎么添加资源文件的很多,比如这个 http://blog.csdn.net/lizanhong/archive/2004/09/10/100812.aspx
就不错,而且其中也注解了:
  注意:ResourceManager rm = new ResourceManager ( " Res.My " , Assembly.GetExecutingAssembly ( ) ) ;语句中,构造函数的第一个参数Res.My 由两部分构成,Res表示测试工程的命名空间,My表示资源文件名My.resources的根名称,即点号有前部分My

然而自己在实践过程中,还是对baseName 的理解发生一个错误。由于自己使用C#写程序的,刚开始认为添加资源文件很简单,就直接用ResourceManager区读取.resouce文件使用,但是失败了。


//private const System.String RESOURCE_BASE_NAME = "Component.Popup";
this.ResourceDirectory = @"E:/projects/Popup/src/Resources";
 System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-cn");
this.resMng = System.Resources.ResourceManager.CreateFileBasedResourceManager(RESOURCE_BASE_NAME, this.ResourceDirectory, typeof(PopupCtl));

随后又换成ResourceWriter 来自己写.resource 文件,调用还是出现了问题。

this.ResourceDirectory = @"E:/projects/Popup/src/Resources";
 System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("zh-cn");
this.CreateResource();

this.resMng = new System.Resources.ResourceManager("Component.Popup.Resources", System.Reflection.Assembly.GetExecutingAssembly());
Image img = (System.Drawing.Image)this.resMng.GetObject("btn_close") //这句报错,说是找不到btn_close

private void CreateResource()
 {

     System.Resources.ResourceWriter rw = new System.Resources.ResourceWriter(RESOURCE_FILE_NAME);

     Image img = Image.FromFile(@"E:/projects/Work/UpdateUI/Test/Component/btn_close.gif");
      rw.AddResource("btn_close", img);

     rw.Generate();
      rw.Close();
}

不知道自己是在那里错误了,找了1个小时的网上资料也没有结果。刚好电视在放《唐伯虎点秋香》,哈哈,又看到了“刚出炉的孝子大拍卖”,“美女”,“这是你们逼我的——龟波气功”。哈哈,经典就是经典。

看完了电视再来看看程序,无聊的翻看着程序所在的目录发现在obj/Debug目录下有这个一个文件Component.Popup.Properties.Resources.resouce

看着这个文件怎么这么熟悉,好像是资源文件,而且文件名中多了一个properties ,这个不是vs2005中的属性目录吗? 难道说是程序自动把资源文件所在目录也加入到了名称中?

返回程序,修改了baseName 的字符串为 Component.Popup.Properties.Resources ,运行程序,一切ok。

晕,怎么会这样?到底是怎么回事?马上上Microsfot查找,找到了这片文章:

http://www.microsoft.com/china/community/program/originalarticles/techdoc/how_resourcefile.mspx

其中有这么一段:

如何准确的定义资源文件的逻辑位置
我想这是许多人最关注的一段了!在这里作者将解说如何正确的填写 ResouceManager(String, Assembly) 这个 constructor,还有如何正确的填写 Assembly.GetManifestResourceStream(String),因为它们两个的原理是相同的。看过了上面的描述,到了这里就简单多了。这里主要讨论的是怎么填写那个 String。这个 String 就是资源的完整名,一个完整名由它的名字空间和文件名前部分(BaseName)组成。例如,如果默认名字空间(root namespace)是 DefaultNamespace,资源文件的名字是 Strings.en-US.resources,那么它的完整名就是 DefaultNamespace.Strings。这个很简单,不过怎样确定名字空间呢?这就有些奇怪了,因为 C# 的编译器与 VB.NET 的编译器有些不同。作者在这里分别给出两个编译器怎样给嵌入资源自动添加命名空间:
C#
它自动添加 default namespace(与 root namespace 相同),但也添加子文件夹的名字。例如,在 Subfolder 子文件夹下放的资源文件 Strings.en-US.resources,它的完整名是 default namespace + subfolder + base name = DefaultNamespace.Subfolder.Strings
VB.NET
在 VB.NET 中就很简单了,它自动给嵌入资源添加 root namespace。不管你在哪个子文件夹中放置资源文件,资源文件的完整名永远是 root namespace + base name。
根据上面的描述,如果我们使用 C#,用 VS.NET 在 NewFolder 这个子文件夹中添加了一个叫 Images.resources 的资源文件,那么我们应该用以下代码获取这些资源,假设 default namespace 是 MyDefault:
ResourceManager res = new ResourceManager("MyDefault.NewFolder.Images", this.GetType().Assembly);
但如果我们用 VB.NET 的话,就应该这样:
Dim res As New ResourceManager("MyDefault.Images", Me.GetType().Assembly)


看完上面的解释才发现自己的正确性,再更改CreateResource,运行,ok。一路绿灯。哈哈,成功了。

总结一下:

1、不要眼高手低。虽然看到资源文件很简单,大体上你可能知道,但是不妨动手试一下,也许你遇到一个强有力的对手的;

2、对于困难的问题可以适当休息后再解决;

3、《唐伯虎点秋香》经典还是经典。

Image img = (System.Drawing.Image)this.resMng.GetObject("btn_close") //这句报错,说是找不到btn_close
posted on 2007-05-20 00:34  孤剑  阅读(301)  评论(0编辑  收藏  举报