How to make a screen saver

How to make a screen saver in C#, one very similar to the Windows XP screen saver. Tutorial and source code.

Making a screen saver in C# is rather simple, but only if you know the ‘secret’.

When Windows loads the screen saver it actually passes an argument – ‘/s’. Also, you know from Display Properties in Windows that some screen savers have settings you can set. When Windows wants to access this settings it passes another argument – ‘/c’. Also in Display Properties there is a small picture representing a display where the user can view a preview of the screen saver – the preview is called using the argument ‘/p’.

Any screen saver is actually an executable (.exe) file with the extension changed to .scr. If you let the extension unchanged after you compile the program and you execute the .exe file, the screen saver will still work of course, but if you add it to the System32 folder in your Windows directory, the screen saver won’t appear in the list at Display Properties. After changing the extension to .scr Windows will add the screen saver to the list.

Also, when you execute the screen saver while it has the .exe extension, windows won’t pass the ‘/s’ argument, the argument is passed only when the file is a .scr file.

You can see that in the first lines of the program we check for passed arguments. First it checks if Windows passes any arguments at all, because as I said earlier if the application is started as an .exe file no arguments are passed. As you can see from the code, even if no arguments are passed we still want the screen saver to start.

Start a new Windows Application project named ‘scrSaver’. To the project add a new class named ‘scrClass’. Use the following code in the new class:

using System;

using System.Windows.Forms;
namespace scrSaver

{

public class scrClass

{

[STAThread]

static void Main(string[] args)

{

     // If Windows passes arguments...

     if (args.Length > 0)

     {

     // If argument is /c...

          if (args[0].ToLower().Trim().Substring(0,2) == "/c")

          {

          // Add code here if you want your screen saver to have settings

          }

          // If argument is /s...

          else if (args[0].ToLower() == "/s")

          {

               // Start the screen saver on all the displays the computer has

               for (int x = Screen.AllScreens.GetLowerBound(0); x <= Screen.AllScreens.GetUpperBound(0); x++)

               {

               // Pass the number of the display to Form1()

               System.Windows.Forms.Application.Run(new Form1(x));

               }

          }

     }

     // If there are no arguments just start the screen saver

     else


     {

          // Start the screen saver on all the displays the computer has


          for (int x = Screen.AllScreens.GetLowerBound(0); x <= Screen.AllScreens.GetUpperBound(0); x++)

          {

          // Pass the number of the display to Form1()


          System.Windows.Forms.Application.Run(new Form1(x));

          }

     }

}

}

}

The screen saver is actually a form. So let’s open it in Design mode and add a PictureBox to it named ‘pictureBox1’. Set the BackColor property of the PictureBox to any color you wish. Now also change the BackColor property of the form to black, the ShowInTaskbar property to False and the FormBorderStyle property to None. The form should look similar to this one now:

Now it’s time to add a timer to our form for the animation to work. So add a timer named timer1 and set the Enabled property to True and the Interval property to 7000 (7 seconds).

Let’s get into the code of Form1.cs now.

This is the code we use in Form1 class. So select all the code created by Visual Studio and delete it, then paste the code below, we will review it after.

using System;

using System.Drawing;

using System.Collections;

using System.ComponentModel;

using System.Windows.Forms;

using System.Data;

namespace scrSaver

{

public class Form1 : System.Windows.Forms.Form

{

private System.Windows.Forms.PictureBox pictureBox1;

private System.Windows.Forms.Timer timer1;

private System.ComponentModel.IContainer components;

// Store the mouse coordinates

private Point mouseCoords;

// Store the number of displays

private int displayNum;

// Random number that will change the position of the PictureBox

Random rand = new Random();

// Accept one argurment - the number of displays

public Form1(int display)

{

InitializeComponent();

// Assign the number to an accessible variable

displayNum = display;

}

protected override void Dispose( bool disposing )

{

    if( disposing )

    {

        if (components != null)

        {

        components.Dispose();

        }

    }

    base.Dispose( disposing );

}

#region Windows Form Designer generated code

///



/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

///


private void InitializeComponent()

{

this.components = new System.ComponentModel.Container();

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.timer1 = new System.Windows.Forms.Timer(this.components);

this.SuspendLayout();

//

// pictureBox1

//

this.pictureBox1.BackColor = System.Drawing.Color.FromArgb(((System.Byte)(192)), ((System.Byte)(0)), ((System.Byte)(0)));

this.pictureBox1.Location = new System.Drawing.Point(8, 8);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(80, 80);

this.pictureBox1.TabIndex = 0;

this.pictureBox1.TabStop = false;

//

// timer1

//

this.timer1.Enabled = true;

this.timer1.Interval = 7000;

this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

//

// Form1

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.BackColor = System.Drawing.Color.Black;

this.ClientSize = new System.Drawing.Size(292, 273);

this.Controls.AddRange(new System.Windows.Forms.Control[] {

this.pictureBox1});

this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

this.Name = "Form1";

this.ShowInTaskbar = false;

this.Text = "Form1";

this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

this.Load += new System.EventHandler(this.Form1_Load);

this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseMove);

this.ResumeLayout(false);
}

#endregion

private void Form1_Load(object sender, System.EventArgs e)

{

    // Set the bounds of the form, fill all the screen

    this.Bounds = Screen.AllScreens[displayNum].Bounds;

    // The form should be on top of all

    TopMost = true;

    // We don't need the cursor

    Cursor.Hide();

}

private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

{

    // If mouseCoords is empty don't close the screen saver

    if(!mouseCoords.IsEmpty)

    {

        // If the mouse actually moved

        if(mouseCoords != new Point(e.X, e.Y))

        {

            // Close

            this.Close();

        }

    }

    // Set the new point where the mouse is

    mouseCoords = new Point(e.X, e.Y);

}

// If a key was pressed...

private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)

{

    // ...close the screen saver

    this.Close();

}

// Every 7 seconds...

private void timer1_Tick(object sender, System.EventArgs e)

{

    // set the new X position of the PictureBox to random number

    int newX = rand.Next(0, (this.Size.Width - pictureBox1.Size.Width));

    // set the new Y position of the PictureBox to random number

    int newY = rand.Next(0, (this.Size.Height - pictureBox1.Size.Height));

    // and actually move the PictureBox to the new position

    pictureBox1.Location = new Point(newX, newY);

}

}

}

From the above code let’s first review the following piece:

private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)

{

    // If mouseCoords is empty don't close the screen saver

    if(!mouseCoords.IsEmpty)

    {

        // If the mouse actually moved

        if(mouseCoords != new Point(e.X, e.Y))

        {

            // Close

            this.Close();

        }

    }

    // Set the new point where the mouse is

    mouseCoords = new Point(e.X, e.Y);

}

What happens here? You ask yourself. Sure, when the mouse moves we want the screen saver to exit – that makes sense – but that looks a bit complicated, a simple Close() should do it, you cry. Well, for this piece of code I’m indebted to Rakesh Rajan with his tutorial that you might also want to consider.

If you simply use Close(), when the screen saver starts it gets closed immediatly, that’s because the mouse coordinates are passed to the application immediatly and the event fires. The Point variable saves the day because it is used to check the changes in mouse coordinates, therefore not considering the mouse coordinates passed to our screen saver, because at that time the if conditions will return false.

A screen saver should usually be animated, that is actually the original purpose of a screen saver, to save your display from developing permanent etching of a pattern. This is why we change the position of the PictureBox every 7 seconds (using the timer) to a random place on the screen:

// Every 7 seconds...

private void timer1_Tick(object sender, System.EventArgs e)

{

    // set the new X position of the PictureBox to random number

    int newX = rand.Next(0, (this.Size.Width - pictureBox1.Size.Width));

    // set the new Y position of the PictureBox to random number

    int newY = rand.Next(0, (this.Size.Height - pictureBox1.Size.Height));

    // and actually move the PictureBox to the new position

    pictureBox1.Location = new Point(newX, newY);

}

We don’t want the PictureBox to go to some place not visible on the screen, so we generate a random number between 0 and the difference between the width of the form and the size of the PictureBox (because the position of the PictureBox is considered from the top – left corner of it). If you have no ideea what I’m talking about, check a tutorial about C# graphics and GDI.

What’s left for you to do? Insert an image into the PictureBox, compile the program, change the extension from .exe to .scr and copy it to your System32 directory where the other screen savers reside.

The transparent screen saver

Something pretty interesting is a transparent screen saver. Just set the opacity property of the form to 85% perhaps and check out the results.

Geekpedia screen saver

We have a screen saver with the Geekpedia logo using this source code.

There are two versions of this screen saver. The standard version:

And the transparent version:

(14.5 KB). Extract them to your System32 directory and open from Display Properties.

Good luck 😉

Nathan Pakovskie is an esteemed senior developer and educator in the tech community, best known for his contributions to Geekpedia.com. With a passion for coding and a knack for simplifying complex tech concepts, Nathan has authored several popular tutorials on C# programming, ranging from basic operations to advanced coding techniques. His articles, often characterized by clarity and precision, serve as invaluable resources for both novice and experienced programmers. Beyond his technical expertise, Nathan is an advocate for continuous learning and enjoys exploring emerging technologies in AI and software development. When he’s not coding or writing, Nathan engages in mentoring upcoming developers, emphasizing the importance of both technical skills and creative problem-solving in the ever-evolving world of technology. Specialties: C# Programming, Technical Writing, Software Development, AI Technologies, Educational Outreach

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top