In this tutorial lesson, I am going to try and show how you can create a simple screen saver program. The main screen will be a simple black background, in the 'popup' style we used in lesson 17 to create an un-titled message box. In this, we will create a second window, which will contain the eu.bmp bitmap. The second window will be constantly re-located by an onTimer[] event handler, in a simple 'bouncing' fashion, whenever the bitmap 'hits' the edges of the main window.
Since a screen saver should cover the whole screen, and users may have different screen sizes set up on their system, we can't declare our main window's size directly. We will instead use the GetSystemMetrics() function to 'discover' the user's screen size before we create the main window. The values returned by this function will then be used to create our main window, so it fills the whole screen, no matter what it's size.
--
screen1.exw
--screen1.exw--
include win32lib.ew
without warning
constant
-- get the users screen size
CXFULL = w32Func( xGetSystemMetrics, {SM_CXSCREEN} ),
CYFULL = w32Func( xGetSystemMetrics, {SM_CYSCREEN} ),
-- use these values to create our main
Win1 = create( Window, "", 0, 0, 0, CXFULL, CYFULL, #80400000 ),
-- next, create our 'bitmap' window
Win2 = create( Window, "", Win1, 0, 0, 330, 148, #80400000 ),
-- leaving a little room for some text
Title5 = create( CText, "_empowered by WIN32LIB_", Win2, 1, 121, 322, 20, 0 ),
-- then the actual bitmap area
Bitmap2 = create( Bitmap, "", Win2, 0, 0, 324, 120, 0 ),
-- set up a timerId for an onTimer[] event handler
Mytimer1 = 1,
-- and calculate the 'extents' of how far
-- we allow our secondary window to move
-- within the main window
CX = CXFULL-330,
CY = CYFULL-148
setBitmap( Bitmap2, ".\\Bin\\eu.bmp" )
setFont( Title5, "Arial", 12, 3 )
setWindowBackColor( Win1, rgb(0,0,0) )
atom rgbColor
rgbColor = getSysColor( COLOR_BTNFACE )
setWindowBackColor( Win2, rgbColor )
atom posx, posy, xsize, ysize, xdir, ydir
xdir = 1 ydir = 1
-- always start with a centered bitmap
procedure center_win( atom win_id )
sequence loc
loc = getRect( win_id )
xsize = loc[3]-loc[1]
ysize = loc[4]-loc[2]
posx = floor(( w32Func( xGetSystemMetrics, {SM_CXFULLSCREEN} )/2)-(xsize/2) )
posy = floor(( w32Func( xGetSystemMetrics, {SM_CYFULLSCREEN} )/2)-(ysize/2) )
setRect(win_id,posx,posy,xsize,ysize,1 )
end procedure
procedure start_up( integer self, integer event, sequence params )
center_win(Win2)
openWindow(Win2,Modal)
setTimer( Win1, Mytimer1, 25 ) -- 40 moves/sec. maximum
end procedure
-- this moves the bitmap,
-- and changes direction
-- if we hit a main window 'border'
procedure next_pos( integer self, integer event, sequence params )
if posx < 1 or posx > CX then
xdir = -xdir
end if
if posy < 1 or posy > CY then
ydir = -ydir
end if
posx = posx + xdir
posy = posy - ydir
setRect(Win2,posx,posy,xsize,ysize,1 )
end procedure
-- closes everything on exit
procedure exit_prog( integer self, integer event, sequence params )
closeWindow(Win2)
closeWindow(Win1)
end procedure
-- shut-down, if a key is pressed
procedure blah( integer self, integer event, sequence params )
exit_prog()
end procedure
setHandler( Win1, w32HOpen, routine_id("start_up") )
setHandler( Win1, w32HTimer, routine_id("next_pos") )
setHandler( Win2, w32HKeyDown, routine_id("blah") )
setHandler( Win2, w32HClick, routine_id("exit_prog") )
WinMain( Win1,Maximize )
--end code--Hitting any normal key on the keyboard, or left-clicking on the 'bitmap' secondary window will stop the program.
...of interest.
I originally posted an example of this program on the Euphoria mailing list. I was trying to find out what setting I should use for Mytimer1, to allow the bitmap to to be displayed at a reasonable speed, without 'blurring', and still allow a user to click on it, to stop the program.
I guess I needn't have worried ... :)
Brian Broker kindly tested the program for me on a 550 mhz. dual
processor system, and found out that setting the timer value below 15
had no further effect in speeding up the bitmap moves. Apparently,
the minimum 'response' time for a timer is about 15 milliseconds, so
the bitmap won't move more than 66 times a second, no matter how
small a timer value is used, or how fast the computer is. If you want
to move something faster than this, you can't use a simple timer call
!
...on my 'ancient' 486/DX/4/100, it moves only 22 times/second... :(
Just to prove this to myself, I wrote screen2.exw. This uses a MUCH smaller 32 by 32 bitmap of only 1024 pixels, which it moves around in the main window. It's no faster, even with a timer setting of 5 ! You might want to check out the mouse handling routine, since it uses onMouse[], ...so it's a little different from screen1.exw.
..and on to the next lesson.