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) 8)

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