News:

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

SetTimer callback problem

Started by jj2007, September 12, 2011, 02:41:51 PM

Previous topic - Next topic

jj2007

I use invoke SetTimer, hWnd, MyID, 1000, CbTimer in a Win GUI app, mostly successfully.

The problem is that I discovered events in CbTimer that shouldn't be there. My IDs are all in the -100 ... -127 range, but I get events like e.g. +31546 ... and different, decreasing, numbers for each app run, as if a global system-wide counter was involved.

Any ideas who could play foul here? The app is too large to post here, and I can't reproduce it with a simpler window. All SetTimer invokes look fine.

CbTimer proc hwnd:DWORD, uMsg:DWORD, PMidEvent:DWORD, dwTime:DWORD
LOCAL gpCbT, hEdit, hOK, hCancel, rc:RECT, rcp:RECT, wpf:WINDOWPLACEMENT
LOCAL txrg:TEXTRANGE
LOCAL chrg:CHARRANGE
LOCAL LocBuf[MAX_PATH*2]:BYTE
  pushad ; save all - we are inside a timer...
  mov ebx, PMidEvent
  .if sdword ptr ebx>0
MsgBox 0, str$(ebx), 0, MB_OK
  .endif
...
  popad
ret
CbTimer endp


Among the 14 SetTimer calls, the marked one seems responsible, with TimerActivate = -120 (but same result for other values):

CASE WM_ACTIVATE
.if ActFlag==0
invoke SetTimer, hWnd, TimerActivate, 200, CbTimer  ; <<<< the culprit
invoke SetTimer, hWnd, TimerPipeClose, 20, CbTimer
.endif


SetTimer happens once, and the problem starts directly after.

dedndave

the Community Content section for TimerProc Callback may be of interest

http://msdn.microsoft.com/en-us/library/ms644907%28v=VS.85%29.aspx

is there some reason for not filtering them out ?

jj2007

Quote from: dedndave on September 12, 2011, 03:27:14 PM
the Community Content section for TimerProc Callback may be of interest

http://msdn.microsoft.com/en-us/library/ms644907%28v=VS.85%29.aspx

is there some reason for not filtering them out ?

The error handling issue is interesting, but it seems not to be the problem, as I get the wrong ID right on top of the CB. And yes I could filter them out, but it appears that the right ID is not working either. Very strange...

MichaelW

The third parameter is the timer ID as a 32 or 64-bit unsigned integer, not a pointer. The UINT_PTR is specified to ensure that the size will match the size of a pointer.

http://msdn.microsoft.com/en-us/library/aa383751(v=VS.85).aspx#UINT_PTR

From BaseTsd.h:

// The INT_PTR is guaranteed to be the same size as a pointer.  Its
// size with change with pointer size (32/64).  It should be used
// anywhere that a pointer is cast to an integer type. UINT_PTR is
// the unsigned variation.

eschew obfuscation

dedndave

maybe use smaller (positive) ID's   :P

jj2007

The IDs are defined as DWORD, so that could not be the problem...

But I found it: The bloody WM_ACTIVATE message is triggered the first time with a zero handle!!
So invoke SetTimer, hWnd, MyID, 200, CbTimer was in reality invoke SetTimer, 0, MyID, 200, CbTimer... and that explains the "global" countdown.

Thanks, Michael and Dave :thumbu

Anyway, I learnt something important:
Quote; Create the main application window
   invoke CreateWindowEx, ....
   mov hWnd, eax  ; set global handle

QuoteWndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
...
   SWITCH uMsg
   CASE WM_CREATE
      m2m hWnd, hWin      ; global window handle must be set here, not in WinMain

:bg

dedndave

i have been doing that for most windows
it seems to be the earliest time that the window handle is known
but, i was doing it so i knew WM_CREATE had executed - lol

qWord

Quote from: jj2007 on September 12, 2011, 06:00:47 PMAnyway, I learnt something important:
QuoteWndProc proc hWin:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
...
      m2m hWnd, hWin      ; global window handle must be set here, not in WinMain
or better:
Quoteinvoke SetTimer, hWin, MyID, 200, CbTimer
:bg
FPU in a trice: SmplMath
It's that simple!

jj2007

Quote from: qWord on September 12, 2011, 10:02:31 PM
or better:
Quoteinvoke SetTimer, hWin, MyID, 200, CbTimer
:bg

Or even shorter:
SetMyTimerP proc TheID, TheDelay
  invoke SetTimer, hWnd, TheID, TheDelay, CbTimer
  ret
SetMyTimerP endp

With a WndProc of already 1,000 lines and 14 timers, it is convenient to have an extra proc that handles both WndProc and non-WndProc calls. But for a smaller app, your idea is absolutely right, of course :U