Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » C# » Applications » Downloads
 
Add your own
alternative version

Controlling The Screen Saver With C#

, 8 Jan 2007 CPOL
A C# class for monitoring, activating, deactivating, closing, and changing the timeout of the screen saver.
screensavercontrol_src.zip
ScreenSaver Control
Properties
Settings.settings
screensavercontrol_test.zip
ScreenSaver Control.exe
using System;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;

namespace ScreenSaver_Control
{
	public partial class ScreenSaverTest : Form
	{
		private System.Threading.Timer killTimer;
		private int killState = 1;
		private int killPeriod = 8000;		// msec
		private int timerState = STOPPED;
		private bool ssIsActive = false;
		private int ssTimeout = 5;				// sec
		private Int32 ssSaveTimeout = 0;
		private IntPtr hThisWnd = IntPtr.Zero;

		private const int STOPPED = 0;
		private const int RUNNING = 1;
		private const int FALSE = 0;
		private const int TRUE = 1;

		// This delegate enables asynchronous calls for setting
		// the text property on a TextBox control.
		delegate void SetTextCallback( string text );

		public ScreenSaverTest( )
		{
			InitializeComponent( );
			TimerCallback timerDelegate = new TimerCallback( KillTimer_Elapsed );
			killTimer = new System.Threading.Timer( timerDelegate, null, System.Threading.Timeout.Infinite, killPeriod );

			// Save off this Window's handle. Used in the kill event handler.
			hThisWnd = ScreenSaver.GetForegroundWindow( );

			// Save off the original Settings values
			ssIsActive = ScreenSaver.GetScreenSaverActive( );
			ssSaveTimeout = ScreenSaver.GetScreenSaverTimeout( );

			UpdateSettingsValues( );
		}

		private void buttonActivate_Click( object sender, EventArgs e )
		{
			// Toggle Screen Saver Active
			ScreenSaver.SetScreenSaverActive( ( ScreenSaver.GetScreenSaverActive( ) ) ? FALSE : TRUE );
			UpdateSettingsValues( );
		}

		private void buttonUpdateTimeout_Click( object sender, EventArgs e )
		{
			ScreenSaver.SetScreenSaverTimeout( ssTimeout );
			UpdateSettingsValues( );
		}

		private void buttonRefresh_Click( object sender, EventArgs e )
		{
			UpdateSettingsValues( );
		}

		private void buttonRestore_Click( object sender, EventArgs e )
		{
			// Restore original screen saver settings
			ScreenSaver.SetScreenSaverActive( ( ssIsActive ) ? TRUE : FALSE );
			ScreenSaver.SetScreenSaverTimeout( ssSaveTimeout );

			UpdateSettingsValues( );
		}

		private void UpdateSettingsValues( )
		{
			valueScreensaverActive.Text = ScreenSaver.GetScreenSaverActive( ).ToString( );
			valueScreensaverTimeout.Text = ScreenSaver.GetScreenSaverTimeout( ).ToString( );
			buttonActivate.Text = ( ScreenSaver.GetScreenSaverActive( ) ) ? "Deactivate" : "Activate";
		}

		private void entryScreensaverTimeout_ValueChanged( object sender, EventArgs e )
		{
			ssTimeout = ( int ) entryScreensaverTimeout.Value;
		}

		private void entryKillPeriod_ValueChanged( object sender, EventArgs e )
		{
			killPeriod = ( int ) entryKillPeriod.Value * 1000;	// convert to msec
		}

		private void buttonStartStopTimer_Click( object sender, EventArgs e )
		{
			timerState = ( timerState == RUNNING ) ? STOPPED : RUNNING;

			if( timerState == RUNNING )
			{
				// Start the kill event timer
				killTimer.Change( 0, killPeriod );

				entryKillPeriod.Enabled = false;
				entryScreensaverTimeout.Enabled = false;
				buttonStartStopTimer.Text = "Stop Timer";
			}
			else
			{
				// Stop the kill event from triggering
				killTimer.Change( System.Threading.Timeout.Infinite, killPeriod );

				entryKillPeriod.Enabled = true;
				entryScreensaverTimeout.Enabled = true;
				buttonStartStopTimer.Text = "Start Timer";
			}
		}

		// Kill event timer handler
		private void KillTimer_Elapsed( object state )
		{
			// Toggle kill state to indicate activity
			killState = ( killState == 1 ) ? 0 : 1;
			this.SetText( killState.ToString( ) );

			// Stop the screen saver if it's active and running, otherwise reset the screen saver timer.
			// Apparently it's possible for GetScreenSaverRunning( ) to return TRUE before the
			// screen saver has time to actually become the foreground application. So...
			// Make sure we're not the foreground window to avoid killing ourself.

			if( ScreenSaver.GetScreenSaverActive( ) )
			{
				if( ScreenSaver.GetScreenSaverRunning( ) )
				{
					if( ScreenSaver.GetForegroundWindow( ) != hThisWnd )
						ScreenSaver.KillScreenSaver( );
				}
				else
				{
					// Reset the screen saver timer, so the screen saver doesn't turn on until after a full 
					// timeout period. If killPeriod is less than ssTimeout the screen saver should never activate.
					ScreenSaver.SetScreenSaverActive( TRUE );
				}
			}
		}

		private void SetText( string text )
		{
			// InvokeRequired required compares the thread ID of the
			// calling thread to the thread ID of the creating thread.
			// If these threads are different, it returns true.
			if( valueKillState.InvokeRequired )
			{
				SetTextCallback d = new SetTextCallback( SetText );
				this.Invoke( d, new object[ ] { text } );
			}
			else
			{
				valueKillState.Text = text;
			}
		}

		private void ScreenSaverTest_FormClosing( object sender, FormClosingEventArgs e )
		{
			// Restore original screen saver settings
			ScreenSaver.SetScreenSaverActive( ( ssIsActive ) ? TRUE : FALSE );
			ScreenSaver.SetScreenSaverTimeout( ssSaveTimeout );
		}
	}

	#region ScreenSaver Class

	public static class ScreenSaver
	{
		// Signatures for unmanaged calls
		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern bool SystemParametersInfo( int uAction, int uParam, ref int lpvParam, int flags );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern bool SystemParametersInfo( int uAction, int uParam, ref bool lpvParam, int flags );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern int PostMessage( IntPtr hWnd, int wMsg, int wParam, int lParam );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern IntPtr OpenDesktop( string hDesktop, int Flags, bool Inherit, uint DesiredAccess );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern bool CloseDesktop( IntPtr hDesktop );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern bool EnumDesktopWindows( IntPtr hDesktop, EnumDesktopWindowsProc callback, IntPtr lParam );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		private static extern bool IsWindowVisible( IntPtr hWnd );

		[DllImport( "user32.dll", CharSet = CharSet.Auto )]
		public static extern IntPtr GetForegroundWindow( );

		// Callbacks
		private delegate bool EnumDesktopWindowsProc( IntPtr hDesktop, IntPtr lParam );

		// Constants
		private const int SPI_GETSCREENSAVERACTIVE = 16;
		private const int SPI_SETSCREENSAVERACTIVE = 17;
		private const int SPI_GETSCREENSAVERTIMEOUT = 14;
		private const int SPI_SETSCREENSAVERTIMEOUT = 15;
		private const int SPI_GETSCREENSAVERRUNNING = 114;
		private const int SPIF_SENDWININICHANGE = 2;

		private const uint DESKTOP_WRITEOBJECTS = 0x0080;
		private const uint DESKTOP_READOBJECTS = 0x0001;
		private const int WM_CLOSE = 16;


		// Returns TRUE if the screen saver is active (enabled, but not necessarily running).
		public static bool GetScreenSaverActive( )
		{
			bool isActive = false;

			SystemParametersInfo( SPI_GETSCREENSAVERACTIVE, 0, ref isActive, 0 );
			return isActive;
		}

		// Pass in TRUE(1) to activate or FALSE(0) to deactivate the screen saver.
		public static void SetScreenSaverActive( int Active )
		{
			int nullVar = 0;

			SystemParametersInfo( SPI_SETSCREENSAVERACTIVE, Active, ref nullVar, SPIF_SENDWININICHANGE );
		}

		// Returns the screen saver timeout setting, in seconds
		public static Int32 GetScreenSaverTimeout( )
		{
			Int32 value = 0;

			SystemParametersInfo( SPI_GETSCREENSAVERTIMEOUT, 0, ref value, 0 );
			return value;
		}

		// Pass in the number of seconds to set the screen saver timeout value.
		public static void SetScreenSaverTimeout( Int32 Value )
		{
			int nullVar = 0;

			SystemParametersInfo( SPI_SETSCREENSAVERTIMEOUT, Value, ref nullVar, SPIF_SENDWININICHANGE );
		}

		// Returns TRUE if the screen saver is actually running
		public static bool GetScreenSaverRunning( )
		{
			bool isRunning = false;

			SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0 );
			return isRunning;
		}

		// From Microsoft's Knowledge Base article #140723: http://support.microsoft.com/kb/140723
		// "How to force a screen saver to close once started in Windows NT, Windows 2000, and Windows Server 2003"

		public static void KillScreenSaver( )
		{
			IntPtr hDesktop = OpenDesktop( "Screen-saver", 0, false, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS );
			if( hDesktop != IntPtr.Zero )
			{
				EnumDesktopWindows( hDesktop, new EnumDesktopWindowsProc( KillScreenSaverFunc ), IntPtr.Zero );
				CloseDesktop( hDesktop );
			}
			else
			{
				PostMessage( GetForegroundWindow( ), WM_CLOSE, 0, 0 );
			}
		}

		private static bool KillScreenSaverFunc( IntPtr hWnd, IntPtr lParam )
		{
			if( IsWindowVisible( hWnd ) )
				PostMessage( hWnd, WM_CLOSE, 0, 0 );
			return true;
		}
	}
	#endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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

Share

About the Author

kschulz
Web Developer
United States United States
Kurt's programming career began in 1978, developing firmware for the Zilog Z80-A microprocessor on a Mostek development workstation. For 23 years, Kurt led the development of Human Machine Interface (HMI) programs used in factory automation, marketed and sold worldwide by CTC and Parker Hannifin as ScreenWare, Interact and InteractX. For the last 4 years, Kurt has been consulting on agile development practices and working as an independent software contractor focusing on graphical and user interface development.
 
Other passions include spending time with his wife Janice, daughters Erica and Laura, scuba diving, target shooting, guitar, travel, and digital photo imaging and restoration. Currently residing in southwestern Ohio.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150123.1 | Last Updated 8 Jan 2007
Article Copyright 2007 by kschulz
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid