Click here to Skip to main content
15,895,709 members
Articles / Desktop Programming / WPF

WPF Screensaver Helper

Rate me:
Please Sign up or sign in to vote.
4.00/5 (9 votes)
9 Jul 2016CPOL4 min read 17.5K   266   11   8
A Helper DLL to ease (some) of the headaches around creating a WPF screensaver

https://www.nuget.org/packages/ScreenSaver.Helper

Introduction

This is an introduction to my screensaver helper library. The aim was to offload, as much as possible, the minutiae around creating a screensaver. In essence, a screensaver is a regular exe with the extension changed to .scr. In practice, there are multiple components to making this work as expected. Processing various command line arguments, watching for keyboard & mouse events, allowing configuration, providing a win32 child window for preview mode, multiple monitor support, etc. this helper attempts to simplify as much of that as possible. 

Background

This is my first contribution to code project but I have benefited so much from all the experts here I thought it was time to attempt to give something back to the community. Rather than a "how-to" this is more of a tool you may use to help in your development of screensavers. Believe it or not, yes, there is still a need for screensaver development. In my case, I had multiple customer-facing kiosks and to avoid screen burn-in I wanted a custom screensaver. In this case, I wanted to consume our company's Facebook page but that is another topic. 

Using the code

Once you have a WPF application that you would like to make into a screensaver, reference the ScreenSaver.Helper.dll and log4net.dll and open your App.xml and remove/comment the existing StartupUri and add a Startup method.

XML
<Application x:Class="WPF_App_Tester.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="App_OnStartup">
    <!--StartupUri="YourWindow">-->
...
</Application>

After that is complete, move to your App.xaml.cs and use the ScreensaverApp Attribute to link your application to to the ScreenSaver helper subsystem.  The only required parameter is the main window (Your primary screensaver window) in the example below we named it "MainWindow". There are multiple optional parameters, ConfigWindow (Window) {This is the configuration window you want windows to use}, RestartOnUnhandled (bool), RepeatOnEachMonitor(bool), StretchAcrossMonitors(bool).

Inside the method you just created App_OnStartup you should pass the existing parameters (sender & e) to the Core.App_Startup method. This will handle multiple factors for you (covered later). 

You may also wish to hook into the Core.UnhandledException event to deal with any unexpected exceptions. By default the library uses log4net and creates a rolling log file stored in AppData/AppName to log the exception prior to shutting down. 

C#
using System.Windows;
using ScreenSaver.Helper;

namespace WPF_App_Tester
{
    [ScreensaverApp(typeof(MainWindow),typeof(ConfigWindow))]
    public partial class App : Application
    {
        private void App_OnStartup(object sender, StartupEventArgs e)
        {
            Core.UnhandledException += Core_UnhandledException;
            Core.App_Startup(sender, e);          
        }

        private void Core_UnhandledException(object sender, ref System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            // Your exception handling logic.
            // If you have resolved the exception 
            // set e.Handled = true;
        }
    }
}      

Custom Settings Provider

Screensavers have a quirk about how they access files/folders linked back to WinNT file/folder eight character naming limitations which fusses with the default settings provider. Instead of tweaking this we are going to use HKCU section of the registry to store our settings. The library provides a custom settings provider to enable this. To use it, navigate to your project's settings file, click the <>View Code button. Visual Studio should move you to your Settings.cs file.

Image 1

Include a using reference to ScreenSaver.Helper.SettingsProviders and add two attributes. The first,

C#
[SettingsProvider(typeof(SettingsProviderEx))]

this tells the settings system to use our alternative provider and the second,

C#
[SettingsProviderEx.SettingsHelper(typeof(RegCurrentUserHelper))]

informs the SettingsProviderEx to use the HKCU key we discussed before. 

C#
using System.Configuration;
using ScreenSaver.Helper.SettingsProviders;
namespace WPF_App_Tester.Properties {

    [SettingsProviderEx.SettingsHelper(typeof(RegCurrentUserHelper))]
    [SettingsProvider(typeof(SettingsProviderEx))]

    internal sealed partial class Settings {...} 
...
}

Command Line Parameters

If you build your application at this point it should now accept multiple command line parameters. 

/s  - Is a required parameter for windows screensavers it will show the form you identified in the MainWindow attribute of your App.xaml.cs. Inside the IDE the forces the window to TopMost = false to allow for debugging breaks and exception handling. When the debugger is not attached TopMost is set to true. 

In show mode, mouse and keyboard event listeners are injected into the MainWindow to allow for the traditional close events screensavers typically possess.

By default, if multiple monitors are present a 'shade' window is loaded on every monitor but the one identified as the main monitor in windows. The main monitor receives your MainWindow.

You can override this behavior with the RepeatOnEachMonitor(bool) or StretchAcrossMonitors(bool) as you see fit. 

/p IntPtr Using the IntPtr passed typically from windows while selecting a screensaver, the helper makes your MainWindow a child window for the preview mode but does not inject any mouse/keypress closure events.

/c  Opens the ConfigWindow you passed to the ScreenSaverApp attribute's ConfigWindow parameter.

/i Installs the screensaver by first changing the main file extension, if necessary, from an .exe to a .scr then updating the registry to set your screensaver as the default and then opens the Windows screen saver configuration window.

Additional Helper Classes

Logging

As mentioned previously the helper library used log4Net for its logging. You can provide your own additional logging by using the provided extension methods after adding a reference to the LogHelper class and log4net.

The first Log() simply logs your message with an optional exception object

C#
this.Log().Warning("YOUR WARNING MESSAGE",ex);

the second LogP() also logs your message but also adds the public properties of the calling class to the logg

C#
this.LogP().Error("YOUR ERROR MESSAGE",ex);

AnimationHelper

Is an await-able task based double animation helper, additionally, a Fade method is provided that adjusts the opacity of a UIElement or IEnumerable<UIElement> to fade in/out.

Usage: 

C#
await Image.Fade();   // Fades Image opacity to 0 in 3 seconds
C#
await Image.Fade(1);  // Fades Image opacity to 1 in 3 seconds
C#
await Image.Fade(1,6.Secs());  // Fades Image opacity to 1 in 6 seconds *Using included TimeSpanExtensions

ListExtensions

Methods to randomize a list of objects

C#
MyList.Shuffle();

And convert a List<string> to a CSV list and back again.

C#
string myCsvString = MyList.ToCsvLine();

List<string> MyList = myCsvString.FromCsvLine();

BitmapExtensions

Converts a Bitmap to an ImageSource

C#
Image.Source = Properties.Resources.MyResourceBitmap.ToImageSource(); 

History

11/8/2015 - Initial Post

7/9/2016 - Cleaned up some typos.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems / Hardware Administrator
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionBut what does it do? Pin
Harm Salomons11-Nov-15 4:07
Harm Salomons11-Nov-15 4:07 
AnswerRe: But what does it do? Pin
rleonard5511-Nov-15 12:19
rleonard5511-Nov-15 12:19 
PraiseRe: But what does it do? Pin
Imagiv11-Jul-16 4:47
Imagiv11-Jul-16 4:47 
I think you just mean WPF, there is no "WPF forms." At any rate, awesome library!
GeneralRe: But what does it do? Pin
rleonard5511-Jul-16 9:52
rleonard5511-Jul-16 9:52 
QuestionWPF Screensaver Helper Pin
Shojib Rahman9-Nov-15 18:44
Shojib Rahman9-Nov-15 18:44 
AnswerRe: WPF Screensaver Helper Pin
rleonard5510-Nov-15 0:26
rleonard5510-Nov-15 0:26 
GeneralNo library or code for library (?) Pin
david union9-Nov-15 14:16
david union9-Nov-15 14:16 
GeneralRe: No library or code for library (?) Pin
rleonard559-Nov-15 16:10
rleonard559-Nov-15 16:10 

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.