第6章 定时器和windows时间

1 定时器

相关api

//设置定时器
SetTimer
UINT SetTimer(
    HWND hWnd,  // handle of window for timer messages
    UINT nIDEvent,  // timer identifier
    UINT uElapse,   // time-out value
    TIMERPROC lpTimerFunc   // address of timer procedure 当为NULL时会向窗口发送VM_TIMER消息
   );

WM_TIMER 消息的附加参数
wTimerID = wParam;            // timer identifier 
tmprc = (TIMERPROC *) lParam; // address of timer callback 
 

//撤销定时器
KillTimer
BOOL KillTimer(
    HWND hWnd,  // handle of window that installed timer
    UINT uIDEvent   // timer identifier
   );

源代码
Timer.rc

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include        <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define DLG_MAIN        1
#define ICO_1           1
#define ICO_2           2
#define IDC_SETICON     100
#define IDC_COUNT       101
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//定义了两个icon
ICO_1   ICON        "1.ico" //对话框的图标,会取第一个ICON
ICO_2   ICON        "2.ico"


//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//定义一个对话框 name DIALOG x,y,w,h
DLG_MAIN DIALOG 50, 50, 113, 40
//对话框的style
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

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 3rd Edition>
; by 罗云彬, http://www.win32asm.com.cn
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Timer.asm
; 定时器的使用例子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令进行编译和链接:
; ml /c /coff Timer.asm
; rc Timer.rc
; Link /subsystem:windows Timer.obj Timer.res
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .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      ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 定时器过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcTimer  proc    _hWnd,_uMsg,_idEvent,_dwTime
        
        PUSHAD ;将通用寄存器压栈 入栈顺序为EAX,ECX,EDX,EBX,ESP(初始值),EBP,ESI,EDI.
        invoke  GetDlgItemInt,hWinMain,IDC_COUNT,NULL,FALSE
        ; GetDlgItemInt 获取对话框指定控件文本,将其转换为整数
        ;UINT GetDlgItemInt(
        ;    HWND hDlg, // handle to dialog box
        ;    int nIDDlgItem,    // control identifier
        ;    BOOL *lpTranslated,    // points to variable to receive success/failure indicator
        ;    BOOL bSigned   // specifies whether value is signed or unsigned
        ;   );
        inc eax
        invoke  SetDlgItemInt,hWinMain,IDC_COUNT,eax,FALSE
        ;BOOL SetDlgItemInt(
        ;    HWND hDlg, // handle of dialog box
        ;    int nIDDlgItem,    // identifier of control
        ;    UINT uValue,   // value to set
        ;    BOOL bSigned   // signed or unsigned indicator
        ;   );
        POPAD ;将通用寄存器恢复
        ret

_ProcTimer  endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口过程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain    proc    uses ebx edi esi,hWnd,uMsg,wParam,lParam

        mov eax,uMsg
;********************************************************************
        .if eax ==  WM_TIMER 
            ;处理WM_TIMER
            ;WM_TIMER 消息的附加参数
            ;wTimerID = wParam;            // timer identifier 
            ;tmprc = (TIMERPROC *) lParam; // address of timer callback 
            ;
            mov eax,wParam ;将定时器ID放入eax
            .if eax ==  ID_TIMER1 ;若是第1个定时器
                inc dwCount ;dwCount加1
                ;取dwCount的第1位 0/1
                mov eax,dwCount
                and eax,1 ;eax=0 or 1
                inc EAX ;eax=1 or 2 对应ICO_1 ICO_2
                invoke  LoadIcon,hInstance,EAX ;加载icon
                ;修改ICON控件IDC_SETICON的图标
                invoke  SendDlgItemMessage,hWnd,IDC_SETICON,STM_SETIMAGE,IMAGE_ICON,EAX
                ;LONG SendDlgItemMessage(
                ;    HWND hDlg, // handle of dialog box
                   ; int nIDDlgItem,    // identifier of control
                   ; UINT Msg,  // message to send
                   ; WPARAM wParam, // first message parameter
                   ; LPARAM lParam  // second message parameter
                   ;);
                ;STM_SETIMAGE消息的附带参数
                ;wParam = (WPARAM) fImageType;       // image-type flag IMAGE_ICON/IMAGE_BITMAP/...
                ;lParam = (LPARAM) (HANDLE) hImage;  // handle of the image
            .elseif eax ==  ID_TIMER2 ;若是第2个定时器
                invoke  MessageBeep,-1 ;调用蜂鸣器
            .endif
;********************************************************************
        .elseif eax ==  WM_INITDIALOG ;窗口初始化时
            push    hWnd
            pop hWinMain ;将hWnd赋值给hWinMain
            invoke  SetTimer,hWnd,ID_TIMER1,250,NULL ;创建定时器ID_TIMER1 周期为250ms
            invoke  SetTimer,hWnd,ID_TIMER2,2000,NULL ;创建定时器ID_TIMER2 周期为2s
            invoke  SetTimer,NULL,NULL,1000,addr _ProcTimer ;创建定时器ID_TIMER3 周期为1s 定时器回调函数为_ProcTimer
            mov idTimer,EAX ;将第3个定时器的id保存至idTimer
;********************************************************************
        .elseif eax ==  WM_CLOSE
            ;在窗口退出之前撤销3个定时器
            invoke  KillTimer,hWnd,ID_TIMER1
            invoke  KillTimer,hWnd,ID_TIMER2
            invoke  KillTimer,NULL,idTimer
            ;结束对话框
            invoke  EndDialog,hWnd,NULL
;********************************************************************
        .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,NULL
        invoke  ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        end start

Makefile

NAME = Timer
OBJS = $(NAME).obj
RES  = $(NAME).res

LINK_FLAG = /subsystem:windows
ML_FLAG = /c /coff

$(NAME).exe: $(OBJS) $(RES)
    Link $(LINK_FLAG) $(OBJS) $(RES)

.asm.obj:
    ml $(ML_FLAG) $<
.rc.res:
    rc $<

clean:
    del *.obj
    del *.res

2 windows时间

2.1 windows时间的获取和设置

GetLocalTime SYSTEMTIME
GetSystemTime

2.2 计算时间间隔

GetTickCount

Guess you like

Origin blog.csdn.net/a854596855/article/details/114920018