windows环境下32位汇编语言程序设计-第31节
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
对于多选列表框,需要用LB_GETSELITEMS消息获取全部选中项目,这个消息返回的是一个列表,所有选中项目的索引按顺序排列返回到缓冲区中,所以在例子中处理“查看”按钮消息(IDOK)的时候,程序先发送LB_GETSELCOUNT消息得到选中的项目数,以便在下面用一个循环获取所有的项目,得到项目数后,再用LB_GETSELITEMS将选中项目的索引取到@szBuffer中,接下来进入一个循环,循环的次数就是LB_GETSELCOUNT得到的数值,在循环中,程序从@szBuffer中将索引值逐个取出并用LB_GETTEXT消息获取每一项的字符串,最后用一个MessageBox显示出来。
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第5章 使用资源
5。5 字符串资源/5。6 版本信息资源(1)
程序中用到的字符串常常定义在 nst段中,但Windows也提供了另外一种使用字符串常量的方法,那就是在资源中定义。虽然在资源中定义字符串使用起来比直接在 nst段中定义要复杂一点,但它带来的好处是便于开发不同语言的版本,比如,要推出其他语种的版本只需要修改资源中的字符串表就可以了,即使语言转换的工作是由第三者通过修改可执行文件来做的(如编程爱好者常常做的汉化工作),修改资源也远比修改代码来得快捷和安全。
在资源脚本中定义字符串的语法是:
STRINGTABLE 'DISCARDABLE'
BEGIN
字符串ID1 〃字符串1〃
字符串ID2 〃字符串2〃
。 。 。
END
全部字符串组成一个字符串表,和其他资源定义不同,由于整个资源文件中只能定义一个字符串表,所以字符串表没有资源ID,但是表中的不同字符串分别有一个字符串ID。
在程序中使用字符串资源也很简单,用LoadString把字符串装入到缓冲区中去就可以用了:
invoke LoadString,hInstance,字符串ID,addr 缓冲区,sizeof 缓冲区
为了防止溢出,最后一个参数指定缓冲区的长度。
如果要在单个可执行文件中实现多语种,那么可以在字符串表中定义不同语言的字符串。同一语种的字符串按规律排列,如下列中文的以1000开头,英文的以2000开头:
stringtable
{
1001 〃文件未找到!〃
1002 〃无法打开文件!〃
。。。
2001 〃File not found!〃
2002 〃Can not open file!〃
。。。
}
在程序中使用的时候,先确定一种语言并预先设置在dwLanguage变量中,使用中文时将dwLanguage设置为1000,使用英文时设置为2000,再写一个读取不同版本字符串的子程序_GetString,这样调用_GetString子程序后就不用考虑版本问题了:
_GetString proc _dwID;_lpBuffer;_dwSize
pushad
mov eax;_dwID
add eax;dwLanguage
invoke LoadString;hInstance;eax;_lpBuffer;_dwSize
popad
ret
_GetString endp
5。6 版本信息资源
有时应用程序需要确保自己运行时使用某一特定版本的DLL,以便确保可以使用某些函数。检测版本是通过API函数查询定义于资源中的版本信息来完成的,如果资源中没有定义版本,那么就无法知道一个文件的版本究竟是多少。
版本信息是以VERSIONINFO类型的资源保存在应用程序中的,里面可以定义的信息包括文件的版本号、创建单位和语种等。版本信息的定义是可选的,一个程序可以不定义版本信息资源,如果定义了的话,也不一定要定义全部信息项目。
如果一个文件定义有版本信息资源,那么在文件的属性页(在文件图标上按鼠标右键,在弹出的菜单上选择)上就会有一个“版本”页面,如图5。10所示。
图5。10 文件属性中的版本信息
5。6。1 版本信息资源的定义
在所附光盘的Chapter05VersionInfo目录中有一个例子,在该目录的Version。rc文件中定义了一个版本信息,读者可以看编译后的VersionInfo。exe中的“版本”属性页,对比一下资源定义中的内容究竟出现在属性页的哪些地方,定义的代码如下:
1 VERSIONINFO
FILEVERSION 1;2;3;4
PRODUCTVERSION 2;3;4;5
FILEOS VOS_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK 〃VarFileInfo〃
BEGIN
VALUE 〃Translation〃; Ox804; Ox4b0
END
BLOCK 〃StringFileInfo〃
BEGIN
BLOCK 〃080404b0〃
BEGIN
VALUE 〃ments〃; 〃Here is ments0〃
VALUE 〃panyName〃; 〃Here is panyName0〃
VALUE 〃FileDescription〃; 〃Here is FileDescription0〃
VALUE 〃FileVersion〃; 〃1; 0; 0; 10〃
VALUE 〃InternalName〃; 〃Here is InternalName0〃
VALUE 〃LegalCopyright〃; 〃Here is LegalCopyright0〃
VALUE 〃LegalTrademarks〃; 〃Here is LegalTrademarks0〃
VALUE 〃OriginalFilename〃; 〃Here is OriginalFilename0〃
VALUE 〃PrivateBuild〃; 〃Here is PrivateBuild0〃
VALUE 〃ProductName〃; 〃Here is ProductName0〃
VALUE 〃ProductVersion〃; 〃1; 0; 0; 10〃
VALUE 〃SpecialBuild〃; 〃Here is SpecialBuild0〃
END
END
END
现在来看这些定义语句的含义。首先,版本信息定义的语句格式是:
版本信息资源ID VERSIONINFO
固定属性
BEGIN
块声明定义
……
END
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第5章 使用资源
5。6 版本信息资源(2)
版本信息资源ID的取值必须为1,如果不为1则属性页上的“版本”信息是无法显示出来的。(笔者也不明白为什么必须为1还要定义这个ID,像stringtable一样没有ID不就完事了?)
可以定义的固定属性有:
● FILEVERSION——定义文件版本号,可以定义4个16位版本号xx。xx。xx。xx。
● PRODUCTVERSION——定义产品版本号,可以定义4个16位版本号xx。xx。xx。xx。
● FILEFLAGSMASK——指定FILEFLAGS属性中哪些位有效。
● FILEFLAGS—文件标志,是一些标志位的组合:VS_FF_PATCHED,VS_FF_DEBUG,VS_FF_PRIVATEBUILD,VS_FF_INFOINFERRED,VS_FF_PRERELEASE和VS_FF_SPECI… ALBUILD。
● FILEOS—定义适用的操作系统,可以定义为VOS_UNKNOWN,VOS_DOS,VOS_NT,VOS_WINDOWS16,VOS_WINDOWS32,VOS_DOS_WINDOWS16,VOS_DOS_WINDOWS32 或VOS_NT_WINDOWS32。
● FILETYPE—定义文件类型,可以是VFT_UNKNOWN,VFT_APP,VFT_DLL,VFT_ DRV,VFT_FONT,VFT_VXD或VFT_STATIC_LIB。
● FILESUBTYPE——定义文件的子类型。当文件类型是VFT_DRV(驱动程序)的时候,这里可以是VFT2_UNKNOWN,VFT2_DRV_M,VFT2_DRV_PRINTER,VFT2_DRV_ KEYBOARD,VFT2_DRV_LANGUAGE,VFT2_DRV_DISPLAY,VFT2_DRV_MOUSE,VFT2_DRV_NETWORK,VFT2_DRV_SYSTEM,VFT2_DRV_INSTALLABLE或VFT2_ DRV_SOUND;当文件类型是VFT_FONT(字体)的时候,这里可以是VFT2_UNKNOWN,VFT2_FONT_RASTER,VFT2_FONT_VECTOR或VFT2_FONT_TRUETYPE。
在固定属性定义完成以后,需要定义一些块声明,块声明有两种:变量型的信息块和字符串类型的信息块,变量类型的信息块定义如下:
BLOCK 〃VarFileInfo〃
BEGIN
VALUE 〃Translation〃;
语言ID;字符集ID
……
END
语言ID的常用值有Ox0404(繁体中文)、Ox0409(美国英语)和Ox0804(简体中文),字符集ID的常用值有0(7位ASCII)、950(台湾GB5)和1200(Unicode)。一般使用Ox804; Ox4b0来定义,也就是简体中文和Unicode(Ox4b0=1200)。其他还有很多取值,读者可以查看Rc。exe的帮助文件。
变量类型信息块用来表示VERSIONINFO资源中定义有哪些语言和字符集的字符串类型信息块。如上例中有一句VALUE 〃Translation〃,Ox804,Ox4b0表示对应有一个名为“080404b0”的字符串类型的信息块。
字符串信息块的定义语句为:
BLOCK 〃StringFileInfo〃
BEGIN
BLOCK 〃语言集〃
BEGIN
VALUE 〃字符串名称〃; 〃字符串〃
……
END
END
语言集就是变量类型中定义的,其名称一定要是将语言ID和字符集ID组合成一个8位的16进制的格式,以上例文件来说明,当变量类型的信息块种定义Ox804;Ox4b0时,语言集名称就是“080404b0”,在语言集块的定义中,还可以定义多条字符串型的版本信息,这些版本信息的字符串名有12种,如表5。9所示。
表5。9 版本信息字符串类型
字符串名称
属性页位置
说 明
ments
备注
有关程序的附加说明信息
panyName
公司
开发产品的公司
FileDescription
描述
有关文件的简单描述
FileVersion
文件版本
如1。50、5。0。RC2等字符串型的版本信息
InternalName
内部名称
LegalCopyright
版权
文件的所有版权信息
LegalTrademarks
合法商标
文件的所有注册商标信息
OriginalFilename
源文件名
原始文件名,从这里可以得知文件是否被改名
PrivateBuild
个人用内部版本说明
作者私人信息
ProductName
产品名称
文件所属的产品名称
ProductVersion
产品版本
文件所属的产品的版本号
SpecialBuild
特殊内部版本说明
特殊说明
定义版本信息字符串的时候要注意,所有的字符串必须是以NULL结尾的串,所以要在字符串尾加上0,如例子程序所示:
VALUE 〃ments〃; 〃Here is ments0〃
VALUE 〃panyName〃; 〃Here is panyName0〃
。。。
5。6。2 在程序中检测版本信息
Win32 API中有3个版本信息函数:GetFileVersionSize,GetFileVersionInfo 和 VerQueryValue,它们驻留在VERSION。DLL文件中,如果在源程序中使用它们,注意要加上include Version。inc以及includelib Version。lib语句。
用这3个函数获取版本信息的方法是:
首先调用GetFileVersionInfoSize函数检测文件中有没有版本信息资源:
invoke GetFileVersionInfoSize;addr szFile;NULL
其中szFile是要检测的PE文件名字符串,该函数的返回值是版本信息资源的长度,如果返回0,则表示文件不是PE文件或没有定义版本信息资源。
如果检测到文件中有版本信息资源,那么可以将版本信息资源读取到一个缓冲区中,缓冲区的长度必须足够容纳上一步返回的资源长度,方法是:
invoke GetFileVersionInfo;addr szFile;NULL;sizeof dbVerInfo;addr dbVerInfo
其中dbVerInfo为一个足够大的缓冲区。该函数会把整个版本信息资源拷贝到这个缓冲区中。
拷贝到缓冲区种的信息有它自己的格式,必须用VerQueryValue去“解码”,解码固定属性的方法是:
invoke VerQueryValue;addr dbVerInfo;addr szRoot;addr lpBuffer;addr dwLen
第一个参数指向前一步返回的版本信息资源数据,第二个参数指向一个字符串:“”,第三和第四个参数指向dw类型的变量lpBuffer和dwLen,返回到lpBuffer中的是指向一个VS_FIXEDFILEINFO结构的指针,这个结构中有定义的固定属性内容。
如果要获取字符串类型信息块中的版本信息,那就比较复杂一