魅力博客

魅力Linux|魅力空间|魅力博客|学习Linux|ubuntu日记|电脑教程|手机软件

在VC++中侦测Windows NT的屏幕保护状态



开发基于 Windows NT/2000的程序时,程序员往往需要知道系统是否处于屏幕保护状态,然后可以根据不同的状态在程序中做出相应的处理,如改变程序运行的优先级、先执行低优先级的例行工作等,以优化系统性能。微软公司在 Windows 2000操作系统中提供了 SystemParametersInfo() API函数,可以直接返回系统是否处于屏幕保护状态的信息,但是在 Windows NT中并没有提供,只能由程序员自己编程实现。

在 Windows 3.x/9x操作系统上,可以用 API函数 FindWindow()来判断某个程序是否正在运行,对于屏幕保护程序也同样适用。但是此方法在 Windows NT上却无法实现,因为 Windows NT/2000操作系统屏幕保护的实现机制与 Windows 3.x/9x不一样,前者的屏幕保护程序是运行在操作系统为屏幕保护程序单独创建的 "虚拟桌面 "上,因此并不能在当前运行的 "用户桌面 "上找到屏幕保护程序。为此,找到屏幕保护程序的 "虚拟桌面 "成为解决问题的关键。下面给出利用 VC++编写侦测 Windows NT/2000是否处于屏幕保护状态的源代码。

# include

# include

# include

# include

BOOL IsScreenSaverRunning(void)

{

//定义一个 "虚拟桌面 "句柄

HDESK hDesktop;

hDesktop = OpenDesktop(

//操作系统分配给屏幕保护程序 "虚拟桌面 "的标识

TEXT(" screen- saver"),

0,

FALSE,

MAXIMUM_ALLOWED

);

if(hDesktop == NULL) {

//如果打开 "虚拟桌面 "失败

if(GetLastError()==ERROR_ACCESS_DENIED) /*如果是因为访问权限不足,则说明该 "虚拟桌面 "已经存在,只不过是我们的权限不足而已,此时可以判定系统正处于屏幕保护状态。* /

--------------------------------------------------------------------------------

屏幕保护程序是一种特殊的应用程序,如果用户打开了Windows的屏幕保护功能,而且在一特定的时间段内没有任何输入,系统就回自动启动屏幕保护程序。屏幕保护程序有两个作用:

1.防止屏幕长时间显示静态图象而降低荧光介质的寿命。

2.防止用户离开计算机时屏幕上的信息被不相干的人看到。

相应的,屏幕保护程序至少应该实现以下两个功能:

1.动画功能:显示动态的图象。

2.密码校验功能:退出程序时屏蔽一切系统热键(Ctrl+Alt+Del,Alt+Tab,Ctrl+Esc 等,避免用户使用热键关闭程序或切换到其它程序而跳过密码校验),并要求输入授权密码。

我们可以找到不少介绍Windows屏幕保护程序的资料,也可以找到许多制作屏幕保护程序的工具。然而,由于不清楚Windows屏幕保护程序的密码校验功能,所以它们实现的往往只是动画功能,而没有提供密码校验功能。

实际上,Visual C++已经为我们准备好了一个屏幕保护库,使用它,我们可以非常容易的实现Windows屏幕保护程序的一切功能。

介绍Windows屏幕保护库

Windows屏幕保护库为我们提供了

1.WinMain ( )函数:完成程序初始化和消息调度。看到这里,可能有些读者已经想到了:我们不能在MFC中使用Windows屏幕保护库。为什么呢?原因很简单:MFC的底层封装了WinMain( )函数,如果在MFC中使用Windows屏幕保护库,一个程序中就会有两个WinMain( )函数,显然说不过去。因此,我们只有使用Win32 SDK了。

2.DefScreenSaverProc ( )函数:处理键盘、鼠标等消息,实现屏蔽热键及密码校验等功能。

3.一些函数、变量和常量的定义。

大家可以在Visual C++安装目录的Include子目录中找到SCRNSAVE.H文件,通过它,我们可以看到它们具体的定义。

当系统启动一个屏幕保护程序时,WinMain( )函数首先判断系统传递的命令行参数。如果参数指示设置屏幕保护程序,那么WinMain( )函数将会用函数

BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg,

UINT message,

WPARAM wParam,

LPARAM lParam

);

来创建设置对话框并将用户的输入保存到注册表中,还会用函数

BOOL WINAPI RegisterDialogClasses (HANDLE hInst)来注册设置对话框中的特殊窗口类或自定义控件类,如果没有特殊窗口类和自定义控件类,RegisterDialogClasses( )函数只需简单的返回TRUE值。如果参数指示运行屏幕保护程序,WinMain( )函数会调用一些初始化代码来注册窗口类并建立一个全屏窗口。而发送给屏幕保护程序的消息则由函数

LRESULT WINAPI ScreenSaverProc ( HWND hWnd,

UINT message,

WPARAM wParam,

LPARAM lParam

);

处理。我们可以在ScreenSaverProc( )函数中处理下面几个消息(当然也可以处理其它消息):

WM_CREATE 从注册表中获取屏幕保护程序的设置信息

创建一个计时器

处理其它的初始化工作

WM_TIMER 处理绘制工作

WM_DESTORY 销毁计时器

处理其它销毁工作

ScreenSaverProc( )函数未处理的消息则传递给DefScreenSaverProc( )处理。从这里我们可以看出,我们所要做的只是实现ScreenSaverProc( ),ScreenSaverConfigureDialog( )和

RegisterDialogClasses( )三个函数,而麻烦的密码校验和密码更改已经由DefScreenSaverProc( )函数实现了!剩下的就是编译并与Windows屏幕保护程序库连接了。

必须注意的是,Windows屏幕保护程序库对资源ID有一些特殊的要求。首先,它要求有一个ID为IDS_DESCRIPTION(定义为#define IDS_DESCRIPTION 1,见Visual C++目录的Include\SCRNSAVE.H文件),长度小于25的字符串资源,这个字符串将显示在桌面属性对话框屏幕保护程序列表框中。另一个要求是屏幕保护程序的设置对话框的ID必须为DLG_SCRNSAVECONFIGURE(定义为#define DLG_SCRNSAVECONFIGURE 2003)。

下面我们来看一个屏幕保护程序框架的源程序:

(笔者的开发环境为Windows 98和Visual C++ 6.0,由于笔者没有Windows NT,故未考虑Windows NT下的情况。)

屏幕保护程序框架的源程序

/////////////////////// 主程序 ///////////////////////

#include "windows.h"

#include "resource.h"

#include "ScrnSave.h"

LRESULT CALLBACK ScreenSaverProc(HWND hWnd,

UINT message,

WPARAM wParam,

LPARAM lParam

)

{

switch (message)

{

case WM_CREATE:

// 从注册表中获取屏幕保护程序的设置信息

// 创建一个计时器

// 处理其它的初始化工作

return TRUE;

case WM_TIMER:

// 处理绘制工作

return TRUE;

case WM_DESTORY:

// 销毁计时器

// 处理其它销毁工作

return TRUE;

default:

return DefScreenSaverProc(hWnd, message, wParam, lParam);

}

return FALSE;

}

[an error occurred while processing this directive]

BOOL WINAPI ScreenSaverConfigureDialog (HWND hDlg,

UINT message,

WPARAM wParam,

LPARAM lParam

)

{

switch ( message )

{

case WM_INITDIALOG:

// 创建设置对话框并初始化各控件值

return TRUE;

case WM_COMMAND:

if ( LOWORD( wParam ) == IDOK )

{

// 将用户的输入保存到注册表中

EndDialog( hDlg, LOWORD( wParam ) );

return TRUE;

}

else if( LOWORD( wParam ) == IDCANCEL )

{

EndDialog( hDlg, LOWORD( wParam ) );

return TRUE;

}

break;

}

return FALSE;

}

BOOL WINAPI RegisterDialogClasses (HANDLE hInst)

{

// 注册特殊窗口类或自定义窗口类

return TRUE;

}

///////////////////////// Resource.h ////////////////////////////////

//{{NO_DEPENDENCIES}}

// Microsoft Developer Studio generated include file.

// Used by Script1.rc

//

#include "scrnsave.h" // 手工加入

// Next default values for new objects

//

#ifdef APSTUDIO_INVOKED

#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE 102

#define _APS_NEXT_COMMAND_VALUE 40001

#define _APS_NEXT_CONTROL_VALUE 1000

#define _APS_NEXT_SYMED_VALUE 101

#endif

#endif

大家可以在这个屏幕保护程序框架的基础上加入自己的实现。

注意我们必须先创建ID为DLG_SCRNSAVECONFIGURE的对话框资源和ID为IDS_DESCRIPTION的字符串资源,然后将Visual C++产生的Resource.h文件中的对

DLG_SCRNSAVECONFIGURE和IDS_DESCRIPTION的定义删除掉,并在其前部手工加入#include “scrnsave.h”,以保证这些资源能被Windows屏幕保护程序库使用。

编译前(无论是编译Win32 Debug版本还是Win32 Release版本均应做这一步),应先单击Visual C++的Project子菜单中的Settings选项,在弹出的对话框中选择Link选项卡,在其中的Object/library modules编辑框中加入Scrnsave.lib,单击OK,然后就可以编译了。编译完成后,将生成的.EXE改名为.SCR文件,拷贝到Windows系统目录的System子目录中,然后在桌面上单击鼠标右键,选属性,在弹出的对话框中选屏幕保护程序选项卡,并在屏幕保护程序下拉列表框中选中自己的屏幕保护程序,下面就自己去体验吧。

怎么样,用Windows屏幕保护程序库做屏幕保护程序不难吧!看着自己写的屏幕保护程序,感觉很不一样吧!

-----------------------------------------------------------------------------------------------

GetLastInputInfo

------------------------------------------------------------------

首先定义一变量保存GetForegroundWindow句柄

几秒后再次GetForegroundWindow和先保存句柄比较,如果相同且能维持5分钟则比较第二关,并保存这个GetForegroundWindow句柄

EnumProcess取前台窗口路径,如果位于System32目录和扩展名为scr则Call 关机过程。

框架就是这样。

-------------------------------------------------------------------

SystemParametersInfo

或者处理WM_SYSCOMMAND 消息, 参数是 SC_MONITORPOWER, SC_SCREENSAVE等



返回顶部

发表评论:

Powered By Z-BlogPHP 1.7.3


知识共享许可协议
本作品采用知识共享署名 3.0 中国大陆许可协议进行许可。
网站备案号粤ICP备15104741号-1