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!