Page 1 of 1
Just to add a simple clock [SOLVED]
Posted: Wed Feb 07, 2007 6:12 am
by Rook Zimbabwe
I know this is possible... it just seems hard because I am missing something of the structure I need to know about...
How can I add a simple clock to my Application... It seems that the clock I have will not update unless the mouse is moving...
I can add the time update as a function... If I do this will the computer update the clock once each event loop of the REPEAT / UNTIL process?
EDIT:: NO it will not
Posted: Wed Feb 07, 2007 9:17 am
by r_hyde
I think you need to change your event loop to WaitWindowEvent(1)
Posted: Wed Feb 07, 2007 10:35 am
by Kale
Create a procedure to handle the drawing of your clock:
Code: Select all
Procedure UpdateTime()
Now.l = Date()
SetGadgetText(#TEXT_GADGET, FormatDate("%hh:%ii:%ss", Now))
EndProcedure
then create a timer (outside of your main loop) to call this procedure once every second to update the time display. (Uses WinAPI)
Code: Select all
SetTimer_(WindowID(#WINDOW), 0, 1000, @UpdateTime())
(Untested (written from memory))
Posted: Wed Feb 07, 2007 5:49 pm
by Joakim Christiansen
r_hyde wrote:I think you need to change your event loop to WaitWindowEvent(1)
You're right, but I think a bigger delay may be appropriate, 100 maybe.
Actually a clock only need to be updated once a second so actually 1000 could be enough.
Hey, nice trick Kale, guess I'll start using those timers!
Posted: Wed Feb 07, 2007 6:03 pm
by Kaeru Gaman
one thing to remember:
SetGadgetText and the other gadget-command create an event.
this means, you must only update the clock-gadget, when the
WaitWindowEvent timer is over, when no other event occured.
snippet:
Code: Select all
Repeat
EventID = WaitWindowEvent(500)
If EventID = 0
SetGadgetText( ClockGadget, Clock$ )
EndIf
;.....
Until EXIT
Clock& is the string you'll get from Date or whereever....
Posted: Wed Feb 07, 2007 9:30 pm
by Rook Zimbabwe
I think you are all correct. I had a function created exactly that way to update the clock... I was still not aware I could set the timeout to 500 (check every 1/2 second)

Posted: Thu Feb 08, 2007 10:06 am
by Baldrick
A bit late, but here is a sample I have cut down from 1 of my recent projects. ( It is using the same timer function as suggested by Kale )
It is using a shared structure which gives me hr, min, sec, etc values as bytes to allow easy access from the main loop to allow triggering of other parts of my program by simply passing these values into other control procedures.
This way avoids need to have any timeout on your waitwindowevent()
Code: Select all
Structure tTimeInfo
tDisplay.s
tHr.b
tHr12f.b
tMin.b
tSec.b
tMeridian.b
tUpdate.b
EndStructure
Time.tTimeInfo
Procedure Clock()
Shared Time.tTimeInfo
Time$=FormatDate("%hh%ii%ss", Date())
Time\tHr=Val(Left(Time$,2))
Time\tMin=Val(Mid(Time$,3,2))
Time\tSec=Val(Right(Time$,2))
If Time\tHr>11
Time\tMeridian=#True
Meridian$=" pm"
Else
Time\tMeridian=#False
Meridian$=" am"
EndIf
If Time\tHr>12
Time\tHr12f=Time\tHr-12
Else
Time\tHr12f=Time\tHr
EndIf
If Time\tHr12f=0
tHr12f$="12"
Else
tHr12f$=Str(Time\tHr12f)
EndIf
Time\tDisplay= tHr12f$+":"+RSet(Str(Time\tMin),2,"0")+":"+RSet(Str(Time\tSec),2,"0")+Meridian$
Time\tUpdate=#True
EndProcedure
If OpenWindow(0,0,0,200,100,"Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
If CreateGadgetList(WindowID(0))
TextGadget(1,10,10,70,20,"")
EndIf
eClock=SetTimer_(WindowID(0),2,1000,@Clock())
EndIf
Repeat
If Time\tUpdate ;updates once per second as set by settimer elapse value
SetGadgetText(1,Time\tDisplay)
Time\tUpdate=#False
EndIf
Until WaitWindowEvent()=#PB_Event_CloseWindow
If eClock
KillTimer_(WindowID(0),eClock)
EndIf
Not yet fully tested through the entire 24 hr day range, but at this stage seems to be working in my project very nicely.

Posted: Thu Feb 08, 2007 8:45 pm
by Kale
Another version using a thread:
Code: Select all
;]=============================================================================
;-CONSTANTS
;[=============================================================================
#APP_NAME = "Name"
Enumeration
#WINDOW_ROOT
#TIME_TEXT
EndEnumeration
;]=============================================================================
;-PROCEDURES
;[=============================================================================
;Handle an error
Procedure HandleError(Result.l, Text.s)
If Result = 0
MessageRequester("Error", Text, #PB_MessageRequester_Ok)
End
EndIf
EndProcedure
;sort out the time and display it
Procedure SetTime()
currentDate = Date()
hours.b = Hour(currentDate)
minutes.b = Minute(currentDate)
seconds.b = Second(currentDate)
append.s = "am"
If hours >= 12
append.s = "pm"
EndIf
If hours = 0
hours = 12
EndIf
If hours > 12
hours = hours-12
EndIf
If minutes < 10
adjustedMinutes.s = "0"+Str(minutes)
Else
adjustedMinutes.s = Str(minutes)
EndIf
If seconds < 10
adjustedSeconds.s = "0"+Str(seconds)
Else
adjustedSeconds.s = Str(seconds)
EndIf
SetGadgetText(#TIME_TEXT, Str(hours)+":"+adjustedMinutes+":"+adjustedSeconds+" "+append)
Delay(1000)
SetTime()
EndProcedure
;]=============================================================================
;-GEOMETRY
;[=============================================================================
HandleError(OpenWindow(#WINDOW_ROOT, 0, 0, 400, 300, #APP_NAME, #PB_Window_SystemMenu | #PB_Window_ScreenCentered), "Main window could not be created.")
HandleError(CreateGadgetList(WindowID(#WINDOW_ROOT)), "Gadget list for the main window could not be created.")
TextGadget(#TIME_TEXT, 10, 10, 100, 25, "")
ThreadID = CreateThread(@SetTime(), #Null)
;]=============================================================================
;-MAIN LOOP
;[=============================================================================
Repeat
EventID.l = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
KillThread(ThreadID)
End
;]=============================================================================
;-END
;==============================================================================
Posted: Thu Feb 08, 2007 8:46 pm
by Kale
Using the Timer WinAPI function
Code: Select all
;]=============================================================================
;-CONSTANTS
;[=============================================================================
#APP_NAME = "Name"
Enumeration
#WINDOW_ROOT
#TIME_TEXT
EndEnumeration
;]=============================================================================
;-PROCEDURES
;[=============================================================================
;Handle an error
Procedure HandleError(Result.l, Text.s)
If Result = 0
MessageRequester("Error", Text, #PB_MessageRequester_Ok)
End
EndIf
EndProcedure
;sort out the time and display it
Procedure SetTime()
currentDate = Date()
hours.b = Hour(currentDate)
minutes.b = Minute(currentDate)
seconds.b = Second(currentDate)
append.s = "am"
If hours >= 12
append.s = "pm"
EndIf
If hours = 0
hours = 12
EndIf
If hours > 12
hours = hours-12
EndIf
If minutes < 10
adjustedMinutes.s = "0"+Str(minutes)
Else
adjustedMinutes.s = Str(minutes)
EndIf
If seconds < 10
adjustedSeconds.s = "0"+Str(seconds)
Else
adjustedSeconds.s = Str(seconds)
EndIf
SetGadgetText(#TIME_TEXT, Str(hours)+":"+adjustedMinutes+":"+adjustedSeconds+" "+append)
SetTimer_(WindowID(#WINDOW_ROOT), 1, 1000, @setTime()) ; generates a #WM_TIMER which can be caught by the event loop
EndProcedure
;]=============================================================================
;-GEOMETRY
;[=============================================================================
HandleError(OpenWindow(#WINDOW_ROOT, 0, 0, 400, 300, #APP_NAME, #PB_Window_SystemMenu | #PB_Window_ScreenCentered), "Main window could not be created.")
HandleError(CreateGadgetList(WindowID(#WINDOW_ROOT)), "Gadget list for the main window could not be created.")
TextGadget(#TIME_TEXT, 10, 10, 100, 25, "")
SetTime()
;]=============================================================================
;-MAIN LOOP
;[=============================================================================
Repeat
EventID.l = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
End
;]=============================================================================
;-END
;==============================================================================
Posted: Thu Feb 08, 2007 8:49 pm
by Kale
Another version using the ElapsedMilliseconds() command:
Code: Select all
;]=============================================================================
;-CONSTANTS
;[=============================================================================
#APP_NAME = "Name"
Enumeration
#WINDOW_ROOT
#TIME_TEXT
EndEnumeration
;]=============================================================================
;-PROCEDURES
;[=============================================================================
;Handle an error
Procedure HandleError(Result.l, Text.s)
If Result = 0
MessageRequester("Error", Text, #PB_MessageRequester_Ok)
End
EndIf
EndProcedure
;sort out the time and display it
Procedure SetTime()
currentDate = Date()
hours.b = Hour(currentDate)
minutes.b = Minute(currentDate)
seconds.b = Second(currentDate)
append.s = "am"
If hours >= 12
append.s = "pm"
EndIf
If hours = 0
hours = 12
EndIf
If hours > 12
hours = hours-12
EndIf
If minutes < 10
adjustedMinutes.s = "0"+Str(minutes)
Else
adjustedMinutes.s = Str(minutes)
EndIf
If seconds < 10
adjustedSeconds.s = "0"+Str(seconds)
Else
adjustedSeconds.s = Str(seconds)
EndIf
SetGadgetText(#TIME_TEXT, Str(hours)+":"+adjustedMinutes+":"+adjustedSeconds+" "+append)
EndProcedure
;]=============================================================================
;-GEOMETRY
;[=============================================================================
HandleError(OpenWindow(#WINDOW_ROOT, 0, 0, 400, 300, #APP_NAME, #PB_Window_SystemMenu | #PB_Window_ScreenCentered), "Main window could not be created.")
HandleError(CreateGadgetList(WindowID(#WINDOW_ROOT)), "Gadget list for the main window could not be created.")
TextGadget(#TIME_TEXT, 10, 10, 100, 25, "")
SetTime()
;]=============================================================================
;-MAIN LOOP
;[=============================================================================
StartTime = ElapsedMilliseconds()
Repeat
EventID.l = WindowEvent()
CurrentTime = ElapsedMilliseconds()
If CurrentTime > StartTime + 1000 ; 1 second
SetTime()
StartTime = ElapsedMilliseconds()
EndIf
If EventID = #Null
Delay(1)
EndIf
Until EventID = #PB_Event_CloseWindow
End
;]=============================================================================
;-END
;==============================================================================
Posted: Thu Feb 08, 2007 10:34 pm
by rsts
Nice examples.
Thanks Kale - include those in next revision
cheers