Click here to Skip to main content
Click here to Skip to main content

How to develop a screen saver in C#

, 12 Nov 2004
Rate this:
Please Sign up or sign in to vote.
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:

static void Main() 
{
  ...
}

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

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:

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:

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:

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:

...
...
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:

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:

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:

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:

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:

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. Smile | :)

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

Share

About the Author

Rakesh Rajan
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

 
GeneralMy vote of 1 PinmemberDeja29-Jun-09 9:12 
Generalbanks screen saver PinmemberWalterThizo1-Oct-08 1:12 
GeneralThe article is not sufficient [modified] PinmemberNiklas Henricson24-Sep-06 1:33 
QuestionRe: The article is not sufficient PinmemberMika24-Apr-07 1:29 
AnswerRe: The article is not sufficient PinmemberMartin Brice22-May-07 7:54 
GeneralRe: The article is not sufficient Pinmemberkesterd27-May-08 11:25 
QuestionAny way to detect scn svr running? Pinmembertomsmaily12325-Aug-06 6:21 
GeneralI want to add screensaver into display properties windows PinmemberDungVinh18-Aug-06 17:46 
GeneralRe: I want to add screensaver into display properties windows PinmemberNiklas Henricson24-Sep-06 1:36 
GeneralThanks, BTW PinmemberEnnis Ray Lynch, Jr.2-Aug-06 6:02 
QuestionMouseEvent [modified] PinmemberTheEagle25-May-06 21:47 
QuestionMouseEvent PinmemberTheEagle29-Apr-06 5:54 
QuestionHow to update screen? Pinmemberbekiser22-Feb-06 5:40 
GeneralDeployment Pinmemberivan 4512-Dec-05 4:36 
GeneralRe: Deployment PinmemberRakesh Rajan12-Dec-05 17:45 
Generalfire Screensaver event c#.net Pinmembersweety783-Aug-05 0:59 
GeneralSolved the multi-monitor issue. PinmemberGarryfre11-Jun-05 22:45 
GeneralRe: Solved the multi-monitor issue. PinmemberRakesh Rajan12-Jun-05 3:02 
GeneralRe: Solved the multi-monitor issue. PinmemberGarryfre12-Jun-05 7:50 
GeneralRe: Solved the multi-monitor issue. PinmemberGarryfre13-Jun-05 8:09 
GeneralRe: Solved the multi-monitor issue. PinmemberOpossum_the_1st22-Jul-05 8:25 
GeneralRe: Solved the multi-monitor issue. PinsussAnonymous22-Jul-05 8:34 
GeneralRe: Solved the multi-monitor issue. PinsussAnonymous22-Jul-05 8:39 
GeneralApplication.Run() is MODAL!! PinmemberGarryfre20-May-05 2:27 
GeneralI stand corrected on GetLowerBounds PinmemberGarryfre20-May-05 8:34 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141220.1 | Last Updated 12 Nov 2004
Article Copyright 2003 by Rakesh Rajan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid