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.
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 ?
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...
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.
maybe use smaller (positive) ID's :P
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
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
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
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