分享
 
 
 

托管资源全攻略

王朝vc·作者佚名  2006-05-23
窄屏简体版  字體: |||超大  

托管资源全攻略

作者:caeser2

下载源代码

本文内容适用于所有使用.net v1.1及以上框架的语言。

前传1:提出问题(急于了解正式内容的读者请转到下面的正传部分^_^)

前段时间写了一篇题为“VC.NET轻松实现按钮控件自绘”的文章,其中按钮按下时的效果是由一张图片呈现的。这时问题就来了,最初我将该图片加入资源列表(.rc)中,然后使用下面的2个读取资源的方法;编译通过,可执行时程序抛出异常,提示找不到资源文件。

//方法1,从指定的hinstance中名为bitmapName的资源创建Bitmap对象

public: static Bitmap* System::Drawing::Bitmap::FromResource(IntPtr hinstance,String* bitmapName);

//方法2,使用构造函数从指定的type类中提取的resource资源初始化Bitmap对象

public: System::Drawing::Bitmap::Bitmap(Type* type,String* resource);

前传2:分析问题 接着我就犯难了,在论坛上提出该问题,没有得到建设性的回答,为了赶时间只好匆匆将图片和程序放在一起发布了。事后回想一下心里挺不是滋味,将分离的资源文件和程序文件一起发布,搞的目录里乱七八糟很不好看,为什么加入资源的图片不能用呢?会不会是资源没有打包进.exe文件呢?于是我用2进制查看工具打开资源图片和.exe文件,做了下对比,结果发现资源图片已打包进.exe文件:

资源虽已打包进.exe文件,可是除了上面提到的那两个方法,似乎再没有其它读取内部资源的函数了,那怎么办呢?

前传3:看到解决问题的曙光

打开MSDN,查找有关"资源"的索引,看了半天,最后终于弄明白了,原来.net框架对通过资源编辑器(.rc)打包进程序的资源不再提供支持,而改用一种名为"托管资源"的资源。那么这种资源与普通的非托管资源有何异同?既然不能使用Visual Stdio 200x提供的资源编辑器(.rc)打包资源,这种资源又该怎么打包进程序?打包成功后又应该怎样去使用呢?

正传1:什么是托管资源

资源可以理解为是在逻辑上由应用程序部署的任何非可执行数据,托管资源其本质也大抵如此。那么mfc使用的rc资源和.net使用的托管资源有什么区别呢?请看下表:

资源类型

Windows支持度(注1)

索引方式

可否打包"对象"

独立于.exe打包的难易度

资源的部署

其它

.rc资源

95/98/me/nt/2000及以上

依靠资源ID找到资源

不可以

使用纯资源DLL,比较麻烦

由程序员决定,管理混乱

还没想好:)

.net托管资源

目前还没有支持的

取消资源ID,改为依靠资源名,也可以依靠资源的值(内容)

可序列化的就可以

使用专用的资源文件,很简单

由程序集统一管理(注2)

注1:比如说,对一个文件夹右键选"属性"->"自定义"->"更改图标",在"浏览"中选择.exe文件,如果被系统支持则会读出.exe中打包的所有图标,反之只能读出1个;

注2:

有关程序集的讨论超出了本文的范围,感兴趣的读者可以参考MSDN;

从上表可以看出,虽然托管资源的本质概念和以往的"资源"没有区别,但是使用方式却被彻底颠覆了。托管资源将一个资源视为一个对象,对资源的查找引用不再使用资源ID,改为资源名,就像使用一个对象一样;反过来给可序列化的任意对象起个好记的名字就可以当作资源保存起来。.net托管资源的打包方式有两种,分别是打包进程序的资源和独立的资源文件。独立资源文件的组织方式也有两种形式,一种是扩展名为resX的xml文件,其内部是用xml文本方式组织的;另一种是扩展名为resources的2进制文件,其内部是以2进制方式组织的。

.net资源文件类型

扩展名

文件的组织方式

文件体积

资源的保存形式

其它

xml文件

.resX

由xml标签构成的文本文件

文本构成的,体积当然很大啦

文本资源不变,其它对象用Base64算法翻译成文本

在写.net窗体程序时VS使用.resX文件保存资源,编译时一边将resX中的资源打包进.exe文件,一边生成.resources文件

resources文件

.resources

由2进制数据构成的2进制文件

相对于同样内容的xml文件,体积要小很多

文本资源转换为2进制数据,其它对象不变

正传2:对托管资源的操作

下面的几个System::Resources命名空间中的操作类基本可以满足所有的资源操作:

资源的打包方式

操作类

功能

独立于.exe的文件

资源文件类型

xml文件

ResXResourceSet()

直接索引或枚举XML 资源 (.resx) 文件或流中的资源

ResXResourceReader()

枚举 XML 资源 (.resx) 文件或流中的资源

ResXResourceWriter()

将资源写入.resx文件或输出流

resources文件

ResourceSet()

直接索引或枚举 .resources 文件和流或流中的资源

ResourceReader()

枚举 .resources 文件和流或流中的资源

ResourceWriter()

将资源写入.resources文件或输出流

包含在.exe文件中

ResourceManager()

按名称直接访问文件内特定区域的资源,只能索引

正传3:实战

假设我们有一个窗体叫做form1.h,那么他的资源文件就是form1.resX,那么我们是不是通过修改这个.resX文件,就能实现资源打包进程序呢?simple1中描述的就是这个例子,设计思想如下,具体内容请下载全部代码文件,那里有详细的说明,注意我均使用文件操作方式,读者可以自己试验一下流操作方式:

操作

设计思想

备注

生成

将生成资源打包进程序

必须操作窗体的资源文件(比如form1.resX)。先用ResXResourceReader("form1.resX")读入,再用ResXResourceWriter("form1.resX")打开同一个文件,用AddResource()将读入的资源输出,然后将自己的资源加上,最后用Generate()覆盖form1.resX

1>如果添加资源的操作是在程序编译后做的,则需要重新编译一下!

2>一定要在窗口布局彻底完成后再做该操作,否则编译器会在每次窗口布局后自动清理窗体自身的资源文件!

生成独立的资源文件

直接用ResourceWriter()/ResXResourceWriter()构造函数创建一个资源文件,然后AddResource(),最后Generate()生成

这种情况建议生成体积较小的.resources文件

关于打包自定义资源

如果是对象则需要序列化,如果是某种文件则做成Byte[]数组的形式比较好

不要打包体积太大的媒体流文件喔:)

使用

使用本进程本窗体(form1)的资源

ResourceManager * resources = new ResourceManager(__typeof(My::Form1));

resources->GetObject("资源名");

直接用资源名索引到资源,但不可以枚举!

使用本进程其它窗体(form2)的资源

ResourceManager * resources = new ResourceManager(__typeof(My::Form2));

resources->GetObject("资源名");

同上

使用外部资源

ResXResourceReader* s1 = new ResXResourceReader("External.resX");然后枚举或

ResXResourceSet *s2=new ResXResourceSet("External.resX");

然后直接索引

s2-GetObject("资源名");

对于.resources文件思想一样

关于使用自定义资源

如果是对象则反序列化即可,如果是其它格式则需要自己去解析了

对于其它格式,建议打包时做成Byte[]数组比较好

为了给大家一个使用托管资源的映像,我将simple1的程序稍微改动了一下,将已经打好包的demo1.exe拿给大家,效果如下:

外传:应用simple2是一个具有商业价值的托管资源生成工具,不过偶也不是那种小气的人,于是就将其中的核心部分拿过来开源了^_^,使用它可以很方便的生成托管资源,而这种资源又可以给ASP.net、VB.net、C#.net、J++.net、Delphi.net、SmallTalk.net等等等等等等的.net语言使用,应用范围非常广。程序效果如下:

该程序仿Visual Stdio资源编辑器的树界面,支持拖拽,背景为半透明^_^在树中按下"Del"可以快速删除。树下面那个滚动条不关偶的事哦,那是.net v1.1的Bug之一:) 另一个Bug是不可以开启System效果,否则树将无法绘制图标,我猜测可能是操作系统不支持托管的图标资源所致。

由于程序是用Visual C++7.0 写的,有些地方语法十分古怪,和标准ISO C++及微软自己的CLI C++均不一样,整个程序基本上是用指针堆出来的,大家就当伪代码着吧^_^

总结天呐,还没完啊,写完程序写文章,累死我了,再坚持一下下就好.....:)

System::Resources命名空间中还有很多用于操作资源的类,这里就不一一列出了,感兴趣的读者可以自己去参考MSDN,需要注意的是该命名空间中的所有类实际上是封装了IResourceReader/IResourceWriter接口,高手们也可以自己封装出比它更好的类:)

我在Simple1、Simple2中做了大量的注释,如果还有什么问题,可以在下面留言或者联系我,我会尽量给予解答。

本文全部内容均为caeser2本人原创,如要引用本文内容或代码或程序,请说明出处。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有