按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
中有定义的固定属性内容。
如果要获取字符串类型信息块中的版本信息,那就比较复杂一点了,必须首先知道语言集的名称,所以先要获取版本信息资源中变量类型信息块的内容,方法是:
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
pu