在这儿下载本节的所有源程序
概述
Windows 的定时器是一种输入设备,它周期性地在指定的间隔时间通知应用程序。它可以用向指定窗口发送 WM_TIMER 消息或者调用指定的过程来执行用户的程序。定时器的应用主要包括下面一些地方:
总的来说,在 Dos 下实现精确定时的唯一方法是在 int 1ch 时钟中断中处理程序,但你使用起来必须遵守很多的规范,而在 Windows 的定时器中,你可以用 SetTimer 函数分配不止一个的定时器,比如说,在你的文本编辑程序中,你可以使用一个间隔1秒的定时器来在状态栏中显示时钟,同时分配一个10分钟的定时器来实现定时存盘的功能。定时器实际上是 Windows 对时钟中断的一种扩展,它的本质还是基于时钟中断的,所以你实际上无法把定时器的间隔设置到55毫秒以下,另外,定时器的精度也是以55毫秒为倍数的,比如说,你设置了一个1秒的定时器,它实际上是在每989毫秒的时候发生的。和在 Dos 下使用时钟中断,windows 的定时器还有下面一些要点:
讲了这么多定时器的特点,下面是定时器相关的API,你会发现除了在使用中要注意的这些特性,定时器的API真是又少又简单:
在本节的例子程序中,我在对话框中的 WM_INIT 消息中用 SetTimer 建立两个定时器,时间分别是500ms 和 200ms,然后在间隔0.5秒的定时器消息中更换按钮上的图片,在间隔 0.2 秒的定时器消息中更换标题栏上的小图标,你就可以看到动画的效果了。
源程序 - 汇编源文件
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Programmed by 罗云彬, bigluo@telekbird.com.cn ; Website: http://asm.yeah.net ; LuoYunBin's Win32 ASM page (罗云彬的编程乐园) ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 版本信息 ; 汇编教程附带例子程序 - 定时器的使用 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .386 .model flat, stdcall option casemap :none ; case sensitive ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc include kernel32.inc include comctl32.inc include comdlg32.inc includelib user32.lib includelib kernel32.lib includelib comctl32.lib includelib comdlg32.lib ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Equ 数据 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IDI_MAIN equ 1 IDI_MOON1 equ 2 IDI_MOON2 equ 3 IDI_MOON3 equ 4 IDI_MOON4 equ 5 IDI_MOON5 equ 6 IDI_MOON6 equ 7 IDI_MOON7 equ 8 IDI_MOON8 equ 9 DLG_MAIN equ 1000 ID_MOON equ 1001 ID_TIMER1 equ 1 ID_TIMER2 equ 2 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 数据段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .data? hInstance dd ? dwCounter1 dd ? dwCounter2 dd ? hIcon1 dd ? hIcon2 dd ? hIcon3 dd ? hIcon4 dd ? hIcon5 dd ? hIcon6 dd ? hIcon7 dd ? hIcon8 dd ? szBuffer db 256 dup (?) .data ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 代码段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> .code ;******************************************************************** _ProcDlgMain proc uses ebx edi esi, \ hWnd:DWORD,wMsg:DWORD,wParam:DWORD,lParam:DWORD mov eax,wMsg ;******************************************************************** .if eax == WM_CLOSE invoke KillTimer,hWnd,ID_TIMER1 invoke KillTimer,hWnd,ID_TIMER2 invoke EndDialog,hWnd,NULL ;******************************************************************** .elseif eax == WM_INITDIALOG mov edi,offset hIcon1 mov ebx,IDI_MOON1 mov ecx,8 @@: push ecx invoke LoadIcon,hInstance,ebx cld stosd inc ebx pop ecx loop @B invoke SetTimer,hWnd,ID_TIMER1,500,NULL invoke SetTimer,hWnd,ID_TIMER2,200,NULL invoke SendMessage,hWnd,WM_SETICON,ICON_SMALL,hIcon1 ;******************************************************************** .elseif eax == WM_TIMER .if wParam == ID_TIMER1 inc dwCounter1 .if dwCounter1 == 8 mov dwCounter1,0 .endif mov eax,dwCounter1 shl eax,2 add eax,offset hIcon1 mov eax,[eax] invoke SendMessage,hWnd,WM_SETICON,ICON_SMALL,eax .else inc dwCounter2 .if dwCounter2 == 8 mov dwCounter2,0 .endif mov eax,dwCounter2 shl eax,2 add eax,offset hIcon1 mov eax,[eax] invoke SendDlgItemMessage,hWnd,ID_MOON,BM_SETIMAGE,IMAGE_ICON,eax .endif ;******************************************************************** .else mov eax,FALSE ret .endif mov eax,TRUE ret _ProcDlgMain endp ;******************************************************************** start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,0 invoke ExitProcess,NULL ;******************************************************************** end start
程序的分析和要点
有了上面的介绍,这个程序是很容易看懂的,在 WM_TIMER 消息中,通过 wParam 中的 TimerID 可以区分是哪个定时器产生的消息。在 WM_CLOSE 消息中,通过 KillTimer 来取消定时器。本程序中的的图标定义在资源文件中,在对话框建立的时候,先用 LoadIcon 装入,然后为两个定时器分别保存一个图片编号 dwCounter1 和 dwCounter2,在定时器消息中分别用 WM_SETICON 和 BM_SETIMAGE 消息来对窗口标题的图标和按钮的图标进行设置。