The Splash() procedure is (or should be) fully self contained,
no need to provide window id constants or gadget constant etc etc.
(it's an amazing example of how easy PB is really

The Splash accept the timeout in the form of seconds.
Now for the more advanced stuff (or not),
the MessageTimer procedures, normally you would just really use one here,
namely the MessageTimer() one, hopefully it's arguments are self explanatory.
It should be fully thread safe except for one little quirk,
the messagetimer structure do not get the threadid value set
until AFTER the thread has been created, so do not check the threadid in
the structure immediately after you started the timer,
it will take a few cpu cycles before it get set.
Anything else should be fully thread safe as it handles it's own memory and so on.
As you may also notice there is a bunch of supporting functions,
these are simple wrappers for the various Thread functions in PureBasic,
and simply saves you the trouble of making these yourself, oh how nice I am

Note! MessageTimer() will fail if delay is 0 this is on purpose to avoid
wasting resources since there is no point in a 0ms timer!
If the loop argument is set as 0 then the timer will loop forever,
this kind of timer is maybe of more use to certain apps, or games.
The only way to stop and cleanup the timer if loop is 0 is to use the MessageTimer_Kill() function,
so make sure you keep track of the memory pointer that MessageTimer() returns in that case.
(it is a pointer to the memory structure)
You can also use the priority function to set the system priority of a timer,
mostly of interest to time critical programs I guess.
There is also pause and resume functions,
now these may be very interesting to game makers
as you could pause the timers as the player uses a game menu etc.
Or you could apparently pause/freeze time.
Please note that this is all based on the Delay() function,
so the timer resolution is the same as that.
I would not advice the use of this timer for graphics and time critical AI and so on,
as there is some overhead and lack of timer precision.
(consider this a normal resolution timer + message overhead)
However, MessageTimer() should be perfect for splash screens,
events, triggers, auto closing of apps/windows (like the splash example),
periodical checking, program update checks, etc. etc.
the max value of the delay is the same as the Delay() function,
so you can easily set a messagetimer to trigger once each 24 days if you wanted. hehe!
Code: Select all
;by Rescator
;EmSai OpenSource Licence http://emsai.net/esos/
Structure struct_messagetimer
delay.l
loop.l
hwnd.l
message.l
wparam.l
lparam.l
threadid.l
die.l
EndStructure
Procedure MessageTimer_Threadloop(*mem.struct_messagetimer)
If *mem
If *mem\loop=0
Repeat
If *mem\die
Break
Else
Delay(*mem\delay)
PostMessage_(*mem\hwnd,*mem\message,*mem\wparam,*mem\lparam)
EndIf
ForEver
Else
i=0
Repeat
Delay(*mem\delay)
PostMessage_(*mem\hwnd,*mem\message,*mem\wparam,*mem\lparam)
i+1
Until i=*mem\loop
EndIf
FreeMemory(*mem)
EndIf
EndProcedure
Procedure MessageTimer(windowid.l,delay.l,loop.l,message.l,wparam.l,lparam.l)
;if loop is 0 the timer never end, but must be killed instead
Protected *mem.struct_messagetimer
If delay<>0 And delay<>#INFINITE And loop>#INFINITE
*mem=AllocateMemory(SizeOf(struct_messagetimer))
If *mem
*mem\hwnd=WindowID(windowid)
*mem\delay=delay
*mem\message=message
*mem\wparam=wparam
*mem\lparam=lparam
*mem\loop=loop
*mem\die=#False
*mem\threadid=CreateThread(@MessageTimer_Threadloop(),*mem)
If *mem\threadid
ProcedureReturn *mem
Else
FreeMemory(*mem)
EndIf
EndIf
EndIf
ProcedureReturn #False
EndProcedure
Procedure MessageTimer_Kill(*mem.struct_messagetimer)
If *mem
*mem\die=#True
EndIf
EndProcedure
Procedure MessageTimer_Pause(*mem.struct_messagetimer)
If *mem
PauseThread(*mem\threadid)
EndIf
EndProcedure
Procedure MessageTimer_Resume(*mem.struct_messagetimer)
If *mem
ResumeThread(*mem\threadid)
EndIf
EndProcedure
Procedure MessageTimer_Priority(*mem.struct_messagetimer,priority.l)
If *mem
ProcedureReturn ThreadPriority(*mem\threadid,priority)
EndIf
ProcedureReturn #False
EndProcedure
Procedure Splash(splashimage$,splashtitle$,timeout,parentwindow)
image_splash=LoadImage(#PB_Any,splashimage$)
If image_splash
flags=#WS_POPUP|#PB_Window_ScreenCentered|#PB_Window_Invisible
window_splash=OpenWindow(#PB_Any,0,0,ImageWidth(image_splash),ImageHeight(image_splash),splashtitle$,flags,parentwindow)
If window_splash
AddKeyboardShortcut(window_splash,#PB_Shortcut_Escape,window_splash)
AddKeyboardShortcut(window_splash,#PB_Shortcut_Space,window_splash)
If ImageGadget(0,0,0,ImageWidth(image_splash),ImageHeight(image_splash),ImageID(image_splash))
Delay(1)
HideWindow(window_splash,0)
timer1=MessageTimer(window_splash,timeout*1000,1,#PB_Event_CloseWindow,0,0)
If timer1
Debug "Success"
Else
Debug "Failed"
EndIf
Repeat
Event=WindowEvent()
If Event=#PB_Event_Menu Or Event=#PB_Event_Gadget
Event=#PB_Event_CloseWindow
Else
Delay(1)
EndIf
Until Event=#PB_Event_CloseWindow
FreeGadget(0)
EndIf
EndIf
CloseWindow(window_splash)
FreeImage(image_splash)
EndIf
EndProcedure
UsePNGImageDecoder()
Splash("splash.png","splash test",10,0)