屏幕保护程序是以scr为扩展名的标准Windows可执行程序,在激活控制面板的显示器属性的”屏幕保护程序”页时,该模块会自动在Windows启动目录(Windows目录和系统目录)下查找扩展名是scr的基于Windows的可执行文件。使用屏幕保护程序,不仅可以延长显示器的使用寿命,还可以保护私人信息。
编制屏幕保护程序不仅要涉及消息的处理,还要涉及命令行参数的处理。在WIN32SDK文档中描述了编制基于WIN32的标准的屏幕保护程序所必须遵守的严格标准。按照这些标准,屏幕保护程序必须要输出两个函数:ScreenSaverProc和ScreenSaverConfigureDialog,但是,在Windows系统中的很多屏幕保护程序并没有遵循这些标准(使用impdef或者tdump实用工具查看即可)。并且使用该文档中介绍的方法编写屏幕保护程序,不仅要使用资源编辑器,并且在链接时还要利用Scrsaver.lib文件(在C++Builder环境下,不能成功连接)。不仅要涉及消息的处理,还要涉及命令行参数的处理。
C++Builder是一种快速的应用程序开发工具,提供了许多类型的应用程序开发模板,但没有提供开发屏幕保护程序的模板,并且在其在线帮助中也没有提及如何开发这类应用程序。经过本人的研究,找到了用C++Builder3编制屏幕保护程序的方法。
在控制面板的”显示器属性”项的”屏幕保护程序”页中进行设置时,要遇到三种类型的命令行参数,并且,各种情况下的屏幕保护程序的显示结果也各不相同,一般来讲,就需要三种类型的窗体(或两种,在随后的内容中讨论)。下面将分四步来具体地说明如何编制屏幕保护程序。
一、屏幕保护程序的选择
如果在标题为”屏幕保护程序”的下拉列表框中选中了某个保护程序时,系统会自动启动该程序,这个程序的显示范围是在这个页面上的显示器图形的屏幕范围,同时,会将两个命令行参数:一个是”/p”;另一个是显示窗口的句柄,传递给这个被选中的程序。因此,这类程序首先应该能够处理命令行参数。在C++Builder3中,与命令行参数处理有关的函数是:ParamCount()和ParamStr(),具体的申明方式如下:
1 |
1.extern PACKAGE int __fastcall ParamCount(void); |
该函数返回命令行参数的个数,但不包含应用程序本身。
1 |
2.extern PACKAGE AnsiString __fastcall ParamStr(intIndex); |
该函数返回指定索引值的命令行参数。ParamStr(0)返回的是应用程序本身。
所以,在这以步骤中的参数判断的语句如下:
1 2 3 4 5 |
if(UpperCase(ParamStr(1))== "-p"||UpperCase(ParamStr(i))=="/p") { //addthecodeinhere } |
在完成了参数判断后,就应该对显示窗口的处理,为能够使程序在显示器图形的屏幕区域内显示,就要重新设置程序的父窗口和显示区域。这要涉及到父窗口句柄的获得及父窗口的设置,以及API函数的调用。这种环境下的父窗口句柄就是传递过来的第二个命令行参数;要设置父窗口,只需设置窗体的ParentWindow属性即可。这段程序如下:
1 2 3 4 5 6 7 8 9 |
RECTrc;//Line1 HWNDhWnd=(HWND) (atol(ParamStr(2).c_str()));//Line2 ::GetClientRect(hWnd,&rc);//Line3 ParentWindow=hWnd;//Line4 Left=rc.left;//Line5 Top=rc.top;//Line6 Width=rc.right-rc.left;//Line7 Height=rc.bottom-rc.top;//Line8 |
在上面的程序片段中,第2行语句是将传递过来的第2个参数转换成窗口句柄;然后,第3行语句利用这个窗口句柄,调用API函数以获得该窗口的客户区域;第4行语句将选中的屏幕保护程序的父窗口设置为指定的窗口;余下的语句是将该程序的窗口大小设置成副窗口的客户区大小。这一程序片段的位置应该是在窗体的OnCreate事件处理中。
需要说明的是,这种类型(包括第三步介绍的窗体)的窗体样式应是:
1 |
FormStyle=fsStayOnTop; |
窗体边界的样式应为:
1 |
BorderStyle=bsNone; |
当然,这时也不需要鼠标图形,因此,可以将鼠标的形状设为
1 2 |
crNone: Cursor=crNone; |
二、初始化参数的设置
单击”显示器属性”模块的”屏幕保护程序”页面中的”设置”按钮时,系统会启动指定的保护程序的初始值设置对话框,这时传递过来的命令行参数是:”/c”或”-c”(参数的处理与前面介绍的相同)。通过该对话框,可以设置保护程序的一些初始参数,比如图形的变化快慢等。在这段程序中,还要涉及到初始化文件或注册表的读写,用以记录初始化参数,便于保护程序启动时使用。
三、预览及运行
预览的效果就是屏幕保护程序被激活后的显示。单击单击”显示器属性”模块的”屏幕保护程序”页面中的”预览”按钮,就可以观察保护程序运行的实际效果。这时,系统启动该程序时传递过来的命令行参数是:”/s”或”-s”。对于命令行参数的处理与前面的步骤相同,但在这一步中,还要对几个消息进行处理,这些消息是:WM_MOUSEMOVE,WM_LBUTTONDOWN,WM_MBUTTONDOWN,WM_RBUTTONDOWN,WM_KEYDOWN,WM_ACTIVATE。对WM_MOUSEMOVE和WM_ACTIVATE消息的处理形式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void__fastcallHandleSomeMessage(TMessage&Msg) { switch(Msg.Msg) {//...... case WM_ACTIVATE: if(Msg.WParamLo==WA_INACTIVE) Close(); break; case WM_MOUSEMOVE: if(OldMouseX==-1&&OldMouseY==-1) //Intheconstructor,OldMouseXand OldMouseYmustbeinitializedby-1. { OldMouseX=Msg.LParamLo; OldMouseY=Msg.LParamHi; } else if(OldMouseX!=Msg.LParamLo || OldMouse!=Msg.LParamHi) Close(); break; ...... } } |
对于其他的消息仅仅是调用Close()函数来关闭应用程序即可。应用这种消息处理方式时,必须要类定义时进行消息映射,不然的话,就要在相应的消息响应中进行处理(使用一定的布尔变量,就可以与第一步合用一个窗体)。
与第一步类似,在该步骤中,也不需要具体的鼠标指针的形状,因此,将鼠标指针设为
1 2 |
crNone: Cursor=crNone; |
四、修改项目源文件
在C++Builder中,一个窗体也就是一个类,换句话说,具有某些特性的类也就是一个窗体,因此,编制屏幕保护程序时,也不需要什么主窗体,同时,也不用自动创建某些窗体了,这时就要修改项目源文件,下面所列出的程序就是笔者在编制某屏幕保护程序时使用的项目源文件,供读者参考。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { CreateMutex(NULL,true,"ScreenSaver"); if(GetLastError()!=ERROR_ALREADY_EXISTS) { try { Application->Initialize(); Application->Title="屏幕保护程序测试"; if(UpperCase(ParamStr(1))== "/C"||UpperCase(ParamStr(1))=="-C" ||ParamCount()==0) { TScrSaverConfiguerF* ScrCfg= newTScrSaverConfiguerF(NULL); ScrCfg->ShowModal(); delete ScrCfg; return 0; }//单击"设置"按钮 elseif(UpperCase(ParamStr(1))== "/P"||UpperCase(ParamStr(1))=="-P") { TScrForP* ScrFP=newTScrForP(NULL); ScrFP->ShowModal(); delete ScrFP; return 0; }//在"屏幕保护程序"下拉列表框中选择一个程序 else if(UpperCase(ParamStr(1))== "/S"||UpperCase(ParamStr(1))=="-S") { TScreenSaveF* ScreenSave=newTScreenSaveF(NULL); ScreenSave->ShowModal(); delete ScreenSave; return0; }//单击"预览"按钮,及运行屏幕保护程序 else return 1; } catch(Exception& exception) { Application->ShowException(&exception); } } return 0; }//theWinMainFunctionend |
前面介绍了在C++Builder下编制屏幕保护程序的方法.对于C++Builder这种RAD工具来讲,开发这类程序也是相当方便的,按照前述的方法,可以在极短的时间开发出屏幕保护程序。对于屏幕保护程序。