...a simple screen saver program.

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.

CONTENTS