Useful Windows Screensavers - Including Windows 10
Written by Mike James   
Thursday, 24 September 2015
Article Index
Useful Windows Screensavers - Including Windows 10
A Form Based Screensaver
Preview
Listing

A form based screensaver

The method described so far is the traditional approach that you will find in the documentation and examples. Sometimes it’s a good way of implementing a screensaver but if you are planning to use a form to create the display then there is a better way to build an application.

Start a new Windows form project called ScreenSaver2.

The easiest way to get at the command line arguments/parameters is to use

Environment.GetCommandLineArgs();

We need to modify the form's contructor:


public Form1()
{
 InitializeComponent();
 m_args = Environment.GetCommandLineArgs();
 this.TopLevel = false;
}

and add the global variable:

private string[] m_args;

Now any method in Form1 can access m_args to discover what the command line parameters are. Notice that this method of retrieving the command line parameters always returns the execution path as the first parameter i.e. the first real parameter is in m_args[1].

The TopLevel property is set to false to make the form invisible. Notice you can’t make the form loaded on startup invisible by using Hide or setting Visible=false because the Run method makes the form visible after the Load event handler is finished. With these changes all of the command line argument processing can be performed in the Form Load event handler:

private void Form1_Load(object sender,
                                   EventArgs e)
{
 if (m_args.Length > 1)
 {
  string arg = m_args[1].ToLower().Trim().
                               Substring(0, 2);
  switch (arg)
  {
   case "/c":
    //configure
    break;
   case "/s":
    ShowScreenSaver();
    break;
   case "/p":
    //preview  
   break;
  }
 }
 else
 {
  ShowScreenSaver();
 }
}

And the ShowScreenSaver function is just:

void ShowScreenSaver()
{
 this.TopLevel = true;
}

If you run this as a screensaver you will see a blank form.  

Bouncing text

We really need some graphics to show the sort of thing a screensaver can do.

As an example we are going to bounce a message round the form. The simplest way of creating animation is to use a timer – so place a timer control on the form and change the ShowScreenSaver to:

void ShowScreenSaver()
{
 this.TopLevel = true;
 this.DoubleBuffered = true;
 this.timer1.Interval = 20;
 this.timer1.Enabled = true;
}

This sets the timer to 20 milliseconds which produces an update every 1/50th of a second. Setting DoubleBuffered to true makes the animation smooth.

The Timer event handler does all the work.

First it gets the graphics object associated with the form so that it can use it to draw:

private void timer1_Tick(
      object sender, EventArgs e)
{
   Graphics g = this.CreateGraphics();

As will become clear, you can’t assume that the screensaver is going to have a fixed sized form to draw on and everything should be done in terms of a fraction of the available space. To do this we first need the size of the display area:

RectangleF bounds =this.ClientRectangle;

Next we can set the message to display and a font size that is 1/20th of the height of the display area:

string displayM ="Visit I-Programmer";
int fontsize =(int) bounds.Height / 20;

We need to set a font to use and any font from the Arial family will do:

FontFamily fontFamily=new FontFamily("Arial");
Font font = new Font(
                  fontFamily,
                  fontsize,
                  FontStyle.Regular,
                  GraphicsUnit.Pixel);

To blank the message out at its current position we can use the TextRenderer object and its MeasureText method. This returns a size struct giving the height and width of the rectangle that the text fits into:

Size psize=new Size(int.MaxValue,int.MaxValue);
Size size = TextRenderer.MeasureText(
                        g,
                        displayM,
                        font,
                        psize,
                        TextFormatFlags.SingleLine);

Now that we have the size of the text the FillRectangle method can be used to draw a rectangle of just the correct size in the current form’s background colour:

SolidBrush b = new SolidBrush(this.BackColor);
g.FillRectangle(b,
                textpos.X,
                textpos.Y, 
                size.Width,
                size.Height);

To move the text its position is updated and if it is just about to go off the edge of the form we reverse its direction of motion, i.e. bounce it:

textpos.X +=v.X;
textpos.Y +=v.Y;
if (textpos.X+size.Width >= bounds.Width
                  || textpos.X<=0) v.X = -v.X;
if (textpos.Y +size.Height>= bounds.Height
                  || textpos.Y < 0) v.Y = -v.Y;

Finally the text is drawn at its new position on the screen:

 TextRenderer.DrawText(g,
                       displayM,
                       font,
                       textpos,
                       Color.Red);
 g.Dispose();
}

We also need some additional global variables:

private Point textpos = new Point(0, 0);
private Point v = new Point(1, 1);

If you now try the screensaver you should see the message bounce its way around the form and if you resize the form the text will automatically resize and bounce at the new edge.

More like a screensaver

So far we have the basic functionality of a screensaver but it doesn’t look or behave like one.

To make it look like one we have to resize the form to fill the screen and remove its border in the ShowScreenSaver function:

this.FormBorderStyle =FormBorderStyle.None;
this.TopLevel = true;
this.WindowState =FormWindowState.Maximized;
this.Capture = true;
Cursor.Hide();

To make the screensaver close when the mouse moves or if its button is clicked we need a simple event handler:

private void OnMouseEvent(object sender,
          System.Windows.Forms.MouseEventArgs e)
{
 if (!MousePos.IsEmpty)
 {
  if (MousePos != new Point(e.X, e.Y))
                                 this.Close();
  if (e.Clicks > 0) this.Close();
 }
 MousePos = new Point(e.X, e.Y);
}

and another global variable to store the mouse position:

private Point MousePos;

This one-event handler can deal with MouseMove and MouseDown events. View the form in design mode and use the properties window to set both events to the OnMouseEvent function.

Now when you run the program it should fill the screen and close when the mouse moves or is clicked.

You can improve the way that it works by adding code to close only if the mouse moves more than a set amount and you can trap keyboard events to close it.

 

<ASIN:1890774464>

<ASIN:047019135X>

<ASIN:0596514824>

<ASIN:1590599551>



Last Updated ( Tuesday, 06 October 2015 )