Quote
.data
rect RECT <>
.code
.if uMsg==WM_DESTROY
.........................................
.elseif uMsg==WM_COMMAND
mov eax,msg.wParam
.if ax==ButtonId
invoke EnableWindow,hWnd,FALSE
invoke GetWindowRect,hWnd,ADDR rect
invoke SetTimer,hWnd,12,20,NULL
.endif
.elseif uMsg==WM_TIMER
invoke SetWindowPos,hWnd,HWND_TOPMOST,rect.left,rect.top,0,0,SWP_NOSIZE
sub rect.top,3
add rect.left,1
mov eax,rect.top
add eax,250
test eax,80000000h
jz OK
invoke DestroyWindow,hWnd
OK:
.else
invoke DefWindowProc,..................................
.endif
Few Questions .......
1. what does "test eax,80000000h" means in the above code?
2.in invoke SetTimer,hWnd,12,20,NULL,what does 12 represent the
in "win32.hlp" ---->>nIDEvent
Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
but I couldnt understand it properly "What is timer identifier is it an id for the timer or what ? "
3.can we use more then 1 SetTimer function in an application ?
Thanx.
The code:
test eax,80000000h
jz OK
is testing the sign bit (bit 31) of eax. The jump is taken if the sign bit is clear.
The code logic is:
IF rect.top - 3 + 250 < 0 THEN DestroyWindow
When hWnd is not null, the timer identifier is just a number that identifies the timer being created. Without seeing more of the code it would be impossible to know whether the value 12 is just some arbitrary number or if it has some particular function in the program logic.
You can use more than one timer. I've never tested this, but you can probably use a large number of timers.
MDSN: Timers (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/timers.asp)
Well, now I have tested it. Under Windows 2000 I was able to use 2000 timers OK, but with my 500MHz P3, as I increased the number of timers beyond a few hundred, the timer events would fall further and further behind the tick count. With 2000 timers the timers were firing at roughly 20% of the expected rate.
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include \masm32\include\masm32rt.inc
TIMERS EQU 2000
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
.data
hWnd dd 0
counters dd 2000 dup(0)
startTicks dd 0
maxCount dd 0
minCount dd -1
wcx WNDCLASSEX <>
msg MSG <>
szClassName db "timertestclass",0
szWindowName db "Timer Test",0
.code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
mov wcx.cbSize, sizeof WNDCLASSEX
mov wcx.style, CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
mov wcx.lpfnWndProc, OFFSET WndProc
mov wcx.cbClsExtra, NULL
mov wcx.cbWndExtra, NULL
mov wcx.hInstance, 0
invoke GetStockObject, WHITE_BRUSH
mov wcx.hbrBackground, eax
mov wcx.lpszMenuName, NULL
mov wcx.lpszClassName, OFFSET szClassName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wcx.hIcon, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wcx.hCursor, eax
mov wcx.hIconSm, 0
invoke RegisterClassEx, ADDR wcx
invoke CreateWindowEx, WS_EX_OVERLAPPEDWINDOW,
ADDR szClassName,
ADDR szWindowName,
WS_OVERLAPPEDWINDOW,
0, 0, 400, 300,
NULL, NULL,
0, NULL
mov hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke GetTickCount
mov startTicks, eax
mov ebx, 1
.REPEAT
invoke SetTimer, hWnd, ebx, 100, NULL
.IF (eax == 0)
MsgBox hWnd,"SetTimer", "Error", MB_OK or MB_ICONINFORMATION
jmp CleanUp
.ENDIF
add ebx, 1
.UNTIL (ebx > TIMERS)
MsgLoop:
invoke GetMessage, ADDR msg, NULL, 0, 0
cmp eax, 0
je CleanUp
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp MsgLoop
CleanUp:
invoke GetTickCount
sub eax, startTicks
MsgBox 0, ustr$(eax), "elapsed ticks", MB_OK
mov ebx, 1
.REPEAT
invoke KillTimer, hWnd, ebx
add ebx, 1
.UNTIL (ebx > TIMERS)
xor ebx, ebx
.REPEAT
mov eax, [counters+ebx*4]
.IF (eax > maxCount)
mov maxCount, eax
.ELSEIF (eax < minCount)
mov minCount, eax
.ENDIF
add ebx, 1
.UNTIL (ebx >= TIMERS)
MsgBox 0, ustr$(maxCount), "maxCount", MB_OK
MsgBox 0, ustr$(minCount), "minCount", MB_OK
invoke ExitProcess, msg.wParam
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
WndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
.IF uMsg == WM_TIMER
mov eax, OFFSET counters
mov ecx, wParam
sub ecx, 1
inc dword ptr[eax+ecx*4]
xor eax, eax
ret
.ELSEIF uMsg == WM_DESTROY
invoke PostQuitMessage, NULL
xor eax, eax
ret
.ENDIF
invoke DefWindowProc, hWin, uMsg, wParam, lParam
ret
WndProc endp
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
G`HOST,
add eax,250
test eax,80000000h
jz OK
invoke DestroyWindow,hWnd
OK:
Klutzy code there. The test eax,80000000h is unnessary. The previous add eax,250 sets the condition bits, so a JS OK or JNS OK instruction can be used afterwards. Nice handle you got by the way. Ratch
Making thousands of timers :eek is never good. Instead, you should use few 1..5, and have a dynamically-resizable array that holds the addresses of callback funcs/objects. I usually have no more than 1 timer, 20..50fps, and there I process callbacks, animation of GUI elements, drawing (if necessary). This proves to give best performance for my software.
QuoteMaking thousands of timers is never good.
I wasn't suggesting that it is good, or practical, or anything other than ridiculous. I was testing to see if you could, and if you did how the timers would behave.
Hey Thanx MichaelW ur reply was much help and the example u have given is quite useful for someone
new like me. I havent played with it yet, though
Quote from: MichaelW on November 06, 2005, 10:16:18 AM
When hWnd is not null, the timer identifier is just a number that identifies the timer being created. Without seeing more of the code it would be impossible to know whether the value 12 is just some arbitrary number or if it has some particular function in the program logic.
and Yes the value 12 doesnt seems to hold any significant meaning i suppose since the result was same when i changed it to diff. random nos. between 1 and 1000 .
So THanx again.
One more question :---
if we set 2 or more timers of same timeout value then what will be the value of "wParam" in "WM_TIMER" ?
Can you point out errors in the code below if any ?
Quote
.IF ax==ButtonBitId
invoke SetTimer,hWnd,1,1000,NULL
invoke SetTimer,hWnd,2,2000,NULL
.ENDIF
.ELSEIF uMsg==WM_TIMER
mov ecx,wParam
cmp ecx,2
je PASS
.IF ecx==1 ;First Condition
invoke SendMessage,hStartButton,BM_SETIMAGE,IMAGE_BITMAP,hStartButtonBitmap
invoke SendMessage,hStartButton,BM_SETIMAGE,TRUE,NULL
.ENDIF
jmp PASS2
PASS:
.IF ecx==2 ;Second Condition
invoke SendMessage,hStartButton,BM_SETIMAGE,IMAGE_BITMAP,hStartButtonBitmap2
invoke SendMessage,hStartButton,BM_SETIMAGE,TRUE,NULL
.ENDIF
PASS2:
OK here what i m trying to do is set 2 timers at 1000 and 2000 and the at every 2000 milisecond elapsed i want to execute second condition.
is there any other way of doing it ?
If uMsg == WM_TIMER then wParam contains the timer identifier.
I can't see any "errors", but the code (meaning the source code) is inefficient. Everything from mov ecx,wParam to PASS2: could be replaced with an .IF .ELSEIF .ELSE .ENDIF