Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Turn Off Monitor when PC is Locked

4.77/5 (6 votes)
25 Nov 2009CPOL3 min read 45.8K   1.2K  
Turn Off Monitor when PC is locked

Introduction

Energy conservation is among the world’s top priority issues.

By profession, I am a software engineer and work for a software firm. I have taken an initiative towards conservation of energy through GreenUtils.

Background

Most of the Information Technology companies have their power policies in place. For example - there is a power policy to turn off display/monitor automatically if PC remains idle for 10 minutes or standby the system if it is idle for 20 minutes. The idle time is configurable through Windows power policies. These settings helps in saving a good amount of power.

As per my observation, there are additional areas where power savings can be implemented, for example – Turn Off monitor immediately when system is locked. Locking machines is the most common practice being followed by almost all the Information Technology firms. Hence there can be a considerable amount of energy saving if we consider this factor.

GreenMonitor

I have named the application as GreenMonitor and can be freely download from GreenUtils.

Through this article, I would like to share my development experience of GreenMonitor.

I have used Windows terminal services to trap system lock and unlock events. You can register to receive Windows terminal service notification using WTSRegisterSessionNotification(). I have not used global keyboard hooks for two reasons:

  1. Compromise in system’s security
  2. Compromise on system's performance

Below is the code snippet for the usage of WTSRegisterSessionNotification():

C++
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;

    hInst = hInstance; 

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        return FALSE;
    }
    UpdateWindow(hWnd);
    WTSRegisterSessionNotification(hWnd,NOTIFY_FOR_THIS_SESSION);

    return TRUE;
}

I have used WTSRegisterSessionNotification() in InitInstance() method, just after my create window succeeds. I have removed ShowWindow() call from InitInstance() because the application runs in the background and the user should not see any UI.

Once I register my applications handle to window to terminal services, the system sends the following notifications:

C++
WTS_CONSOLE_CONNECT

WTS_CONSOLE_DISCONNECT

WTS_REMOTE_CONNECT

WTS_REMOTE_DISCONNECT

WTS_SESSION_LOGON

WTS_SESSION_LOGOFF

WTS_SESSION_LOCK

WTS_SESSION_UNLOCK

WTS_SESSION_REMOTE_CONTROL 

These notifications are sent to the WndProc method whose handle has been registered using WTSRegisterSessionNotification().

Once I was able to trap windows lock/unlock notifications, I used simple windows SendMessage () to send system command to shutdown the monitor.

Below is the code snippet on how SendMessage can be used to turn off the monitor. For more information on how send message can be used for various monitor operations, click here.

C++
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2); 

The below code snippet shows my WndProc method:

C++
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{

	case WM_DESTROY:

		WTSUnRegisterSessionNotification(hWnd);
		PostQuitMessage(0);
		break;

	case WTS_SESSION_LOCK:

		SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, 
				SC_MONITORPOWER, (LPARAM) 2);
		break; 

	default:

		return DefWindowProc(hWnd, message, wParam, lParam);
	}

return 0;
} 

Architecture

Initially I thought of creating the entire application as a service.

My first version of the software was in fact a service, however I started facing complications when I tried to port my service from XP to Vista and Win 7.

From Vista, Microsoft has tightly implemented the concept of session isolation. Every user runs in a separate session. Services run in session zero. Services should ideally not interact with users. Hence, Microsoft has made session zero non interactive. This concept of session isolation already existed in XP, but was not strictly implemented by Microsoft.

There were two reasons for me why my application should not run as a service:

  • Sending turn off message to monitor in Windows is per session. Click here to find out more on how to use SendMessage() to turn off the display/monitor.
  • Retrieving the last interactive activity on system is again per session. I used GetLastInputInfo() to determine the last time when the user interacted with the system. Finding last input time was important to turn off the monitor if someone accidentally taps the keyboard or moves the mouse when system is in locked state.

Hence I decided to make my application session specific. A separate instance of application runs under each session.

I believe my article would help developers in taking early decisions about complications that could arise if services are made interactive. I have also attached the source code with the article. If you directly wish to download setup, you can download it from here.

Next Article

In my next article, I would like to share my experience of creating an installer for GreenMonitor using Visual Studio 2008.

History

  • 25th November, 2009: Initial post

License

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