News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

3 Questions

Started by G`HOST, November 06, 2005, 08:03:49 AM

Previous topic - Next topic

G`HOST

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.

MichaelW

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
eschew obfuscation

MichaelW

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

eschew obfuscation

Ratch

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

u

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.
Please use a smaller graphic in your signature.

MichaelW

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.


eschew obfuscation

G`HOST

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.

G`HOST

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 ?

MichaelW

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

eschew obfuscation