友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
八万小说网 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

windows环境下32位汇编语言程序设计-第24部分

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




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结构的指针,这个结构中有定义的固定属性内容。

如果要获取字符串类型信息块中的版本信息,那就比较复杂一点了,必须首先知道语言集的名称,所以先要获取版本信息资源中变量类型信息块的内容,方法是:

invoke   VerQueryValue;addr dbVerInfo;addr szVarInfo;addr lpBuffer;addr dwLen

mov      eax;lpBuffer

mov      eax;'eax'

ror      eax;16

szVarInfo是一个字符串:“VarFileInfoTranslation”,这时函数在lpBuffer中返回语言集变量指针的指针,所以要先mov eax;lpBuffer,再用eax作指针用mov eax;'eax'得到语言集变量。语言集变量的高16位是字符集ID,低16位是语言ID,可以使用ror eax;16来调换高低位,以我们的例子为例,现在eax中的值就是080404b0h了!

接下来就可以获取字符串版本信息了,先将语言集的值通过wsprintf函数转换成“080404b0”的形式,然后拼装成“StringFileInfo080404b0字符串名称”形式的字符串;中间的“字符串名称”可以是表5。9中的12种名称之一,最后调用下面的语句(假定拼装好的字符串地址为szString):

invoke   VerQueryValue;addr dbVerInfo;addr szString;addr lpBuffer;addr dwLen

执行后lpBuffer中会得到一个指针,指向版本信息字符串定义的内容,这就是我们最后需要的东西!重复这个步骤可以得到所有12种字符串版本信息。

读者可以在所附光盘的Chapter05ShowVersionInfo目录中找到一个ShowInfo程序,它可以获取PE文件中的版本信息资源并显示出来,详细的代码请参考该目录中的文件,主文件ShowInfo。asm是界面程序,版本信息资源的代码在GetVersionInfo。inc文件中,由于篇幅有限,源程序在这里就不列出来了。



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第5章 使用资源


5。7 二进制资源和自定义资源

    
5。7。1  使用二进制资源

在第2章中曾经提到DOS的exe文件可以带一个覆盖部分,覆盖部分实际上就是在真正的可执行部分后面附加的数据,然后由程序在运行中打开自身文件并使用这些数据。Win32的可执行文件中除了上面介绍的这些标准类型的资源外,也可以在程序中附带其他数据,当然方法完全不同——Win32资源中允许用户自己定义二进制的资源或者自定义格式的资源,资源的内容可以是任何数据,也可以将一个磁盘文件按二进制格式包括进去。

二进制资源的定义格式是:

资源ID   RCDATA 'DISCARDABLE'

BEGIN

         数据定义

         …

END

也可以用一个磁盘文件当做资源的内容:

资源ID  RCDATA 'DISCARDABLE' 文件名

在程序中要使用资源的内容时,可以通过以下步骤将资源装入内存使用:

(1)用FindResource(hInstance;lpName,lpType)查找资源。lpName的值为资源ID,lpType的值为RT_RCDATA,如果找到资源。那么函数返回一个资源信息句柄。

(2)用LoadResource(hInstance; hResInfo)装入资源。hResInfo是上一步中得到的资源信息句柄,装入成功的话函数会返回一个资源句柄。

(3)用LckResource(hResData)将资源锁定到内存中。hResData是上一步得到的资源句柄,函数返回资源装入的内存地址,程序就可以使用内存中的数据了。

(4)如果想知道装入资源的大小是多少,可以使用FindResource返回的hResInfo来调用SizeofResource(hInstance;hResInfo)从而得到资源大小。

下面是一个装入资源ID为ID_MYRES的RCDATA类型资源的例子:

invoke   FindResource;hInstance;ID_MYRES;RT_RCDATA   ;寻找资源

。if      eax

        mov     hResInfo;eax

        invoke  SizeofResource;hInstance;eax            ;获取资源尺寸

         mov     dwResSize;eax

        invoke  LoadResource;hInstance;hResInfo     ;装入资源

        。if     eax

                 invoke  LockResource;eax                ;锁定资源

                 。if     eax

                         mov     lpRes;eax

                         ;处理lpRes指向的资源内容

                 。endif

         。endif

。endif

5。7。2  使用自定义资源

自定义资源的定义格式比二进制资源更灵活,它和二进制资源的区别在于可以指定资源类别为自定义的名称:

资源ID       类型ID 'DISCARDABLE'

BEGIN

     数据定义

    …

END

或用一个磁盘文件当做资源的内容:

资源ID  类型ID 'DISCARDABLE' 文件名

类型ID可以是大于255的数值(255及以下的数值由Windows使用)或字符串,如可以定义如下:

1000     WAVE        〃Hello。wav〃     ;定义类型为“WAVE”,资源ID为1000的资源

1000     TEXT        〃Readme。txt〃        ;定义类型为“TEXT”,资源ID为1000的资源

1000     1000        〃Test。bin〃      ;定义类型ID为1000,资源ID为1000的资源

在程序中使用自定义资源的方法和使用二进制资源类似,惟一的区别是使用FindResource得到hResInfo的参数有些区别,得到hResInfo以后的步骤是一模一样的。针对上面3句定义,查找资源的方法可以是:

szResType1       db      〃WAVE〃;0

szResType2       db      〃TEXT〃;0

                 。。。

invoke   FindResource;hInstance;1000;addr szResType1 ;针对上面第一句

invoke   FindResource;hInstance;1000;addr szResType2 ;针对上面第二句

invoke   FindResource;hInstance;1000;1000                ;针对上面第三句

在使用完二进制或自定义资源以后,不必使用任何函数去释放它们,Windows在程序退出的时候会自动将它们释放。



 
来源:电子工业出版社 作者:罗云彬 上一页         回书目         下一页          
上一页         回书目         下一页          
  


第6章 定时器


6。1 定时器简介/6。2 定时器的使用(1)

    
在应用程序需要使用定时器时,可以用SetTimer函数向Windows申请一个定时器,要求系统在指定的时间以后“通知”应用程序,如果申请成功的话,系统会以指定的时间周期调用SetTimer函数指定的回调函数,或者向指定的窗口过程发送WM_TIMER消息,和DOS操作系统固定以55 ms的间隔触发中断服务程序相比,SetTimer函数可以指定的时间间隔更为灵活——以ms为单位,可以指定的时间周期为一个32位的整数,也就是从1~4 294 967 295 ms,这可是一个将近50天的范围!

但是在具体的使用中不要被这个参数所迷惑:由于Windows的定时器同样是基于时钟中断的,所以虽然参数的单位是ms,但精度还是55 ms,如果指定一个小于55 ms的周期,不管是1 ms还是54 ms,Windows最快也只能在每个时钟中断的时候触发这个定时器,也就是说,实际上这个定时器是以55 ms为触发周期的;另外,当指定一个时间间隔的时候,Windows以和这个间隔最接近的55 ms的整数倍时间来触发定时器,假定建立一个周期为1 000 ms的定时器,定时器的触发周期实际上不是1 s而是989 ms(55 ms×18)。

使用定时器时还有一个要点就是定时器消息是一个低级别的消息,这表现在两个方面:首先就是Windows只有在消息队列中没有其他消息的情况下才会发送WM_TIMER消息,如果窗口过程忙于处理某个消息没有返回,使消息队列中有消息积累起来,那么WM_TIMER消息就会被丢弃,在消息队列再度空闲的时候,被丢弃的WM_TIMER消息不会被补发(用一句经典的话来描述就是:“过去的就让它过去吧!”);其次,消息队列中不会有多条WM_TIMER消息,如果消息队列中已经有一条WM_TIMER消息,还没来得及处理,又到了定时的时刻,那么两条WM_TIMER消息会被合并成一条。

 
 
所以,应用程序不能依靠定时器来保证某件事情必须在规定的时刻被处理,另外,也不能依赖对定时器消息计数来确定已经过去了多少时间。

读者可以在所附光盘的Chapter06Timer目录中找到一个例子,运行Timer。exe以后出现的界面如图6。1所示。

这个例子程序中共定义了3个定时器,第1个以250 ms为周期更换对话框上的图标;第2个以1s为单位进行计数并把结果显示在对话框上;第3个以2s为单位驱动扬声器发出“嘟嘟”的响声。为了验证WM_TIMER消息的级别,读者可以在运行中按住标题栏的“关闭”按钮不放,就可以发现3个定时器全部停止了,然后将鼠标移出“关闭”按钮并释放,定时器会重新工作,但对话框上的计数结果在定时器停止的期间并没有补上去,也就是说,在这期间,WM_TIMER消息被全部丢弃了。

6。2  定时器的使用

下面以Timer程序为例说明定时器的使用方法,这个程序的资源脚本文件定义如下:

#include        

#define DLG_MAIN            1

#define ICO_1           1

#define ICO_2           2

#define IDC_SETICON     100

#define IDC_COUNT       101

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

ICO_1   ICON        〃1。ico〃

ICO_2   ICON        〃2。ico〃

//》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

DLG_MAIN DIALOG 50; 50; 113; 40

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU

CAPTION 〃定时器例子〃

FONT 9; 〃宋体〃



 ICON ICO_1; IDC_SETICON; 8; 9; 18; 21

 LTEXT 〃计数:〃; …1; 35; 16; 25; 10

 LTEXT 〃〃; IDC_COUNT; 62; 16; 40; 10



对资源的定义读者现在一定不会陌生了,这个文件中定义了两个图标和一个对话框,对话框中定义了一个图标框和两个文本框,其中的一个文本框中的文字为空,这是以后显示每秒一次的计数值用的。

Timer。asm源程序如下:

                。386

                。model flat;stdcall

                option casemap:none

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; Include 文件定义

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

include         windows。inc

include         user32。inc

includelib      user32。lib

include         kernel32。inc

includelib      kernel32。lib

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

ID_TIMER1       equ     1

ID_TIMER2       equ     2

ICO_1           equ     1

ICO_2           equ     2

DLG_MAIN            equ     1

IDC_SETICON     equ     100

IDC_COUNT       equ     101

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 数据段

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

                    。data?

hInstance       dd      ?

hWinMain            dd      ?

dwCount         dd      ?

idTimer         dd      ?

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 代码段

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

                de

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

; 定时器过程

;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

_ProcTimer      proc        _hWnd;uMsg;_idEvent;_dwTime

 

        
返回目录 上一页 下一页 回到顶部 7 6
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!