| ||
The next program is slightly more difficult than the previous one. Here, two timers are operating. It is possible to say that two tasks are started simultaneously . [i] The first task gets the system time every 0.5 seconds and forms the string for output ( STRCOPY ). This task has its own function, to which the WM_TIMER message arrives. The second task operates within the framework of the window function. This task displays the data and the time in the edit field of the dialog box at an interval of 1 second. Thus, the two tasks interact to each other using the STRCOPY global variable.
Another important aspect needs to be mentioned related to this program. Because the message that specifies the timer identifier arrives at the timer function, you can implement any number of timers on the basis of a single function.
// The TIMER2.RC file // Constant definitions #define WS_SYSMENU 0x00080000L //Elements of the dialog box must be visible #define WS_VISIBLE 0x10000000L // Border around the element #define WS_BORDER 0x00800000L // Elements can be activated using the <TaB> key #define WS_TABSTOP 0x00010000L // Left-align the text in the edit field #define ES_LEFT 0x0000L // Style of all elements of the window #define WS_CHILD 0x40000000L // Disable the keyboard input #define ES_READONLY 0x0800L #define DS_3DLOOK 0x0004L // Dialog definition DIAL1 DIALOG 0, 0, 240, 100 STYLE WS_SYSMENU DS_3DLOOK CAPTION "Dialog with the date and clock" FONT 8, "Arial" { CONTROL "", 1, "edit", ES_LEFT WS_CHILD WS_VISIBLE WS_BORDER WS_TABSTOP ES_READONLY, 100, 5, 130, 12 } ; The TIMER2.INC file ; Constants ; This message arrives when the window is closed WM_CLOSE equ 10h ; This message arrives when, the window is created WM_INITDIALOG equ 110h ; This message arrives when some event occurs to the window element WM_COMMAND equ 111h ; Message from the timer WM_TIMER equ 113h ; Message for sending text to the window element WM_SETTEXT equ 0Ch ; Prototypes of external procedures IFDEF MASM EXTERN SendDlgItemMessageA@20:NEAR EXTERN wsprintfA:NEAR EXTERN GetLocalTime@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN SetTimer@16:NEAR EXTERN KillTimer@8:NEAR ELSE EXTERN SendDlgItemMessageA:NEAR EXTERN _wsprintfA:NEAR EXTERN GetLocalTime:NEAR EXTERN ExitProcess:NEAR EXTERN GetModuleHandleA:NEAR EXTERN DialogBoxParamA:NEAR EXTERN EndDialog:NEAR EXTERN SetTimer:NEAR EXTERN KillTimer:NEAR SendDlgItemMessageA@20 = SendDlgltemMessageA wsprintfA = _wsprintfA GetLocalTime@4 = GetLocalTime ExitProcess@4 = ExitProcess GetModuleHandleA@4 = GetModuleHandleA DialogBoxParamA@20 = DialogBoxParamA EndDialog@8 = EndDialog SetTimer@16 = SetTimer KillTimer@8 = KillTimer ENDIF ; Structures ; Message structure MSGSTRUCT STRUC MSHWND DD ? MSMESSAGE DD ? MSWPARAM DD ? MSLPARAM DD ? MSTIME DD ? MSPT DD ? MSGSTRUCT ENDS ; Date-time data structure DAT STRUC year DW ? month DW ? dayweek DW ? day DW ? hour DW ? min DW ? sec DW ? msec DW ? DAT ENDS ; The TIMER2.ASM file .586P ; Flat memory model .MODEL FLAT, stdcall include timer2.inc ; INCLUDELIB directives for the linker IFDEF MASM ; For the LINK.EXE linker includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\gdi32.lib ELSE ; For the TLINK32.EXE linker includelib c:\tasm32\lib\import32.lib ENDIF ;----------------------------------------------- ; Data segment _DATA SEGMENT MSG MSGSTRUCT <?> HINST DD 0 ; Application descriptor PA DB "DIAL1", 0 TIM DB "Date %u/%u/%u Time %u:%u:%u", 0 STRCOPY DB 50 DUP(?) DATA DAT <0> _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get application descriptor PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ; Create a dialog PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX, -1 JNE KOL ; Error message KOL: ;--------------------------------- PUSH 0 CALL ExitProcess@4 ;--------------------------------- ; Window procedure ; Position of parameters in the stack ; [EBP+014H] ; LPARAM ; [EBP+10H] ; WAPARAM ; [EBP+0CH] ; MES ; [EBP+8] ; HWND WNDPROC PROC PUSH EBP MOV EBP, ESP PUSH EBX PUSH ESI PUSH EDI ;---------------- CMP DWORD PTR [EBP+0CH], WM_CLOSE JNE L1 ; Reaction to window closing ; Delete timer 1 PUSH 1 ; Timer identifier PUSH DWORD PTR [EBP+08H] CALL KillTimer@8 ; Delete timer 2 PUSH 2 ; Timer identifier PUSH DWORD PTR [EBP+08H] CALL KillTimer@8 ; Close the dialog PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH], WM_INITDIALOG JNE L2 ; Startup initialization takes place here ; Set timer 1 PUSH 0 ; Parameter = NULL PUSH 1000 ; 1-second interval PUSH 1 ; Timer identifier PUSH DWORD PTR [EBP+08H] CALL SetTimer@16 ; Set timer 2 PUSH OFFSET TIMPROC ; Parameter = NULL PUSH 500 ; 0.5-second interval PUSH 2 ; Timer identifier PUSH DWORD PTR [EBP+08H] CALL SetTimer@16 JMP FINISH L2: CMP DWORD PTR [EBP+0CH], WM_TIMER JNE FINISH ; Send the string to the window PUSH OFFSET STRCOPY PUSH 0 PUSH WM_SETTEXT PUSH 1 ; Element identifier PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 FINISH: POP EDI POP ESI POP EBX POP EBP MOV EAX, 0 RET 16 WNDPROC ENDP ;----------------------------- ; Timer procedure ; Position of parameters in the stack ; [EBP+014H] ; LPARAM --- Interval elapsed since Windows startup ; [EBP+10H] ; WAPARAM - Timer identifier ; [EBP+0CH] ; WM_TIMER ; [EBP+8] ; HWND TIMPROC PROC PUSH EBP MOV EBP, ESP ; Get local time PUSH OFFSET DATA CALL GetLocalTime@4 ; Get the string for data and time output MOVZX EAX, DATA.sec PUSH EAX MOVZX EAX, DATA.min PUSH EAX MOVZX EAX, DATA.hour PUSH EAX MOVZX EAX, DATA.year PUSH EAX MOVZX EAX, DATA.month PUSH EAX MOVZX EAX, DATA.day PUSH EAX PUSH OFFSET TIM PUSH OFFSET STRCOPY CALL wsprintfA ; Restore the stack ADD ESP, 32 POP EBP RET 16 TIMPROC ENDP _TEXT ENDS END START
To translate this program, proceed as follows for MASM32:
ML /c /coff /DMASM timer2.asm RC timer2.rc LINK /SUBSYSTEM:WINDOWS timer2.obj timer2.res
Proceed as follows for TASM32:
TASM32 /ml timer2.asm BRCC32 timer2.rc TLINK32 -aa timer2.obj,,,,,timer2.res
I would like to draw your attention to one useful function GetLocalTime . Information received using this function (see the DAT structure in Listing 14.2) can be easily used for various purposes, including screen output. Similarly, you can use the SetLocalTime function to set the current time. To get Greenwich Mean Time (GMT), use the GetSystemTime function; accordingly , to set the system time according to GMT, use the SetSystemTime function. The argument in all of these function is the previously mentioned structure (or, to be more precise, the pointer to that structure).
[i] To be more precise, there are three tasks because the dialog box operates independently.
| ||