Click here to Skip to main content
15,881,812 members
Articles / Multimedia / GDI+
Article

How to develop a screen saver in C#

Rate me:
Please Sign up or sign in to vote.
4.59/5 (84 votes)
12 Nov 20046 min read 400K   6.9K   207   89
An article explaining how to develop a screensaver in C#, with a ready-to-code-screensaver source.

Issues covered

This article explains:

  • the basics of a screensaver
  • loading a screensaver
  • filling the whole screen
  • handling multiple monitors
  • handling events
  • some little intricacies

Additionally, the code provides a basic screensaver framework which you could use easily to create screensavers on your own.

Introduction

A screensaver in Windows® is simply an executable file with the extension .scr. The only difference between a normal executable and a screensaver is that a screensaver does some specific things, viz:

  • parses the command line to find out what Windows® wants it to do
  • loads the screensaver appropriate to that request
  • ends the screensaver (usually), when the user uses the mouse or the keyboard

The arguments Windows® passes to a screensaver are:

  • /s - load the screensaver
  • /c - load the configuration screen
  • /p - load the preview

Once we determine the argument passed, we load the screensaver appropriately. When there is some kind of activity, you end the screensaver or do something else.

The code explained

Step 1: Making the Main method accept command-line arguments

The first step in developing a screensaver in C# is to modify the Main method so that it could accept command-line arguments. The default Main method is like this:

C#
static void Main() 
{
  ...
}

As you can see, this Main method accepts no parameters. So, we add a string array parameter like this:

C#
static void Main(string[] args) 
{
  ...
}

Step 2: Checking the arguments

Now we need to find out what arguments were passed.

First, we check whether Windows did pass some arguments, by checking whether the length of the string array is zero or not. If it's zero, there were no arguments. A typical scenario where no arguments are passed to a screensaver is when users just double click on your screensaver file.

Secondly, if there indeed were arguments, we catch them. Windows may pass arguments in either the lower case or the upper case. So it's a good idea to induce generalization of some sort. We do this by changing the arguments to lower case (or upper case) first and then checking them. The complete Main method would look something like:

C#
static void Main(string[] args) 
{
  if (args.Length > 0)
  {
    // load the config stuff
    if (args[0].ToLower().Trim().Substring(0,2) == "/c") 
    {
      ...
    }
    else if (args[0].ToLower() == "/s") // load the screensaver
    {
      ...
    }
    else if (args[0].ToLower() == "/p") // load the preview
    {
      ...
    }
  }
  else // there are no arguments...nevertheless, do something!
  {
    ...
  }
}

Quite straight forward, isn't it? The only code you need to add here is what you would like to do for each argument.

Step 3: Invoking the screensaver

To run the screensaver, you call the System.Windows.Forms.Application.Run method. You pass a new form object as the argument. The code will look like:

C#
System.Windows.Forms.Application.Run(new frmScreenSaver());

where frmScreenSaver is the main screensaver form.

When the screensaver loads, we want it to fit the entire screen. For this, we need to figure out which screen our screensaver is running in right now and its dimensions. To access screens, we use the Screen class. Using the PrimaryScreen property of this class, we could access the primary screen of the system as well as its properties. Among those properties is Bounds, representing the size of the screen. What we do is set the form's Bounds property to that of this screen so that the form would be resized to occupy the entire screen. This procedure is usually executed in the form's Load event, for example:

C#
private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.PrimaryScreen.Bounds;
  ...
}

We need to address one possibility though - the user may be using more than one screen. If that's true, and if we load the screensaver only on one screen, the whole point of using this screensaver is lost. Hence, we find out the number of screens available, and load the screensaver in each of them. To do this, we iterate through all the available screens in the Main method, where we repeatedly call the form's constructor passing the screen's index. The set of all screens available in the system is listed in the AllScreens property of the Screen class. Thus the code in the Main method invoking the screensaver will have to be modified as:

C#
...
...
for (int i = Screen.AllScreens.GetLowerBound(0); 
     i <= Screen.AllScreens.GetUpperBound(0); i++)
  System.Windows.Forms.Application.Run(new frmScreenSaver(i));
...
...

Note the change in the main screensaver form's constructor - it accepts an int parameter, which represents the screen's index onto which the screensaver is to be run. In response to this, we modify the form's class by adding an int member variable which will store the screen index. The form's constructor will then be modified to initialize this variable, like this:

C#
public frmScreenSaver(int scrn)
{
  ...
  ScreenNumber = scrn;
  ...
}

where ScreenNumber is the int member variable.

After this, the Load event handler will have to be modified to resize the form to the bounds of not the primary screen, but that of the screen represented by the index, like this:

C#
private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.AllScreens[ScreenNumber].Bounds;
  ...
}

Once this is done, we have added multiple screen display functionality to our screensaver.

You will want to make the form topmost and hide the cursor. Just call the additional methods in the Load handler like this:

C#
private void frmScreenSaver_Load(object sender, System.EventArgs e)
{
  ...
  Bounds = Screen.AllScreens[ScreenNumber].Bounds;
    Cursor.Hide();
    TopMost = true;
  ...
}

Step 4: Handling events

Once you have loaded your screensaver, you have to handle events. This is because when the user uses the mouse or hits the keyboard, you probably want to do something, like ending the screensaver. To do this, you add event handlers to the KeyDown, MouseMove and MoveDown events of the screensaver form. In the event handlers, you could use the form's Close method to end the screensaver.

There is one point to note here. When an application is executed, the current mouse parameters are passed to it by Windows. This naturally triggers a mouse event, which would close the screensaver. To handle this, add a Point variable in the class, initialize it when the application executes, and check the mouse position and mouse clicks when mouse events occur. If there happens to be any change, then call Close. The code would look something like:

C#
private void OnMouseMove(object sender, 
                         System.Windows.Forms.MouseEventArgs e)
{
  if (!MouseXY.IsEmpty)
  {
    if (MouseXY != new Point(e.X, e.Y))
       Close();
  }
  MouseXY = new Point(e.X, e.Y);
}

where MouseXY is the Point variable we use to store the initial mouse position temporarily. Initially, MouseXY is null; and thus is assigned the current mouse position through this code. In the next call of this event handler, MouseXY is not empty; so we check whether the position has changed; if yes, close the form.

As mentioned earlier, you should handle both MouseMove and MouseDown events in a screensaver. But since both have the same arguments, you could use the same event handler for handling both events. Such a code would look like:

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

where OnMouseEvent is the event handler which is called on mouse move as well as mouse down events.

Step 5: Finally...

The last step of developing a screensaver is short and sweet...rename the file to an .scr extension. :)

You are done!

Using the bundled code

The code provided just loads a black form. To change it and implement your own features, follow these simple steps:

  1. Change the code in the Main method to handle different arguments
  2. Add a configuration form if necessary, and add the code to load it in the Main method
  3. Modify the main screensaver form so as to display what you want it to
  4. Rename the extension from .exe to .scr.
  5. Go!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
India India
Rakesh Rajan is a Software Engineer from India working at Technopark, Trivandrum in Kerala. He is a Microsoft MVP and an MCSD (.NET) with a few other certifications, and had been working in .NET for the past 3 years. He graduated majoring in Computer Science during his memorable days at Ooty (a wonderful hill station in Southern India). You can find him posting at newgroups, writing articles, working on his own projects or taking some time off by listening to music by Enya or Yanni, or reading an Archer or Sheldon.

Find his online publications here.

Rakesh blogs at http://rakeshrajan.com/blog/ and maintains a site http://rakeshrajan.com/.
He used to blog at http://www.msmvps.com/rakeshrajan/.

Drop him a mail at rakeshrajan {at} mvps {dot} org.

Comments and Discussions

 
GeneralScreen Saver in C# Pin
Member 85003431-Jan-04 17:05
Member 85003431-Jan-04 17:05 
GeneralRe: Screen Saver in C# Pin
Michael Flanakin28-Oct-04 10:40
Michael Flanakin28-Oct-04 10:40 
General.Net Compact Framework Pin
nvaidya19-Jan-04 11:36
nvaidya19-Jan-04 11:36 
GeneralRe: .Net Compact Framework Pin
Rakesh Rajan19-Jan-04 16:38
Rakesh Rajan19-Jan-04 16:38 
General&quot;.exe&quot; to &quot;.scr&quot; Pin
srt73-Dec-03 12:29
srt73-Dec-03 12:29 
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
Rakesh Rajan5-Dec-03 5:50
Rakesh Rajan5-Dec-03 5:50 
GeneralRe: &amp;quot;.exe&amp;quot; to &amp;quot;.scr&amp;quot; [modified] Pin
D11131-May-06 7:42
D11131-May-06 7:42 
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
Cobler26-Jan-04 6:09
Cobler26-Jan-04 6:09 
All you need to do is rename the extension of the file. The default setting for Windows is to hide the file extension, so you will have to change the setting.
1. Open up a window ("My Computer" will do).
2. Go to the "Tools" menu and scroll down to "Folder Options"
3. Uncheck the "Hide extentions for know file types"
4. Rename the extension from .exe to .scr. You will receive a warning that altering the extension can make the file unsuable, hit yes that you want to chage it.
5. Copy the screen saver program to your Windows folder.
Now you should find the screen saver as an option.
Hope this helps.
Cobler
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
Rakesh Rajan28-Jan-04 0:18
Rakesh Rajan28-Jan-04 0:18 
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
Cobler28-Jan-04 2:28
Cobler28-Jan-04 2:28 
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
CoffeeZombie18-Dec-04 7:03
CoffeeZombie18-Dec-04 7:03 
GeneralRe: &quot;.exe&quot; to &quot;.scr&quot; Pin
leonluftwaffel31-Jan-05 10:18
leonluftwaffel31-Jan-05 10:18 
GeneralI must be missing something Pin
sysko27-Oct-03 6:47
sysko27-Oct-03 6:47 
GeneralRe: I must be missing something Pin
Rakesh Rajan27-Oct-03 8:12
Rakesh Rajan27-Oct-03 8:12 
GeneralRe: I must be missing something Pin
sysko27-Oct-03 11:29
sysko27-Oct-03 11:29 
General!!! Pin
sysko27-Oct-03 11:41
sysko27-Oct-03 11:41 
GeneralRe: !!! Pin
Rakesh Rajan27-Oct-03 21:13
Rakesh Rajan27-Oct-03 21:13 
GeneralMissing information Pin
Michael Starr16-Oct-03 7:44
Michael Starr16-Oct-03 7:44 
GeneralRe: Missing information Pin
Rakesh Rajan24-Oct-03 7:49
Rakesh Rajan24-Oct-03 7:49 
GeneralRe: Missing information Pin
Michael Starr24-Oct-03 8:16
Michael Starr24-Oct-03 8:16 
Questionamzing,is that realy all ??? Pin
Anonymous1-Oct-03 14:19
Anonymous1-Oct-03 14:19 
AnswerRe: amzing,is that realy all ??? Pin
Rakesh Rajan3-Oct-03 2:43
Rakesh Rajan3-Oct-03 2:43 
QuestionProcess Priority? Pin
tonymudd4-Sep-03 22:14
tonymudd4-Sep-03 22:14 
AnswerRe: Process Priority? Pin
Rakesh Rajan9-Sep-03 3:22
Rakesh Rajan9-Sep-03 3:22 
GeneralRe: Process Priority? Pin
ForogarTree24-Nov-04 4:51
ForogarTree24-Nov-04 4:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.