Announcement

Collapse
No announcement yet.

killtimer edicate...

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Eric Pearson
    replied
    Here is a test program that always fails if an equate is used, and always works if the return value of SetTimer (ghTimer) is used. After 5 beeps the program will try to stop the timer using %IDT_TIMER1, and it won't work. (According to Win32.HLP the SetTimer function ignores the value if hWnd is zero, so this is to be expected.) After 5 more beeps it will try to stop the timer using the "pseudo-handle" that was returned by SetTimer, and the beeping will stop.

    Code:
    #COMPILE EXE  
    #REGISTER NONE
    #DEBUG ERROR ON
    #DIM ALL
    #INCLUDE "WIN32API.INC"
     
    %IDT_TIMER1 = 100
     
    FUNCTION TimerProc(BYVAL hDlg AS DWORD, BYVAL wMsg AS DWORD, _
                       BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) PRIVATE AS LONG
     
            DIM ghTimer AS GLOBAL LONG      
            DIM slTicks AS STATIC LONG
     
            BEEP
     
            INCR slTicks
            IF slTicks = 5 THEN
                    KillTimer 0, %IDT_TIMER1 'THIS WILL FAIL (5 BEEPS)
            ELSEIF slTicks = 10 THEN
                    KillTimer 0, ghTimer     'THIS WILL WORK (10 BEEPS)
            END IF
     
    END FUNCTION
     
    FUNCTION PBMain AS LONG
            DIM ghTimer AS GLOBAL LONG      
            ghTimer = SetTimer(BYVAL 0, %IDT_TIMER1, 1000, CODEPTR(TimerProc))
            MSGBOX "Click Ok to Exit"
    END FUNCTION
    Note that this example uses a window-less timer, but the same technique can be used for window-based timers. (If this was a real program I'd eliminate the GLOBALs, but you get the idea.)

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited June 07, 2000).]

    Leave a comment:


  • Eric Pearson
    replied
    > Local sTimer As Long

    You need to use a STATIC variable, not a LOCAL, so that it holds its value. Or a GLOBAL would work just as well, if you need the timer "handle" in another function.

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited June 07, 2000).]

    Leave a comment:


  • Scott Turchin
    replied
    Nope, that fails, but this works:

    Code:
    CallBack Function SplashProc() As Long
    Local sTimer As Long
    
        MousePtr 11 'BUSY
    
        Select Case CbMsg
    
        Case %WM_INITDIALOG
            sTimer = SetTimer(sDlg, %IDT_TIMER1,  3500, ByVal %NULL)
            If IsFalse sTimer Then Dialog End sDlg,0
    
        Case %WM_DESTROY
             KillTimer sDlg,  %IDT_TIMER1
    
        Case %WM_TIMER
            Select Case CbWparam
              Case %IDT_TIMER1
                 MousePtr 0
                 Dialog End sDlg, 1
            End Select
    
        End Select
     End Function

    ------------------
    Scott
    mailto:[email protected][email protected]</A>
    MCSE, MCP+Internet

    Leave a comment:


  • Scott Turchin
    replied
    So let me get this correct, it's a good point you made..

    Code:
     
    sTimer = SetTimer(sDlg, %IDT_TIMER1, 3500, ByVal %NULL)
    
    And then...
    
        Case %WM_TIMER
            Select Case CbWparam
              Case sTimer
                 MousePtr 0
                 Dialog End sDlg, 1
            End Select

    ------------------
    Scott
    mailto:[email protected][email protected]</A>
    MCSE, MCP+Internet

    Leave a comment:


  • Semen Matusovski
    replied
    [Deleted]

    [This message has been edited by Semen Matusovski (edited June 07, 2000).]

    Leave a comment:


  • Eric Pearson
    replied
    Scott --

    I went back to my old notes about this, and here is what I found out...

    If you use a window-based timer, then theoretically the return value of the SetTimer function will always be the %IDT_TIMER1 value that you specify. But a couple-three years ago I was having a problem reliably stopping a timer, and I read in a newsgroup message that under certain circumstances it was necessary to use the return value instead of the %IDT_ value that you specify, even with a window-based timer. I have some vague memories about the reason, but I didn't put them in my notes and I don't want to muddy the waters. Sorry I can't be more specific -- I'll look for a hard reference when I get some time -- but all I know for sure is that after I started using the return value, the problem was never reported again. Who knows? Maybe I'm just perpetuating an old wive's tale.

    More recently (just this week!) I found out that if you use a window-less timer then the %IDT_TIMER1 value is ignored (per Win32.HLP) so you have no choice but to use the return value of SetTimer.

    So my philosophy is that if the return value of the SetTimer API function works reliably in all cases, and the SetTimer entry in Win32.HLP says that you're supposed to use it, use it! IMO a static LONG variable is a small price to pay for reliability.

    -- Eric


    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>

    Leave a comment:


  • Scott Turchin
    replied

    sTimer = SetTimer(sDlg, %IDT_TIMER1, 3500, ByVal %NULL)

    At this point the timer is still going to use %IDT_TIMER1 so sTimer would only return whether thetimer was successful in setting, no?


    Scott

    ------------------
    Scott
    mailto:[email protected][email protected]</A>
    MCSE, MCP+Internet

    Leave a comment:


  • Eric Pearson
    replied
    I forgot to mention that a truly industrial-strength application should check the return value of the SetTimer function for another reason. If the API is unable to create a timer, the return value will be zero. It's a relatively small additional step to save the return value, and use it for KillTimer and to sort out multiple timer messages in WM_TIMER code, instead of using an equate.

    The Win32.HLP examples do show the use of equates instead of variables, but the SetTimer description is pretty clear about using the function's return value. As usual, you have to read between the lines.

    -- Eric


    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>

    Leave a comment:


  • Eric Pearson
    replied
    Scott --

    That works because under most circumstances the return value of the SetTimer API is simply an "echo" of the numeric identifier that you give it, like %IDT_TIMER1. The API usually says "sure, I'll use that number" and hands it back to you. But that is not always the case, so the 100% safe method is to use the return value.

    (BTW, for lurkers, the value of %IDT_TIMER must be nonzero.)

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited June 07, 2000).]

    Leave a comment:


  • Scott Turchin
    replied
    This is my preferred method:
    Code:
        Case %WM_INITDIALOG
            SetTimer sDlg, %IDT_TIMER1,  3500, ByVal %NULL
    
    
        Case %WM_DESTROY
             KillTimer sDlg,  %IDT_TIMER1
    
    
        Case %WM_TIMER
            Select Case CbWparam
              Case %IDT_TIMER1
                 MousePtr 0
                 Dialog End sDlg, 1
            End Select

    ------------------
    Scott
    mailto:[email protected][email protected]</A>
    MCSE, MCP+Internet

    Leave a comment:


  • Eric Pearson
    replied
    Mark --

    The value that KillTimer needs is the return value of SetTimer, which you are currently not saving.

    Like this:

    Code:
    lTimerID = SetTimer(hWnd,etc)
    'then later... 
    CALL KillTimer(hWnd,lTimerID)
    BTW the CALL keyword is optional, so you can just to this...
    Code:
    KillTimer hWnd,lTimerID
    (I've never used the "string identifier" so somebody else will have to jump in.)

    -- Eric

    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>



    [This message has been edited by Eric Pearson (edited June 07, 2000).]

    Leave a comment:


  • Guest's Avatar
    Guest started a topic killtimer edicate...

    killtimer edicate...

    hello,

    I was wondering if it's proper to do the following...

    Code:
    call settimer(cbhndl, %IDTIMER, 1000, %NULL)
    call killtimer(cbhndl, %IDTIMER)
    The MSDN states the following...

    "If the function succeeds, the return value is an integer identifying the new timer. An application can pass this value, or the string identifier, if it exists, to the KillTimer function to destroy the timer."

    What string identifier? would this be %IDTIMER in the case above?



    -------------
    Cheers
Working...
X