PlanetSquires Forums

Support Forums => General Board => Topic started by: Martin Francom on January 10, 2010, 09:51:33 PM

Title: Timer Control
Post by: Martin Francom on January 10, 2010, 09:51:33 PM
I must be blind because I can't find any info on the Timer Control in either the
FF-Help nor in the FunctionLibrary.   Could someone show me how to do:

Kill  Timer      What is the Syntax for that command.

What's the command to re-set the Timer Interval?
Title: Re: Timer Control
Post by: Paul Squires on January 10, 2010, 10:59:11 PM
Try some of these results:

http://www.planetsquires.com/protect/forum/index.php?topic=1391.msg11674

http://www.planetsquires.com/protect/forum/index.php?topic=234.msg2837

Title: Re: Timer Control
Post by: Martin Francom on January 11, 2010, 03:27:53 AM
Thanks I will add this to my Function Library for when I need to look it up next time


' Stop timer
KillTimer hWndForm, IDC_FORM1_TIMER1

' Start timer. You are essentially creating a new timer' and specifying the new interval.
' 1000 represents the number of milliseconds of delay (1 second = 1000 milliseconds)

HWND_FORM1_TIMER1 = SetTimer( hWndForm, IDC_FORM1_TIMER1, 1000, ByVal %Null )   
   
' Change timer interval. You need to kill the original timer
' and create a new timer with the new interval. In this
' case the new interval is 2 seconds

KillTimer hWndForm, IDC_FORM1_TIMER1
HWND_FORM1_TIMER1 = SetTimer( hWndForm, IDC_FORM1_TIMER1, 2000, ByVal %Null )       
.
.
Title: Re: Timer Control
Post by: Martin Francom on January 11, 2010, 06:16:31 AM
I must be using this code wrong.  What I wanted to do is have the Timer fire one time and then stop.  This is the code I tried to use but appearently I am doing something wrong.  I have tried it both with and without "SetTimer".
I know I could use a global and set it after timer fires the first time then test for it and exit the timer function every time it fires after that.  But, I would much rarther turn the timer off.  Any ideas what I am doing wrong?


'--------------------------------------------------------------------------------
Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

    Initialize

    KillTimer hWndForm, IDC_FORM1_TIMER1
    HWND_FORM1_TIMER1 = SetTimer( hWndForm, IDC_FORM1_TIMER1, 0, ByVal %Null )
   
End Function



I guest what I realy want is a  "RunOnce" function    that is a function that would run one time right after the MainForm is created.
Title: Re: Timer Control
Post by: Rolf Brandt on January 11, 2010, 06:34:33 AM
Hi Marty,

what happens? Does it fire again?

I use in the WM_Timer event:
Initialize
KillTimer HWND_FRMABOUT, IDC_FRMABOUT_TIMER1

Like this it executes the Initialize function just once and then 'commits suicide'.

Title: Re: Timer Control
Post by: Paul Squires on January 11, 2010, 08:26:28 AM
if you only want your timer to fire once then I would use a STATIC variable and test it.


Static fOneTime As Long

If fOneTime = 1 Then Exit Function
fOneTime = 1

Initialize
KillTimer HWND_FRMABOUT, IDC_FRMABOUT_TIMER1


Title: Re: Timer Control
Post by: Rolf Brandt on January 11, 2010, 08:32:11 AM
Hi Paul,

would the timer still fire after a kill? Or is the static variable just for security in case the timer interval is very short?
Title: Re: Timer Control
Post by: Roger Garstang on January 11, 2010, 09:06:27 AM
It is possible for timers to fire when killed because their messages are posted to the message queue and there can be stray messages.  That is why Visual Studio wraps it and has an enable method that most likely uses the variable on it firing and if enable=false then it ignores it and doesn't pass the message along.
Title: Re: Timer Control
Post by: Rolf Brandt on January 11, 2010, 09:09:56 AM
I thought so. Thanks for the clarification, Roger.
Title: Re: Timer Control
Post by: Martin Francom on January 11, 2010, 02:40:09 PM
Quote from: Rolf Brandt on January 11, 2010, 08:32:11 AM
Hi Paul,

would the timer still fire after a kill? Or is the static variable just for security in case the timer interval is very short?
Yes, the timer continued to fire.
I will write a little test program to demonstrate what is happening.

It would be nice to have a "Run Once" property on the timer control.
Title: Re: Timer Control
Post by: Roger Garstang on January 11, 2010, 03:49:46 PM
Perhaps one of the Wait API functions like WaitForSingleObject would be more of what you are after? They are usually more accurate too since if under load the system may not give you the WM_TIMER message at exactly the time you want...especially if small time frames.  May want to put it in a thread though since it is blocking execution...unless that is what you want.  Could cause undesired graphical and response time issues in GUI if not in a thread and time to wait is long.
Title: Re: Timer Control
Post by: Martin Francom on January 11, 2010, 03:52:40 PM
Quote from: Roger Garstang on January 11, 2010, 03:49:46 PM
Perhaps one of the Wait API functions like WaitForSingleObject would be more of what you are after? They are usually more accurate too since if under load the system may not give you the WM_TIMER message at exactly the time you want...especially if small time frames.
Yes, Roger this might be what woulf work.    Can you to show me an example of how this would be called?
Title: Re: Timer Control
Post by: Martin Francom on January 11, 2010, 04:10:25 PM
Here's a test project the show the use of the timer control.
It appear from my testing the placing the KillTimer ansd SetTimer calls outside if the  WM_TIMER function they work as expected.

But when either or both KillTimer and SetTimer are inside the WM_TIMER function they
fail to work. Paul's idea to put a global test works to prevent the events from Wm_TIMER from re-running but it does not turn off the timer.   Here's a sample project that you can experiment with.   If you find a way to turn off the timer from within the WM_TIMER function, please post.  Thanks
Title: Re: Timer Control
Post by: Roger Garstang on January 11, 2010, 04:31:32 PM
Code works here with it never going above 5, but I have a fast machine, so painting the number in the text box wouldn't cause too much of a delay even at interval 0 for a stray WM_TIMER to sneak in.  Slower machines could have 1+ stray ones though.  As for your sample function, all you'd need to do in the example is put the check first and always kill the timer first thing so no other tasks run that could delay it.  Remember Windows is Multi-Tasking and it may run your app for a few milliseconds then something else too or it will paint the textbox then causes it to draw and in the mean time a WM_TIMER fired before your check and killtimer ran.


Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

   c = c + 1
   If c > 5 Then
      KillTimer HWND_FORM1, IDC_FORM1_TIMER1
   Else
      FF_TextBox_SetText (HWND_FORM1_LABEL1, Format$(c) ) ' Format$ eliminates the space in numeric values
   End If
End Function


This isn't much different than what Paul mentioned though.  With PB now supporting classes it could be useful for FF to have functionality like Visual Studio with a Timer object since it is making it look like such, but API calls are still needed to manipulate it.  Those with previous versions of PB would be left out though.  I guess until everyone goes to the latest it could be built in code and FF Functions that use some kind of Type Structure for Timers to store their value and enabled state.  Possibly even using the TimerProc version to call an internal FF function that then passes on to the WM_TIMER message if valid.  It would need to use one of the Threadsafe/Interlocked API calls to set the value either way though to eliminate all possibilities of stray WM_TIMERS since at any time another thread could take over the timeslice.
Title: Re: Timer Control
Post by: David Kenny on January 11, 2010, 06:42:09 PM
Marty, here is the code you posted up top:
'--------------------------------------------------------------------------------
Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

    Initialize

    KillTimer hWndForm, IDC_FORM1_TIMER1
    HWND_FORM1_TIMER1 = SetTimer( hWndForm, IDC_FORM1_TIMER1, 0, ByVal %Null )
   
End Function


If you set the interval property for Timer1 then it will wait that many milliseconds before firing your FORM1_TIMER1_WM_TIMER routine. If you don't set it (leaving it at zero), it will fire immediately.

Problem #1  When the FORM1_TIMER1_WM_TIMER routine you showed gets executed the first time, you are killing it (as you should in this case) - and then immediately restarting it with an interval of zero (you should not be doing this).  Calling SetTimer again (just to zero the interval) does set the interval to zero, but also starts the timer again.

Problem #2  Calling SetTimer fires the timer every "interval" milliseconds until you either change the interval with another call to SetTimer, or you kill the timer. In your example you call your initialize routine before you kill the timer.  If your routine takes more than "interval" milliseconds, the timer will fire again.  You should kill the timer first, then call your initialize routine.

Try:Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

    KillTimer hWndForm, IDC_FORM1_TIMER1     'This will only fire once unless restarted outside this routine.

    Initialize

   
End Function


David
Title: Re: Timer Control
Post by: Douglas McDonald on January 11, 2010, 10:51:24 PM
I must really be missing something. I have a timer control on the form. The very first thing I do is call StopTimer
Sub StopTimer(hWndForm As Dword)

KillTimer hWndForm, IDC_FRMDMM_TIMER1
MsgBox Str$(hWndForm) & "  " & "killtimer"
End Sub


Problem is it never kills the timer:
This event keep firing every 10 seconds like its setup in the properities:

Function FRMDMM_TIMER1_WM_TIMER ( _
                                hWndForm      As Dword, _  ' handle of Form
                                wTimerID      As Dword  _  ' the timer identifier
                                ) As Long
MsgBox "timer"
'Writedata
End Function


I was hoping to stop the timer on start up:
Function FRMDMM_WM_CREATE (hWndForm As Dword, _      ' handle of Form
                          ByVal UserData As Long _  ' optional user defined Long value
                          ) As Long

Local ret As Long
StopTimer hWndForm
ret = SetListHeader(hWndForm)
End Function


Then kill the timer:

Sub StopTimer(hWndForm As Dword)

KillTimer hWndForm, IDC_FRMDMM_TIMER1
MsgBox Str$(hWndForm) & "  " & "killtimer"
End Sub


Then Start the timer when I need it:

Sub Set_Timer_Int(hWndForm As Dword,tm As Long )
' Start timer. You are essentially creating a new timer
' and specifying the new interval.
' 1000 represents the number of milliseconds of delay (1 second = 1000 milliseconds)
KillTimer hWndForm, IDC_FRMDMM_TIMER1 'kill first
HWND_FRMDMM_TIMER1 = SetTimer( HWND_FRMDMM_TIMER1, IDC_FRMDMM_TIMER1, tm, ByVal %Null )       


End Sub


BTW I tried both  HWND_FRMDMM_TIMER1 and hWndForm. I'm very new to FireFly so I haven't figured out what the difference is in the two if any other than ones passed and the other is global

It looks to me that killtimer just doesn't work but it seems to work for others here if outside the timer event like In using it. What am I doing wrong

Also why isn't there any HELP for timers or any FF commands like for the other controls? Its no big deal but it should be consistent with the rest of the controls.

Thanks
Doug

One full day using FF3 and so far this is the only major issue
Title: Re: Timer Control
Post by: Paul Squires on January 12, 2010, 08:32:13 AM
Hi Doug,

In your case you will not be able to kill the timer in the WM_CREATE message handler because at that point the timer does not yet exist. Here is what the Firefly generated code looks like:


         ' The form is being created, but not yet shown. Allow the user to process their
         ' commands prior to showing the Form's controls.
         FLY_nResult = FORM1_WM_CREATE (hWndForm, @FLY_UserData)
             If FLY_nResult Then Function = FLY_nResult: Exit Function
         
         ' Create any user defined Timer controls
         SetTimer hWndForm, IDC_FORM1_TIMER1, 2000, ByVal %Null


As you can see, the call to create the timer occurs after the call to the function to handle the WM_CREATE message from the user. The question will then be, why not have the timer created before the WM_CREATE message handler? I could do that but then it creates another problem for those people who want to initialize their controls in WM_CREATE prior to any timer firing. Chicken and egg sort of problem.

A simple solution would be to create a global variable, say, GLOBAL fStopTimer As Long and set it to %TRUE in your WM_CREATE handler. Then in the WM_TIMER handler, test that variable and exit as approproate.

For example,


Global fStopTimer As Long

'--------------------------------------------------------------------------------
Function FORM1_WM_CREATE ( _
                         hWndForm As Dword, _      ' handle of Form
                         ByVal UserData As Long _  ' optional user defined Long value
                         ) As Long
   
   ' Stop the timer from firing. To re-enable the timer, set this
   ' variable to %FALSE.
   fStopTimer = %TRUE
   
End Function


'--------------------------------------------------------------------------------
Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

   If fStopTimer = %TRUE Then Exit Function
   
   Static nCount As Long
   Incr nCount
   FF_Control_SetText hWndForm, "Timer has fired again for the" & Str$(nCount) & " time."

End Function


'--------------------------------------------------------------------------------
Function FORM1_COMMAND1_BN_CLICKED ( _
                                   ControlIndex     As Long,  _  ' index in Control Array
                                   hWndForm         As Dword, _  ' handle of Form
                                   hWndControl      As Dword, _  ' handle of Control
                                   idButtonControl  As Long   _  ' identifier of button
                                   ) As Long

   ' Toggle starting and stopping the Timer
   fStopTimer = Not fStopTimer
   
End Function

Title: Re: Timer Control
Post by: Martin Francom on January 12, 2010, 02:04:37 PM
Paul,
   With this method the Timer Control continues to fire every interval.  If the interval is very short 100msec say will this cause any negative performance issues?   
   I would prefer to turn the Timer Control off so it stops.    Would it be possible to use post message to the message handler from the WM_TIMER function  that would then KillTimer?   
Title: Re: Timer Control
Post by: Paul Squires on January 12, 2010, 03:50:00 PM
Quote from: Marty Francom on January 12, 2010, 02:04:37 PM
Paul,
   With this method the Timer Control continues to fire every interval.  If the interval is very short 100msec say will this cause any negative performance issues?   
   I would prefer to turn the Timer Control off so it stops.    Would it be possible to use post message to the message handler from the WM_TIMER function  that would then KillTimer?   

I have read this thread a couple of times and I still can not figure what the problem is that you are having. There is no problem killing a timer from within WM_TIMER message. David Kenny offered very good advice in a previous post in this thread - kill the timer before running your time intensive task.

Other than that, you may want to test to ensure that the WM_TIMER is not being re-entered before the previous WM_TIMER has completed. Not sure if WM_TIMER is synchronous - ie. it waits until fully complete before processing the next WM_TIMER. Maybe they are all queued in the message loop - not sure. Nonetheless, if you have a very short time interval (say, 100 milliseconds) then you can do the following to ensure that it is no re-entrant.


Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long

   Static fProcessing As Long
   
   ' If we are already processing a timer message then
   ' don't allow us to start to process another.
   If fProcessing Then Exit Function
   
   ' Set the flag to prevent the timer message being re-entrant
   fProcessing = %TRUE
   
   
   ' Do you thing that you want to do.....
   
   
   ' Allow us to deal with the next timer message
   fProcessing = %FALSE
   
End Function


Quote
If the interval is very short 100msec say will this cause any negative performance issues?   
I doubt it.

Title: Re: Timer Control
Post by: John Montenigro on January 12, 2010, 04:07:46 PM
Paul,
I have a small app that I wanted to "time out" if not registered. Originally, I put a Timer control on the main form, and in WM_CREATE, I checked the registration. If OK, then I'd KILLTIMER. But I found that the timer would never die. So instead, I removed the Timer control from the form and then if the registration failed, I called SetTimer to create the desired timed exit... a reasonable workaround, I think.

But then I found out that FF3 had a feature that I wasn't using...

Whereas with FF2 I placed all my initialization code in the main form's WM_CREATE, with FF3, it appears that I should place all my initialization code in FF_AppStart.

Is that correct? And would that avoid the kill timer problem?

-John
Title: Re: Timer Control
Post by: David Kenny on January 12, 2010, 04:50:42 PM
John,

Can you reproduce that? Or do you have the old code you could post?  I have never had a problem killing a timer in FF.

David
Title: Re: Timer Control
Post by: Paul Squires on January 12, 2010, 05:24:00 PM
Quote from: John Montenigro on January 12, 2010, 04:07:46 PM
I put a Timer control on the main form, and in WM_CREATE, I checked the registration. If OK, then I'd KILLTIMER. But I found that the timer would never die. 
Refer to my reply above to Douglas McDonald. You can not kill a timer in the WM_CREATE because it does not exist at that point. Likewise, it does not exist in FF_AppStart.
Title: Re: Timer Control
Post by: Roger Garstang on January 12, 2010, 05:35:01 PM
Petzold in Programming Windows says:

"You can allocate a timer for your Windows program by calling the SetTimer function. SetTimer includes an unsigned integer argument specifying a time-out interval that can range (in theory) from 1 msec (millisecond) to 4,294,967,295 msec, which is nearly 50 days. The value indicates the rate at which Windows sends your program WM_TIMER messages. For instance, an interval of 1000 msec causes Windows to send your program a WM_TIMER message every second.

When your program is done using the timer, it calls the KillTimer function to stop the timer messages. You can program a "one-shot" timer by calling KillTimer during the processing of the WM_TIMER message. The KillTimer call purges the message queue of any pending WM_TIMER messages. Your program will never receive a stray WM_TIMER message following a KillTimer call."

Many people have said he was wrong though.  Sometime back I myself received a stray WM_TIMER after a KillTimer call, and MSDN says- "The KillTimer function does not remove WM_TIMER messages already posted to the message queue."  Not sure about the sync of the messages.  Multiple WM_TIMER messages are supposed to be consolidated into one, but you can get them quick if one is delayed by your app being busy right up to the point the next one fires you can get two in a row really quick.  I guess one quick test would be a delay/sleep/wait function in WM_TIMER with a global/static to save if entered pause the thread/function at least twice the interval then reset the global and see if another is sent while the global is set. Same could be done to test KillTimer then if determined that only one at a time is sent- Pause function and kill the timer then see if another gets sent that was in the queue.
Title: Re: Timer Control
Post by: Roger Garstang on January 12, 2010, 06:32:40 PM
Hmm, just made a form with only a 1sec(1000 interval) timer and:


'--------------------------------------------------------------------------------
Function FORM1_TIMER1_WM_TIMER ( _
                               hWndForm      As Dword, _  ' handle of Form
                               wTimerID      As Dword  _  ' the timer identifier
                               ) As Long
Static test As Dword
Local temp As Dword

If test = 1 Then MsgBox "Another WM_TIMER": Exit Function
Incr test
For temp = 1 To 2147483647:Next temp
FF_Control_SetText(HWND_FORM1, "1")
For temp = 1 To 2147483647:Next temp
FF_Control_SetText(HWND_FORM1, "2")
For temp = 1 To 2147483647:Next temp
FF_Control_SetText(HWND_FORM1, "3")
For temp = 1 To 2147483647:Next temp
FF_Control_SetText(HWND_FORM1, "4")
For temp = 1 To 2147483647:Next temp
FF_Control_SetText(HWND_FORM1, "5")

KillTimer(HWND_FORM1, IDC_FORM1_TIMER1)
End Function


Tried sleep too with both giving about the same results.  Never got a stray timer pulse after KillTimer.  Change KillTimer line to test= 2 and you can test for multiple Timer messages at the same time (Although since it only tests the first time anyway the KillTimer test does both).  Faster machines may need more For loops or larger numbers to loop through.  Toss in a FFDoEvents though and you never get back to the original function or do but with difficulty...I ran some tests with message boxes that were messy.  First test I ran was just one sleep for 20000 (20sec) and once it stopped sleeping I got like 20 message boxes at once then the app closed which to me would mean they are queued up and not sent as one WM_TIMER like MSDN states, but I ran it again and didn't get the same result...so??? Could vary by OS too.  Probably best to be on safe side though and maybe have a 3 state global where 0 is not in WM_TIMER, 1 is in WM_TIMER and 2 is timer killed (Or just make both 1 and have a 2 state) and if not 0 exit WM_TIMER function/message.  That way you cover all bases.
Title: Re: Timer Control
Post by: Martin Francom on January 12, 2010, 07:13:21 PM
Paul,
    I may be all "bassackwards" in my mind about this timer issue or maybe  I am not explaning the problem correctly.
   Attached here is a very simple example program that I think demonstartes what I am trying to say.
   When you run the program, the timer will initially be stopped.  Click the "Start Timer" button you will note that the Timer is firing (see count in Label )  Click "Interval 0" button and timer counts faster (as expected??  actually I would have thought that a zero setting would have disable the timer...my bad)   Now, click the button "Stop Timer"  and indeed the timer stops.
    Now note that in the  WM_Timer function is the statement   "KillTimer ....",   one would think that that statement would stop the timer but it doesn't.   The KillTimer statement appears to only work if executed outside of the WM_TIMER  function.
....Marty   
Title: Re: Timer Control
Post by: David Kenny on January 12, 2010, 07:59:30 PM
I just threw together an example project to test Timer's in FF.  I hope someone finds it useful.

It has two FF "Timer Controls".  Timer1 has a five second interval and Timer2 has a one second interval. Both start as soon as they are created (I believe Paul stated earlier that they are created at the same time as the other controls on the form).  I don't bother to kill these timers(see changes below to test Marty's last issue) or change their intervals.  You could kill one the first time it fires by inserting a call to KillTimer in the first line of the it's wm_timer routine. If you do change their interval, remember to save the new handle to the timer in the variable FF created for that control.

It has another timer created on the fly.  I let the user start and stop this timer as they wish.  You could easily do that with code also. (Douglas, this is how you could have handled your situation).

Marty got his post in as I was working on this post.  I modified Timer1 to stop after two iterations.

I kept it as simple as possible to make it easy to follow. 

David
Title: Re: Timer Control
Post by: Paul Squires on January 12, 2010, 08:07:09 PM
Quote from: Marty Francom on January 12, 2010, 07:13:21 PM
Paul,
    I may be all "bassackwards" in my mind about this timer issue or maybe  I am not explaning the problem correctly.
   Attached here is a very simple example program that I think demonstartes what I am trying to say.
   When you run the program, the timer will initially be stopped.  Click the "Start Timer" button you will note that the Timer is firing (see count in Label )  Click "Interval 0" button and timer counts faster (as expected??  actually I would have thought that a zero setting would have disable the timer...my bad)   Now, click the button "Stop Timer"  and indeed the timer stops.
    Now note that in the  WM_Timer function is the statement   "KillTimer ....",   one would think that that statement would stop the timer but it doesn't.   The KillTimer statement appears to only work if executed outside of the WM_TIMER  function.
....Marty   

Hi Marty,

I am getting completely different results with the EXE in your download versus the EXE that I create on my computer using your source. Your EXE continually increments the counter whereas mine stops after 5. See the attached archive containing my exe and Marty's. Do they run the same on your computer? (I am running Win 7).

Very strange. Marty, I assume that you compiled on WinXP, right?

(David, I haven't downloaded your project yet).
Title: Re: Timer Control
Post by: Rolf Brandt on January 12, 2010, 08:08:35 PM
Hi Marty,
when I ran the compiled program you sent it worke exactly as you described. After I compiled it here under XP it behaves properly. Setting the interval to zero disables the timer.

Win7 specific????
Title: Re: Timer Control
Post by: David Kenny on January 12, 2010, 08:11:05 PM
Marty,

I get the same results as Paul. The executable you provided runs as you described.  The one that I get when I compile your code works like you want it to.

Rolph,

I haven't found that setting the interval to zero disables the timer. Check out the example I posted above.
In the FORM1_COMMAND2_BN_CLICKED routine,
Change the:    Killtimer %Null, hMyTimer
To:                hMyTimer=Settimer (%Null, %Null, 0, Codeptr(MyTimerProc))

Run the program again and start and stop the timer.

David
Windows XP SP2
Title: Re: Timer Control
Post by: Paul Squires on January 12, 2010, 08:15:01 PM
Setting the timer interval should not disable the timer. According to http://msdn.microsoft.com/en-us/library/ms644906(VS.85).aspx using a value < USER_TIMER_MINIMUM then the value is set to USER_TIMER_MINIMUM (which I believe is 10 milliseconds - defined winuser.h).

Marty - do you have gremlins in your machine or something?  :)
Title: Re: Timer Control
Post by: Rolf Brandt on January 12, 2010, 08:44:45 PM
Very interesting, I tried Martys example on two different computers with different results.
On my netbook (Atom processor) the timer won't stop after 5, it continues to run until I set interval to 0 or KillTimer.
On my desktop (Athlon) it works as Marty describes.

I guess the netbook is to slow, it fires the timer before it was able to update the label.

(Or maybe Gremlins after all...)
Title: Re: Timer Control
Post by: Rolf Brandt on January 12, 2010, 09:04:35 PM
QuoteNow, click the button "Stop Timer"  and indeed the timer stops.
    Now note that in the  WM_Timer function is the statement   "KillTimer ....",   one would think that that statement would stop the timer but it doesn't.   The KillTimer statement appears to only work if executed outside of the WM_TIMER  function.

KillTimer really does kill the timer and not only stop it.
But the timer id is reusable, and if you use SetTimer with the same id then a new timer will be created.
Title: Re: Timer Control
Post by: Martin Francom on January 12, 2010, 11:21:27 PM
Quote
Hi Marty,

I am getting completely different results with the EXE in your download versus the EXE that I create on my computer using your source. Your EXE continually increments the counter whereas mine stops after 5. See the attached archive containing my exe and Marty's. Do they run the same on your computer? (I am running Win 7).

Very strange. Marty, I assume that you compiled on WinXP, right?

(David, I haven't downloaded your project yet).


Paul,
    I am using Win-7  (upgrade from Vista)
...Marty
Title: Re: Timer Control
Post by: Martin Francom on January 12, 2010, 11:27:41 PM
Quote from: TechSupport on January 12, 2010, 08:15:01 PM
Setting the timer interval should not disable the timer. According to http://msdn.microsoft.com/en-us/library/ms644906(VS.85).aspx using a value < USER_TIMER_MINIMUM then the value is set to USER_TIMER_MINIMUM (which I believe is 10 milliseconds - defined winuser.h).

Marty - do you have gremlins in your machine or something?  :)


Paul,
   I am beginning to think that I do.
Sometime when you have nothing better to
do,  maybe you "Remote Connect" to my
computer.   
Title: Re: Timer Control
Post by: Martin Francom on January 13, 2010, 12:03:01 AM
Paul,
   I can now recreate/fix the problem on demand.  Here's a screen print of the error message.  Does anything about this message make any sense to you?
   I am starting to believe that the wierd problems I have been experiencing of late are all related to Windows-7.   Thinking back these problems began after I had a Windows-7 upgrade. (Upgrade from Vista)
   Would a few of you good folks that are running Windows-7  be so kind as to download and compile the "TimerExample" project that I attached above.  And, see if you get the same problem I am seeing.

   Ok, what do I have to do to make the error message below go away?   Well, all I have to do is to change the caption of the from from "Timer Example"   to "Timr Example"   and the problem goes away.   To get the problem again all I need to do is change the caption back to "Timer Example".      Weird or what!
Title: Re: Timer Control
Post by: Cho Sing Kum on January 13, 2010, 07:16:18 AM
Hi Marty,

I downloaded your TimerExample.zip file. This is what I found:

Your Form1.frm has a timestamped 12Jan2010 2:40pm.
Your compiled TimerExample.exe has a timestamp of 11Jan2010 10:38am, which is more than 24 hours before Form1.frm was last saved.

I can only deduce that the compiled exe CANNOT be from the Form1.frm you provided in the zip but from an earlier one that has very different source code.

Compiling a fresh exe from the Form1.frm you provided, the exe runs correctly as per the source code.

From the error message screen shot, you have your "working" files in "C:\PBWIN90\..."

WinVista and Win7 are very fuzzy where you want to write exe files (you do this when you are compiling). I do not know whether this may be the problem.

Try moving all your projects to your "My Documents". This is the recomemnded location for your "working" files, including when compiling exe. Recommended by Microsoft.

All other location in the system drive C:, including C:\PBWIN90\... and C:\Program Files\..., are NOT recomended for your "working" files. Although WinVista and Win7 has Virtualiztion, it is better to avoid the need for WinVista and Win7 to put your files into Virtualiztion folder.

Notice that, even before WinVista and in WinXP at least, when you open Windows Explorer it always default to "My Documents" ?

I do not know whether this is the problem but I think can try to remove potential problems from "unexpected direction".
Title: Re: Timer Control
Post by: Martin Francom on January 13, 2010, 03:45:56 PM
      I know what the problem with Timer is.  And it's not the  TIMER  control.  It turns out to be my mistake.  I didn't understand how FF and the Snippets worked.   I was using snippets to store my notes and then when needed to I would use "Cut & Paste"  to add stuff from MySnippets to the code I was working on.   
     I didn't realize that FF would automatically add those snippets to the CodeGen file.  Well, I had a snippet named  "Timer"  which contain my notes about using the Timer Control.  This snippet was not a true function just some notes.  Appearently, when FF builds the CodeGen files it looks for the file name of the snippets you have in your Function Library and if that name is present in the FF project then  FF will add those functions to the end of the  CodeGen_---_Utility.INC  file.   (Paul, do I have that understanding correct?)
    Because my snippet was not a true function the PB compiler would stop at a statement that was not compilable and generate the error message I was recieving. 
    What made it more confusing for me was that the Key word (Timer) I was using was in a the Caption of the form.  Once I remove the word "Timer" from the Caption of FORM1 that snippet was no longer added to the CodeGen file and the program compiled correctly.   
    I appologize for running you guys on a wild goose chase and want to thank you for your help.

I now know better how the Function Library works.  This is what I learned:
  1) do not use snippets for storing notes unless you preface the line with a comment mark '
  2) make sure that all snippets are compilable
  3) don't use snippet names in captions as FF will add those snippets to the project

Is there anything else I need to be aware of concerning the Function Library and snippets?
Title: Re: Timer Control
Post by: Martin Francom on January 13, 2010, 04:15:53 PM
Rolf,
   Thanks for emailing me.  The easiest and simplest way to observe the behavoir of FF adding a Function Library Function to the CodeGen_--_Utility.INC  file when the function name appears in the Caption is to do the following:

    1) create a new FF project (don't add any controls to Form1)
    2) change the CAPTION of Form1 to  File\FF_FilePath
    3) compile the program
    4) go to the Release directory and  view the CodeGen_--_Utility.INC file
       You will find the function  FF_FilePath has been added

    5) now change the Caption of the FORM1 to something else and compile the
       program and look at the CodeGen_--_Utility file.  Now, you will note that
       the function  FF_FilePath was not added.   


   
       
Title: Re: Timer Control
Post by: Jean-pierre Leroy on January 13, 2010, 05:22:40 PM
Marty,

You're right I made the test and have exactly the same behavior as you.

I'm pretty sure Paul will find an easy fix for that.

Jean-Pierre
Title: Re: Timer Control
Post by: Rolf Brandt on January 13, 2010, 05:49:33 PM
That is interesting...
Title: Re: Timer Control
Post by: Paul Squires on January 13, 2010, 09:47:44 PM
Very interesting indeed. Looks like there is an oversight in my built-in parser. It must not be skipping the string literals during the parse to determine which FireFly Functions and user defined functions to include in the final code.

Should be "easy" to fix. I will report back.
Title: Re: Timer Control
Post by: Paul Squires on January 13, 2010, 10:12:07 PM
Okay, I have now modified the parser and any text inside a double quoted string literal is now blanked out prior to being examined for any FireFly Functions. It all appears to be working correctly now.

The fix will be in v3.07.
Title: Re: Timer Control
Post by: Martin Francom on January 14, 2010, 12:55:22 AM
Paul,
   Even code that is behind a comment will cause the problem, such as:


         Function FORM1_COMMAND1_BN_CLICKED ( _
                                   ControlIndex     As Long,  _  ' index in Control Array
                                   hWndForm         As Dword, _  ' handle of Form
                                   hWndControl      As Dword, _  ' handle of Control
                                   idButtonControl  As Long   _  ' identifier of button
                                   ) As Long


   '  "File\FF_FilePath"


End Function


You will want to account for that situation also.
Title: Re: Timer Control
Post by: John Montenigro on January 14, 2010, 12:10:48 PM
Quote from: John Montenigro on January 12, 2010, 04:07:46 PM
Paul,
I have a small app that I wanted to "time out" if not registered. Originally, I put a Timer control on the main form, and in WM_CREATE, I checked the registration. If OK, then I'd KILLTIMER. But I found that the timer would never die. So instead, I removed the Timer control from the form and then if the registration failed, I called SetTimer to create the desired timed exit... a reasonable workaround, I think.

But then I found out that FF3 had a feature that I wasn't using...

Whereas with FF2 I placed all my initialization code in the main form's WM_CREATE, with FF3, it appears that I should place all my initialization code in FF_AppStart.

Is that correct? And would that avoid the kill timer problem?

-John

I want to make a correction to my earlier post, lest it misguide the unsuspecting...

Where I had mentioned "FF_AppStart", I actually meant "FF_WinMain".

The FF_AppStart module is not a Function, so executable code won't compile.

Rather, I put my RegCheck function in the FF_WinMain module, below the FF_WINMAIN function, and I inserted a call to RegCheck in the FF_WINMAIN function. Works fine.

This totally avoids my FF2 habit of putting initialization code in the frmMAIN_WM_CREATE function, and so far, seems to avoid KillTimer problems... (and as Paul pointed out to several of us, the Timer doesn't yet exist in _WM_CREATE, so trying to kill it there has no effect...)

Sorry if I confused anyone...
-JohnM.