分享
 
 
 

[翻译]自己翻译着玩之一:处理屏幕保护程序

王朝other·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

处理屏幕保护程序

Microsoft® Win32® 应用编程接口(API)支持称作屏幕保护程序的特殊程序。屏幕保护程序在鼠标和键盘空闲指定的一段时间后开始运行。它们用于这两个原因:

防止屏幕上的荧光粉被表态图像烧坏。隐藏屏幕上的敏感信息。本文被分成下面两个小节。

关于屏幕保护程序使用屏幕保护程序函数并于屏幕保护程序

Microsoft® Windows®控制面板中的显示程序让用户从一个列表中选择屏幕保护程序,指定屏幕保护程序应该在系统空闲多久之后启动,配置,以及预览屏幕保护程序。屏幕保护程序可以由Windows自动启动或者由用户通过控制面板来启动。

一旦选择了屏幕保护程序,Windows便监视键盘和鼠标动作并在其静止一段时间后启动屏保。然而,Windows在下列任意一种情况下不会启动屏保:

活动的应用程序不是一个基于Windows的程序。一个computer-based training(CBT)窗口在显示。活动的应用程序收到一个wParam参数为SC_SCREENSAVE的WM_SYSCOMMAND消息,但是它没有把消息传给DefWindowProc函数。屏保程序包含一些特定的导出函数,资源定义,和变量声明。屏保程序包含main函数和其它对屏保程序必要的启动代码。当一个屏保程序启动时,该屏保程序库中的启动代码会创建一个全屏窗口。这一窗口的窗口类声明如下:

WNDCLASS cls;

cls.hCursor = NULL;

cls.hIcon = LoadIcon(hInst, MAKEINTATOM(ID_APP));

cls.lpszMenuName = NULL;

cls.lpszClassName = "WindowsScreenSaverClass";

cls.hbrBackground = GetStockObject(BLACK_BRUSH);

cls.hInstance = hInst;

cls.style = CS_VREDRAW | CS_HREDRAW |

CS_SAVEBITS | CS_DBLCLKS;

cls.lpfnWndProc = (WNDPROC) ScreenSaverProc;

cls.cbWndExtra = 0;

cls.cbClsExtra = 0;

为了创建一个屏保程序,多数开发者会创建一个包含三个必需函数的源码模块并将它们与屏保程序库链接。屏保模块仅负责自身的配置及提供可视化效果。

屏保程序模块所需的三个函数中的一个是ScreenSaverProc。这个函数处理特定的消息并将任何不处理的消息传回到屏保程序库。下面是ScreenSaverProc处理的一些典型消息。

消息

含义

WM_CREATE

从Regedit.ini文件获取初始化数据。为屏保窗口设置一个窗口定时器。执行其它必要操作。

WM_ERASEBKGND

擦除屏保窗口,为紧接着的绘制操作作准备。

WM_TIMER

执行绘制操作。

WM_DESTROY

销毁应用程序处理WM_CREATE消息时创建的定时器。执行其它必要的清理。

ScreenSaverProc通过调用DefScreenSaverProc函数将不处理的消息传给屏保程序库。下表说明了这个函数如何处理各种消息。

消息

动作

WM_SETCURSOR

将鼠标指针设为空指针,以从屏幕上移除。

WM_PAINT

绘制窗口背景。

WM_LBUTTONDOWN

终止屏保程序。

WM_MBUTTONDOWN

终止屏保程序。

WM_RBUTTONDOWN

终止屏保程序。

WM_KEYDOWN

终止屏保程序。

WM_MOUSEMOVE

终止屏保程序。

WM_ACTIVATE

如果wParam被设置为FALSE则终止屏保程序。

屏保程序模块必需的第二个函数是ScreenSaverConfigureDialog。这个函数显示一个对话框以允许用户对屏保程序进行配置(应用程序必须提供相应的对话框模板)。Windows在用户点击控制面板中屏保程序对话框中的设置按钮时显示这个配置对话框。

屏保程序模块必需的第三个函数是函数是RegisterDialogClasses。这个函数必须被所有的屏保程序调用。然而,配置对话框中不需要特殊窗口或者自定义控件的程序可以简单地返回TRUE。需要特殊窗口或者自定义控件的程序应该用这个函数来注册相应的窗口类。

除了创建一个支持刚才所描述的这三个函数的模块之外,屏保程序还应该提供一个图标。这个图标只在屏保程序作为一个独立的程序运行时才可见。(为了通过控制面板来运行,屏保程序必须以.scr作为文件的扩展名。)图标必须在屏保程序的资源文件中通过ID_APP来标识,该值的定义在Scrnsave.h头文件中。

最后一个必要条件是一个屏保程序描述字符串。屏保程序的资源文件中必须包含一个被控制面板用来显示作为其名字的字符串。描述字符串必须是其资源文件的字符串表中的第一个字符串(用常数1来标识)。

使用屏保程序函数

本节通过从屏保程序中截取下来的示例代码来说明如下任务:

创建一个屏保程序安装新屏保程序为屏保程序配置对话框添加帮助创建一个屏保程序

该程序以1到10秒范围内的时间间隔以这四中颜色中的一个来重绘屏幕:白色,淡灰,深灰,和黑色。程序在每收到一个WM_TIMER消息时绘制窗口。用户可以通过调节程序的配置对话框中的滚动条来调整这个消息发送的间隔时间。

屏保程序库

静态屏保程序函数包含在屏保程序库中。该库有两个可用版本,Scrnsave.lib和Scrnsavw.lib。你必须将你的工程链接到其中的一个。Scrnsave.lib用于使用ANSI字符集的屏保程序,Scrnsavw.lib则用于使用UNICODE字符集的程序。用Scrnsavw.lib链接的屏保程序只能在支持UNICODE的Windows平台上运行,而用链接的屏保程序则可以在任何Windows平台上运行。

对配置对话框的支持

多数屏保程序提供了一个配置对话框以便用户指定一些自定义数据,如唯一颜色,绘制速度,线宽,字体等待。为了支持配置对话框,程序必须提供一个对话框模板并且必须支持ScreenSaverConfigureDialog函数。下面是示例程序的对话框模板。

DLG_SCRNSAVECONFIGURE DIALOG 6, 18, 160, 63

LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION |

WS_SYSMENU

CAPTION "Sample Screen-Saver Setup"

FONT 8, "MS Shell Dlg"

BEGIN

GROUPBOX "Redraw Speed", 101, 0, 6, 98, 40

SCROLLBAR ID_SPEED, 5, 31, 89, 10

LTEXT "Fast", 103, 6, 21, 20, 8

LTEXT "Slow", 104, 75, 21, 20, 8

PUSHBUTTON "OK", ID_OK, 117, 10, 40, 14

PUSHBUTTON "Cancel", ID_CANCEL, 117, 32, 40, 14

END

你必须将标识对话框模板的的常数定义为十进制数2003,像下面的例子这样:

#define DLG_SCRNSAVECONFIGURE 2003

下面的例子显示了示例程序中的创建的ScreenSaverConfigureDialog函数。

#define MINVEL 1 /* minimum redraw speed value */

#define MAXVEL 10 /* maximum redraw speed value */

#define DEFVEL 5 /* default redraw speed value */

LONG lSpeed = DEFVEL; /* redraw speed variable */

extern HINSTANCE hMainInstance; /* screen saver instance handle */

CHAR szAppName[80]; /* .ini section name */

CHAR szTemp[20]; /* temporary array of characters */

CHAR szRedrawSpeed[ ] = "Redraw Speed"; /* .ini speed entry */

BOOL WINAPI ScreenSaverConfigureDialog(hDlg, message, wParam, lParam)

HWND hDlg;

UINT message;

DWORD wParam;

LONG lParam;

{

static HWND hSpeed; /* handle to speed scroll bar */

static HWND hOK; /* handle to OK push button */

switch(message)

{

case WM_INITDIALOG:

/* Retrieve the application name from the .rc file. */

LoadString(hMainInstance, idsAppName, szAppName, 40);

/* Retrieve the .ini (or registry) file name. */

LoadString(hMainInstance, idsIniFile, szIniFile,

MAXFILELEN);

/* Retrieve any redraw speed data from the registry. */

lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed,

DEFVEL, szIniFile);

/*

* If the initialization file does not contain an entry

* for this screen saver, use the default value.

*/

if(lSpeed > MAXVEL || lSpeed < MINVEL)

lSpeed = DEFVEL;

/* Initialize the redraw speed scroll bar control. */

hSpeed = GetDlgItem(hDlg, ID_SPEED);

SetScrollRange(hSpeed, SB_CTL, MINVEL, MAXVEL, FALSE);

SetScrollPos(hSpeed, SB_CTL, lSpeed, TRUE);

/* Retrieve a handle to the OK push button control. */

hOK = GetDlgItem(hDlg, ID_OK);

return TRUE;

case WM_HSCROLL:

/*

* Process scroll bar input, adjusting the lSpeed

* value as appropriate.

*/

switch (LOWORD(wParam))

{

case SB_PAGEUP:

--lSpeed;

break;

case SB_LINEUP:

--lSpeed;

break;

case SB_PAGEDOWN:

++lSpeed;

break;

case SB_LINEDOWN:

++lSpeed;

break;

case SB_THUMBPOSITION:

lSpeed = HIWORD(wParam);

break;

case SB_BOTTOM:

lSpeed = MINVEL;

break;

case SB_TOP:

lSpeed = MAXVEL;

break;

case SB_THUMBTRACK:

case SB_ENDSCROLL:

return TRUE;

break;

}

if ((int) lSpeed <= MINVEL)

lSpeed = MINVEL;

if ((int) lSpeed >= MAXVEL)

lSpeed = MAXVEL;

SetScrollPos((HWND) lParam, SB_CTL, lSpeed, TRUE);

break;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_OK:

/*

* Write the current redraw speed variable to

* the .ini file.

*/

wsprintf(szTemp, "%ld", lSpeed);

WritePrivateProfileString(szAppName, szRedrawSpeed,

szTemp, szIniFile);

case ID_CANCEL:

EndDialog(hDlg, LOWORD(wParam) == ID_OK);

return TRUE;

}

}

return FALSE;

}

除了提供对话框模板和支持ScreenSaverConfigureDialog函数之外,程序还必须支持RegisterDialogClasses函数。这个函数用来注册任何屏保程序所需要的非标准窗口类。因为示例程序在其对话框过程中只使用了标准窗口类,这个函数只是简单地返回了TRUE,如下面代码这样:

BOOL WINAPI RegisterDialogClasses(hInst)

HANDLE hInst;

{

return TRUE;

}

支持屏保窗口过程

每个屏保程序都必须支持一个名称为ScreenSaverProc的窗口过程。代多数窗口过程一个,ScreenSaverProc处理一系列特定消息并将任何不处理的消息传给默认过程。然而,ScreenSaverProc是将不处理的消息传给DefScreenSaverProc,而不是DefWindowProc。ScreenSaverProc有别于普通窗口过程的另一点是传给ScreenSaverProc的句柄标识的是整个桌面而不是一个客户窗口。下面的例子显示了示例屏保程序的ScreenSaverProc窗口过程。

LONG WINAPI ScreenSaverProc(hwnd, message, wParam, lParam)

HWND hwnd;

UINT message;

DWORD wParam;

LONG lParam;

{

static HDC hdc; /* device-context handle */

static RECT rc; /* RECT structure */

static UINT uTimer; /* timer identifier */

switch(message)

{

case WM_CREATE:

/* Retrieve the application name from the .rc file. */

LoadString(hMainInstance, idsAppName, szAppName, 40);

/* Retrieve the .ini (or registry) file name. */

LoadString(hMainInstance, idsIniFile, szIniFile,

MAXFILELEN);

/* Retrieve any redraw speed data from the registry. */

lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed,

DEFVEL, szIniFile);

/*

* Set a timer for the screen saver window using the

* redraw rate stored in Regedit.ini.

*/

uTimer = SetTimer(hwnd, 1, lSpeed * 1000, NULL);

break;

case WM_ERASEBKGND:

/*

* The WM_ERASEBKGND message is issued before the

* WM_TIMER message, allowing the screen saver to

* paint the background as appropriate.

*/

hdc = GetDC(hwnd);

GetClientRect (hwnd, &rc);

FillRect (hdc, &rc, GetStockObject(BLACK_BRUSH));

ReleaseDC(hwnd,hdc);

break;

case WM_TIMER:

/*

* The WM_TIMER message is issued at (lSpeed * 1000)

* intervals, where lSpeed == .001 seconds. This

* code repaints the entire desktop with a white,

* light gray, dark gray, or black brush each

* time a WM_TIMER message is issued.

*/

hdc = GetDC(hwnd);

GetClientRect(hwnd, &rc);

if (i++ <= 4)

FillRect(hdc, &rc, GetStockObject(i));

else

(i = 0);

ReleaseDC(hwnd,hdc);

break;

case WM_DESTROY:

/*

* When the WM_DESTROY message is issued, the screen saver

* must destroy any of the timers that were set at WM_CREATE

* time.

*/

if (uTimer)

KillTimer(hwnd, uTimer);

break;

}

/*

* DefScreenSaverProc processes any messages

* ignored by ScreenSaverProc.

*/

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

}

创建一个模块定义文件

ScreenSaverProcScreenSaverConfigureDialog函数必须通过程序的模块定义文件导出;但RegisterDialogClasses不应该被导出。下面的例子显示了示例程序的模块定义文件。

NAME SSTEST.SCR

DESCRIPTION 'SCRNSAVE : Test'

STUB 'WINSTUB.EXE'

EXETYPE WINDOWS

CODE MOVEABLE

DATA MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 4096

EXPORTS

ScreenSaverProc

ScreenSaverConfigureDialog

安装新屏保程序

控制面板在构造可用屏保程序列表时会搜索Windows启动目录中扩展名为.scr的文件。因为屏保程序是扩展名为.exe的标准Windows可执行文件,你必须对其重命名以使其扩展名为.scr,并将其拷贝到正确的目录。

为屏保程序配置对话框添加帮助

典型的屏保程序配置对话框中包含有一个帮助按钮。屏保程序可以用与其它基于Windows的程序一样的方式检查帮助按钮标识符并调用WinHelp函数。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有