65.9K
CodeProject 正在变化。 阅读更多。
Home

PC 锁定后关闭显示器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (6投票s)

2009年11月25日

CPOL

3分钟阅读

viewsIcon

46469

downloadIcon

1208

PC 锁定后关闭显示器

引言

节能是当今世界最重要的优先事项之一。

我是一名软件工程师,在一个软件公司工作。我发起了一项名为 GreenUtils 的倡议,以促进节能。

背景

大多数信息技术公司都有自己的电源策略。例如,有一个电源策略,如果 PC 空闲 10 分钟,将自动关闭显示器/监视器,如果空闲 20 分钟,则使系统进入待机状态。空闲时间可以通过 Windows 电源策略进行配置。这些设置有助于节省大量电力。

根据我的观察,在其他一些方面也可以实现节能,例如 – 在系统锁定后立即关闭显示器。锁定计算机是几乎所有信息技术公司都在遵循的最常见的做法。因此,如果我们考虑这一点,可以实现可观的节能。

GreenMonitor

我将该应用程序命名为 GreenMonitor,可以从 GreenUtils 免费下载。

通过本文,我希望分享我在开发 GreenMonitor 过程中的经验。

我使用了 Windows 终端服务来捕获系统锁定和解锁事件。您可以使用 WTSRegisterSessionNotification() 注册以接收 Windows 终端服务通知。我没有使用全局键盘钩子,原因有两个:

  1. 影响系统安全
  2. 影响系统性能

下面是 WTSRegisterSessionNotification() 用法代码片段。

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;
}

我在 InitInstance() 方法中使用了 WTSRegisterSessionNotification(),在创建窗口成功后立即进行。我从 InitInstance() 中移除了 ShowWindow() 调用,因为应用程序在后台运行,用户不应看到任何用户界面。

一旦我将应用程序句柄注册到终端服务,系统就会发送以下通知:

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 

这些通知会发送到使用 WTSRegisterSessionNotification() 注册的句柄的 WndProc 方法。

一旦我能够捕获 Windows 锁定/解锁通知,我就使用简单的 Windows SendMessage () 向系统发送命令来关闭显示器。

下面是如何使用 SendMessage 来关闭显示器的代码片段。有关如何使用 SendMessage 进行各种显示器操作的更多信息,请单击此处

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

下面的代码片段显示了我的 WndProc 方法。

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;
} 

架构

最初,我曾想将整个应用程序作为一个服务来创建。

我的软件的第一个版本确实是一个服务,但当我尝试将我的服务从 XP 移植到 Vista 和 Win 7 时,我开始遇到困难。

从 Vista 开始,微软严格实施了会话隔离的概念。每个用户都在单独的会话中运行。服务运行在会话零中。服务理想情况下不应与用户交互。因此,微软使会话零成为非交互式的。会话隔离的概念在 XP 中已经存在,但微软没有严格实施。

我的应用程序不应该作为服务运行,原因有两个:

  • 在 Windows 中向显示器发送关闭消息是按会话进行的。请单击此处了解更多关于如何使用 SendMessage() 关闭显示器/监视器。
  • 检索系统上的最后一次交互活动也是按会话进行的。我使用了 GetLastInputInfo() 来确定用户最后一次与系统交互的时间。获取最后一次输入时间对于关闭显示器至关重要,以防有人在系统处于锁定状态时不小心按了键盘或移动了鼠标。

因此,我决定使我的应用程序成为会话特定的。应用程序的独立实例在每个会话下运行。

我相信我的文章将有助于开发人员及早决定关于将服务设置为交互式可能带来的复杂性。我也在文章中附上了源代码。如果您想直接下载安装程序,可以从此处下载。

下一篇文章

在我的下一篇文章中,我将分享我使用 Visual Studio 2008 为 GreenMonitor 创建安装程序的经验。

历史

  • 2009 年 11 月 25 日:初始发布
© . All rights reserved.