Preventing Your Monitor from Going to Sleep with Visual Studio 2012

Introduction

Sometimes it is necessary to prevent your monitor from going asleep while your program is active. At the place I work for, I had to develop a program that counts down the amount of time the student has left on his / her exam. Some of the exams are only theoretical. The problem was that either the screensaver popped up after a few minutes or the monitor went to sleep. This caused the student to not know the exact time remaining. This is what we will do today. We will create a small program illustrating how to prevent the monitor from going to sleep or the screensaver from popping up.

There is no design, obviously you’ll have to create a Windows Forms Application with either VB or C#.

Coding

As usual, let us start with the needed Namespaces:

VB.NET

Imports System.Runtime.InteropServices 'APIs
Imports Microsoft.Win32         'For System Events

C#

using System.Runtime.InteropServices; //APIs
using Microsoft.Win32;         //For System Events

Add the following APIs and their constants:

VB.NET

    <FlagsAttribute()> _
    Public Enum EXECUTION_STATE As UInteger ' Determine Monitor State
        ES_AWAYMODE_REQUIRED = &H40
        ES_CONTINUOUS = &H80000000UI
        ES_DISPLAY_REQUIRED = &H2
        ES_SYSTEM_REQUIRED = &H1
        ' Legacy flag, should not be used.
        ' ES_USER_PRESENT = 0x00000004
    End Enum

    'Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
    <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function SetThreadExecutionState(ByVal esFlags As EXECUTION_STATE) As EXECUTION_STATE
    End Function

    'This function queries or sets system-wide parameters, and updates the user profile during the process.
    <DllImport("user32", EntryPoint:="SystemParametersInfo", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function SystemParametersInfo(ByVal uAction As Integer, ByVal uParam As Integer, ByVal lpvParam As String, ByVal fuWinIni As Integer) As Integer
    End Function

        Private Const SPI_SETSCREENSAVETIMEOUT As Int32 = 15

C#

        [FlagsAttribute()]
        public enum EXECUTION_STATE : uint //Determine Monitor State
        {
            ES_AWAYMODE_REQUIRED = 0x40,
            ES_CONTINUOUS = 0x80000000u,
            ES_DISPLAY_REQUIRED = 0x2,
            ES_SYSTEM_REQUIRED = 0x1
            // Legacy flag, should not be used.
            // ES_USER_PRESENT = 0x00000004
        }

        //Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

        //This function queries or sets system-wide parameters, and updates the user profile during the process.
        [DllImport("user32", EntryPoint = "SystemParametersInfo", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);

        private const Int32 SPI_SETSCREENSAVETIMEOUT = 15;

Add the KeepMonitorActive sub:

VB.NET

    Public Sub KeepMonitorActive()

        SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED + EXECUTION_STATE.ES_CONTINUOUS) 'Do not Go To Sleep

    End Sub

C#

        public void KeepMonitorActive()
        {

            SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS); //Do not Go To Sleep

        }

The above sub makes use of the SetThreadExecutionState API. This API, according to MSDN, enables an application to inform the system that it is in use, thereby preventing the system from entering sleep mode or turning off the display while the application is running.

We passed the ES_DISPLAY_REQUIRED field indicating that the display needs to be active, until otherwise stated.

The following sub reverses this effect, by removing the ES_DISPLAY_REQUIRED field. Let us add it now:

VB.NET

    Public Sub RestoreMonitorSettings()

        SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS) 'Restore Previous Settings, ie, Go To Sleep Again

    End Sub

C#

        public void RestoreMonitorSettings()
        {

            SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS); //Restore Previous Settings, ie, Go To Sleep Again

        }

All that is left for us to be able to use the SetThreadExecutionState API is to call these functions:

VB.NET

    Private Sub btnOpt1Off_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpt1Off.Click

        KeepMonitorActive() 'Option 1 On

    End Sub

    Private Sub btnOpt1On_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpt1On.Click

        RestoreMonitorSettings() 'Option 1 Off

    End Sub

C#

        private void btnOpt1On_Click(System.Object sender, System.EventArgs e)
        {

            KeepMonitorActive(); //Option 1 On

        }

        private void btnOpt1Off_Click(System.Object sender, System.EventArgs e)
        {

            RestoreMonitorSettings(); //Option 1 Off

        }

One method is done and dusted now. Let us proceed to using the SystemParametersInfo API. The SystemParametersInfo API queries or sets system-wide parameters, and updates the user profile during the process.

Add the next two events:

VB.NET

    Private Sub tmrMonitor_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrMonitor.Tick

        'Option 2
        SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 5, 0, 0) 'Postpone Sleep For 5 Minutes

    End Sub

    Private Sub btnOpt2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOpt2.Click

        tmrMonitor.Enabled = True 'Start Timer

    End Sub

C#

        private void tmrMonitor_Tick(System.Object sender, System.EventArgs e)
        {

            //Option 2
            SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, 5, "0", 0); //Postpone Sleep For 5 Minutes

        }

        private void btnOpt2_Click(object sender, EventArgs e)
        {

            tmrMonitor.Enabled = true; //Start Timer

        }

We enable the timer and this, via the help of the SystemParametersInfo API, postpones the screen from entering sleep mode for 5 minutes at each recursion.

I am attaching both working samples below, just in case you have missed a step.

Conclusion

In this article I illustrated two methods of sleep mode prevention. Obviously which one you’ll end up using will depend on your preferences as well as your system. Good luck and see you next time!

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read