| ||
The first example to consider is the simplest example of a timer. The timer counts 10 ticks , then closes the window and displays the message box informing the user about the program termination. This program illustrates timer organization on the basis of the window function.
// The TIMER.RC file // Constants #define WS_SYSMENU 0x00080000L #define WS_MINIMIZEBOX 0x00020000L #define WS_MAXIMIZEBOX 0x00010000L // Style - Button #define BS_PUSHBUTTON 0x00000000L // The button must be visible #define WS_VISIBLE 0x10000000L // Center the button label #define BS_CENTER 0x00000300L // Button style #define WS_CHILD 0x40000000L // The possibility of focusing the element // using the <TAB> key #define WS_TABSTOP 0x00010000L #define DS_3DLOOK 0x0004L // Dialog box definition DIAL1 DIALOG 0, 0, 240, 120 STYLE WS_SYSMENU WS_MINIMIZEBOX WS_MAXIMIZEBOX DS_3DLOOK CAPTION "An example of dialog with timer" FONT 8, "Arial" { // Button, identifier 5 CONTROL "Exit", 5, "button", BS_PUSHBUTTON I BS_CENTER WS_CHILD WS_VISIBLE WS_TABSTOP, 180, 76, 50, 14 } ; The TIMER.INC file ; Constants ; This message arrives when the window is closed WM_CLOSE equ 10h WM_INITDIALOG equ 110h WM_COMMAND equ 111n WM_TIMER equ 113h ; Prototypes of external procedures IFDEF MASM EXTERN ReleaseDC@8:NEAR EXTERN GetDC@4:NEAR EXTERN TextOutA@20:NEAR EXTERN MessageBoxA@16:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN SendMessageA@16:NEAR EXTERN SetTimer@16:NEAR EXTERN KillTimer@8:NEAR ELSE EXTERN ReleaseDC:NEAR EXTERN GetDC:NEAR EXTERN TextOutA:NEAR EXTERN MessageBoxA:NEAR EXTERN ExitProcess:NEAR EXTERN GetModuleHandleA:NEAR EXTERN DialogBoxParamA:NEAR EXTERN EndDialog:NEAR EXTERN SendMessageA:NEAR EXTERN SetTimer:NEAR EXTERN KillTimer:NEAR ReleaseDC@8 = ReleaseDC GetDC@4 = GetDC TextOutA@20 = TextOutA MessageBoxA@16 = MessageBoxA ExitProcess@4 = ExitProcess GetModuleHandleA@4 = GetModuleHandleA DialogBoxParamA@20 = DialogBoxParamA EndDialog@8 = EndDialog SendMessageA@16 = SendMessageA 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 ; The TIMER.ASM file .586P ; Flat memory model .MODEL FLAT, stdcall include timer.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 COUNT DD 0 TEXT DB 0 CAP DB 'Message, 0 MES DB 'Exit by. timer', 0 _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get application descriptor PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ;-------------------------------- PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX, -1 JNE KOL 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 ; The reaction to the window closing L3: ; Delete the timer PUSH 1 ; 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 L5 ; The initialization takes place ; Set the timer PUSH 0 ; Parameter = NULL PUSH 1000 ; Interval of 1 second PUSH 1 ; Timer identifier PUSH DWORD PTR [EBP+08H] CALL SetTimer@16 JMP FINISH L5: CMP DWORD PTR [EBP+0CH], WM_COMMAND JNE L2 ; Exit button? CMP WORD PTR [EBP+10H], 5 JNE FINISH JMP L3 L2: CMP DWORD PTR [EBP+0CH], WM_TIMER JNE FINISH ; Time to exit? CMP COUNT, 9 ; Exit without notification JA L3 ; Exit through the message JE L4 ; The timer message has arrived ; Prepare the text MOV EAX, COUNT ADD EAX, 49 MOV TEXT, AL ; Get the context PUSH DWORD PTR [EBP+08H] CALL GetDC@4 ; Save the context PUSH EAX ; Display the counter value PUSH 1 PUSH OFFSET TEXT PUSH 10 PUSH 10 PUSH EAX CALL TextOutA@20 ; Delete the context POP EAX PUSH EAX PUSH DWORD PTR [EBP+08H] CALL ReleaseDC@8 ; Increase the counter INC COUNT JMP FINISH L4: INC COUNT ; The message about exiting from the timer PUSH 0 PUSH OFFSET CAP PUSH OFFSET MES PUSH DWORD PTR [EBP+08H] ; window descriptor CALL MessageBoxA@16 JMP L3 FINISH: POP EDI POP ESI POP EBX POP EBP MOV EAX, 0 RET 16 WNDPROC ENDP ;------------------------------------------ _TEXT ENDS END START
Now, let me comment on the program provided in Listing 14.1. Timer organization here is simple and obvious. The only thing that can cause some difficulties is leaving the MessageBox and simultaneously closing the dialog box. Nevertheless, here everything is simple: the message is displayed when COUNT=9 , and when the next message arrives, COUNT is greater than 9, and the branch that closes the dialog is executed.
To translate this program, issue the following commands using MASM32:
ML /c /coff /DMASM timer.asm RC timer.re LINK /SUBSYSTEM:WINDOWS timer.obj timer.res
Issue the following commands using TASM32:
TASM32 /ml timer.asm BRCC32 timer.re TLINK32 -aa timer.obj,,,,,timer.res
| ||