文章编号 100426410(2007)S120270203
Del phi 开发中的字符串资源动态替换
朱微微
(柳州市第一职业技术中等专业学校,广西柳州 545007)
摘 要:本文介绍了Delphi 中Res ourceString (简称资源字符串)关键字工作原理,运行时动态替换字符串资源,以解决在许多需要多语切换的场合必须定义大量全局变量的方式解决动态切换字符串数据方法。由于全局变量过多且可读写容易被其它模块撰改没有常量的特性,而资源字符串定义的字符串资源是单独存储在P E 资源节的且是在读取时才加载并具有常量的特性。
关 键 词:资源;PE 资源节;字符串资源;动态替换
中图分类号:TP311111    文献标识码:A
收稿日期22作者简介朱微微(652),女,江苏南通市人,广西柳州市第一职业技术学校计算机高级教师。
0 引言
国内普通的自由、共享软件和商业软件等因为面向的是国内用户,因此一般都是中文版。国外的软件大多是英文版,在国内流传时给用户造成了许多不便,因而有热心的程序员开始制作包,用以将程序界面中的英文字符改成中文。但也有一些软件,发布的时候就自带了多种语言包,运行时可以自动判断用户的Windows 语言种类进而确定界面的语言风格,如网络蚂蚁(NetAnt s),它能够在运行的时候由用户来选择中文或英文,它本身能够在两种不同的语言间进行动态切换,这是所谓“国际版”软件的风格。我们可以通过字符串资源定义的字符串动态替换来实现运行时改变字符串资源的目的,从而为或多语言化某些软件提供一种可供选择的方法和途径。
在这里利用Delphi 提供的语言特性,资源字符串揭示高级语言在对许多高效编程技巧的封装,尽可能的利用Win32提供的功能快速高效的解决问题。同时希望读者更加关注通过实践和多解读VCL 自带源码深入理解Wi n 系统特性,体会封装的艺术[1]。
1 关键词解释
资源———可以说是可执行文件中使用的图像、字串等数据的总称。从原则上来说任何类型的文件都可以通过资源的方式编译进EXE 文件中。编程开发中常用的资源有位图、图标、鼠标光标、字符串等,甚至可以包括菜单、加速键等。编译后的资源文件(扩展名一般为1res)能在程序编译时通过声明的方式被引入到可执行文件中。
PE 资源节———指的是在P E 文件格式中一段存放资源的一段数据结构,可借助类似Resource Hacker 之类的工具查看甚至是修改,对于一些简单软件都是修改或者是替换原程序的资源节达到的。
字符串资源———P E 资源节中的字符串数据,一般用于存储提示信息,菜单项名称等。
动态替换———在程序运行时进行资源数据的替换,以达到无需从新编译运行即可改变程序中的某些数据的目的(如程序中/英文界面的切换)等。
2 资源字符串的动态替换
用资源字符串的关键字定义的字符串,将会以字符串资源的形式被链接到可执行文件或者动态链接库第18卷 增刊1          广西工学院学报           Vol 118 Sup 12007年6月 JOURNAL OF G UANGXI UN IV ERSI TY OF TECHNO LO GY    J une 12007:20070420
:19
中,同等于使用装载函数加载指定模块中的字符串资源一样,不同的是Delphi 对其的使用进行了封装使得可像常量一样方便的使用字符串资源。
本文介绍的是如果在不改变原定义的情况下使其可链接到其它模块的字符串资源上。其实现意思是在程序多语言化时动态切换其资源串资源,并不影响程序逻辑和代码结构。
211 资源字符串结构
TResStringRec ———资源字符串结构,它定位了资源字符串在模块[1]中的位置。
PResStringRec ———资源字符串指针,它是指向一个资源结构的指针。
资源字符串结构的定义在System 1pas 单元中,定义如下:
t ype
  PResStringRec =^TResSt ringRec ;
  TResStringRec =packed record
  Module :^Cardi nal ;//模块实例句柄
  Ident ifier :Integer ;//字符串资源编号
end ;
资源结构的Module(简称资源句柄)为什么被定义为一个Cardinal 的指针类型呢?因为在同一模块中所有
实例引用的资源句柄都是一样的,既节约了存储空间,又方便统一修改。让它们同时指向同一资源句柄,这样只要修改了一个资源句柄,那么所有模块中引用了该资源所有实现便会同时改变(可参考\Program Files \Borland \Delphi7\Demos \RichEdit 的实现)。Identifier (简称资源标识符)域则是编译器为资源字符串分配的一个整型编号作为资源标识符,在同一模块中每一个资源项的标识符都是唯一的[2]。
212 动态替换原理
只要利用资源字符串指针改变资源字符串的资源句柄和资源标识符即可实现改变资源字符串的内容。但以resourcest ring 关键字定义的资源字符串,编译器为了保证程序结构一致性与严谨性使得资源字符串的存在就像常量一样,在程序运行时是不允许被修改的。所以在改变资源字符串的资源句柄与资源标识符之前,必须先将资源字符串变为可读写状态。虽然resourcest ring 定义的资源字符串结构是只读的,但由于在程序运行时对自己所属的内存空间内有完全的读写权限,而且资源字符串结构肯定是在进程中分配的内存空间,仅是由于编译器为了实现数据一致性和安全性对该区域的内存进行的读取限制。在Wi ndows 操作系统中提供了VirtualProtect 函数来改变自己提供的内存页面的保护属性,所以只要通过AP I VirtualProtect 先将资源字符串结构的内存地址的访问属性置为可读写的,再时行修改资源字符串结构的内容,在修改完成后再重新置回只读状态即可[3]。
样例关键代码如下:
resourcest ring
 csChineseVer =’我的软件(中文版)’;
 csEngli shVer =’My Sof tware (Engli sh Ver)’;
procedure Tfrm Test 1bt nSwitchClick (Sender :TObject );
var
 OldProtect :DWORD ;
 t mpRes:TResSt ringRec ;
begin
 //通过Vi rt ual Prot ect 修改指定数据所在区域的内存属性为可读写
 //该区域原来的属性保存在Ol dProtect 中
 Vi rt ual Prot ect (@csChi neseVer ,SizeO f (PResSt ri ngRec ),PA GE -EXECU TE -READWRI TE ,@Ol dPro 2);
 R =R S R (@V )^;交换资源字符串结构的值
 R S R (@V )^=R S R (@V )^;
172增刊1             朱微微:Delphi 开发中的字符串资源动态替换tect t mp es:P es t ri ng ec csChi nese er //P es t ri ng ec csChi nese er :P es t ring ec csEnglish er
字符串截取不改变原字符串 PResSt ri ngRec (@csEnglishVer)^:=t mpRes ;
 //恢复原内存区域内的属性
 Vi rt ual Prot ect (@csChineseVer ,S izeOf (PResSt ri ngRec ),Ol dProt ect ,@OldProt ect );
 Self 1Capt ion :=csChineseVer ;//刷新标题
 l bl Ver Ti tle 1Caption :=csChineseVer ;//刷新提示信息
end ;
成功运行时会将资源字符串csChineseVer 、csEnglishVer 的值相互交换。使程序达到只引用一个固定的csChi neseVer 标识符就可以在两种语种的提示信息之间进行切换而无需修改源程序的效果。
运行效果如图1所示。
测试程序运行后,显示的标题为中文字符串,点击“切换”按钮后,标题如图2所示变为英文字符串。
图1 运行效果图图2 切换后效果图
3 结束语
通过该技巧可动态的将原代码中的字符串资源全部替换而不影响其它代码,替换时只需要新建个管理类然后将需要替换的单元引用(uses )进来即可,无论该资源串是放在同一执行文件中还是别的动态链接库中都没有关系,读者可根据项目需要处理。
参 考 文 献:
[1]李 维1VCL 架构剖析[M ]1北京:电子工业出版社,20041
[2]Steve Teixeira ,X avier Pac heco 1Delphi6开发人员指南[M]1龙劲松,王瑜,谢尚书,译1北京:机械工业社,20021
[3]周爱民1Delphi 源代码分析[M]1北京:电子工业出版社,20041
(责任编辑 赖君荣)272广西工学院学报                    第18卷

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。