用C++Builder开发Windows下的屏保.docx
《用C++Builder开发Windows下的屏保.docx》由会员分享,可在线阅读,更多相关《用C++Builder开发Windows下的屏保.docx(11页珍藏版)》请在冰豆网上搜索。
用C++Builder开发Windows下的屏保
用C++Builder开发Windows下的屏保
摘要:
本文通过一个具体的程序演示了Windows下的屏幕保护程序的实现过程。
一.引言
视窗系统下的屏幕保护程序是一个基于命令行(CommandLine)的应用程序。
当屏保程序被调用时操作系统就用具体的命令行执行该程序。
本文组织和处理了所有的命令行,包括“/p”,“/s”,“/c”,“/a”,其中“/p”表示让屏保在预览窗口中显示;“/s”表示真正运行屏保;“/c”表示调用设置对话框;而“/a”表示调用密码设置对话框(WinNT中无效)。
本程序尽可能简单地实现一个全功能的屏保,运行Windows的屏保设置程序时你既可以修改密码(WinNT中无效)又可以设置图片显示的频率并把频率数值保存到注册表里。
当屏保运行时图片以你设置的频率改变显示位置。
笔者还留了个作业给读者,请看图1中的选择图片文件夹这个项目,按下浏览按钮可以设置图片的路径,笔者已经实现了浏览按钮的功能并
把得到的路径也保存到注册表中,并让屏保启动时读picdir的值,picdir等于"no"时的代码笔者已实现了,picdir不等于"no"时的代码由读者实现。
也就是让读者实现一个能把picdir目录里的图片轮流显示的屏保程序。
二.实现方法
首先介绍几个API函数。
WinMain函数:
intWINAPIWinMain(
HINSTANCEhInstance,//当前实例句柄
HINSTANCEhPrevInstance,//前一个实例句柄
LPSTRlpCmdLine,//指向命令行参数的指针(本程序要利用的参数)
intnCmdShow //窗口的状态
);
GetWindowLong函数:
得到指定窗口信息的函数
LONGGetWindowLong(
HWNDhWnd,//窗/口句柄
intnIndex //指/定返回的信息
);
SetWindowLong函数:
改变窗口属性
LONGSetWindowLong(
HWNDhWnd,//窗/口句柄
intnIndex,//指定要设定的值的信息
LONGdwNewLong //新值
);
SetParent函数:
改变指定窗口的父窗口
HWNDSetParent(
HWNDhWndChild,//要/改变父窗体的窗口句柄
HWNDhWndNewParent //新/的父窗体的句柄
);
GetClientRect函数:
得到窗口的客户区
BOOLGetClientRect(
HWNDhWnd,//窗口句柄
LPRECTlpRect //RECT/结构的地址
);
SetWindowPos函数:
改变窗口的大小,位置,顶级窗口等
BOOLSetWindowPos(
HWNDhWnd,//窗口句柄
HWNDhWndInsertAfter,//布置窗口顺序的句柄(Zorder)
intX,//horizontalposition
intY,//verticalposition
intcx,//width
intcy,//height
UINTuFlags //窗口位置等标记
);
SystemParametersInfo函数:
访问或设置系统级的参数
BOOLSystemParametersInfo(
UINTuiAction,//指定要获取或设置的系统参数
UINTuiParam,//dependsonactiontobetaken
PVOIDpvParam,//dependsonactiontobetaken
UINTfWinIni //用户配置文件是否改变标记
);
ShowCursor函数:
显示或隐藏光标
intShowCursor(
BOOLbShow //鼠标可见度标记
);
GetVersion函数:
获取系统的版本信息
DWORDGetVersion(VOID)
以上API函数的具体信息可以查找有关MSSDK文档。
了解了基本函数后笔者简述一下实现方法。
1.新建一工程,增加两个窗体,将三个窗体分别取名为MainForm,FrmConfig,FrmControl。
在MainForm和FrmControl窗体上各添加一个Timer控件和TImage控件,把两窗体的BorderStyle设为bsNone,背景色设为黑色。
在两个窗体的TImage上各加一张图片,FrmControl大小设为:
高130像素,宽160像素,Timage的Stretch属性设为真值。
FrmConfig的样式如图1。
2.保存工程文件为screensaver.cpp,其它单元分别存为Unitmain.cpp,
Unitcontrol.cpp,Unitconfig.cpp。
3.编写代码,具体代码见第三部分的源程序。
4.编译成可执行文件,并把文件扩展名改为scr。
5.最后把屏保程序拷贝到windows目录下就可以测试了。
如果一切正常的话你将会看
到图片在屏幕上以随机的位置显示。
三.源代码
以下是本程序的所有的源代码,其中screensaver.cpp,Unitmain.cpp是核心代码。
/*{*******************************}*/
/*{*****screensaver.cpp ****}*/
/*{*******************************}*/
//---------------------------------------------------------------------------/
#include
#pragmahdrstop
USERES("screensaver.res");
USEFORM("Unitmain.cpp",Frmmain);
USEFORM("Unitconfig.cpp",FrmConfig);
USEFORM("Unitcontrol.cpp",FrmControl);
//---------------------------------------------------------------------------/
WINAPIWinMain(HINSTANCE,HINSTANCE,LPSTRp,int)//“p"是指向命令行参数的指针
{StringStartType;
AnsiStringCommand=p,temp;
HWNDCPWindow=NULL;
if(Command=="")
StartType="/c";
else
StartType=Command.SubString(1,2);//获取命令行的前两个参数
try
{
Application->Initialize();
if(StartType=="/c")//启动设置窗口
Application->CreateForm(__classid(TFrmConfig),&FrmConfig);
elseif(StartType=="/s")启动屏保
Application->CreateForm(__classid(TFrmmain),&Frmmain);
elseif(StartType=="/p")//预览
{
Application->CreateForm(__classid(TFrmControl),&FrmControl);
temp=Command.SubString(3,Command.Length()-2);//获取命令行中的屏保预览窗口句柄的字符串形式
CPWindow=(long*)temp.ToInt();//将预览窗口句柄的字符串形式强制转换为长整形指针
RECT*lookrect;//建立一个RECT结构指针
Longstyle=GetWindowLong(Application->MainForm->Handle,GWL_STYLE);//获取FrmControl窗口的风格
style=style|WS_CHILD;
SetWindowLong(Application->MainForm->Handle,GWL_STYLE,style);//设置窗口为子窗口
SetParent(Application->MainForm->Handle,CPWindow);//设置屏保预览窗口为FrmControl的父窗口
GetClientRect(CPWindow,lookrect);//获取屏保预览窗口的客户区
SetWindowPos(Application->MainForm->Handle,HWND_TOP,0,0,lookrect->right,lookrect->bottom,SW
P_NOZORDER|SWP_NOACTIVATE|SWP_SHOWWINDOW);//将FrmControl的窗口覆盖屏保预览窗口的客户区,并显示它
}
elseif(StartType=="/a")//启动密码设置窗口
{
temp=Command.SubString(3,Command.Length()-2);
CPWindow=(long*)temp.ToInt();//以下是动态调用mpr.dll里的PwdChangePasswordA函数的过程
typedefUINT(CALLBACK*FUN)(LPSTR,HWND,UINT,UINT);
HINSTANCEhDll=LoadLibrary("mpr.DLL");
FUNmyfun;
if(hDll!
=NULL)
{
myfun=(FUN)GetProcAddress(hDll,"PwdChangePasswordA");
if(!
myfun)FreeLibrary(hDll);
else
myfun("SCRSAVE",CPWindow,0,0);//函数的调用
}
}
Application->Run();
}
catch(Exception&exception)
{
Application->ShowException(&exception);
}
return0;
}
//---------------------------------------------------------------------------/
/*{*******************************}*/
/*{***** Unitmain.h ****}*/
/*{*******************************}*/
//---------------------------------------------------------------------------/
#ifndefUnitmainH
#defineUnitmainH
//---------------------------------------------------------------------------/
#include
#include
#include
#include
#include
#include
#include
//---------------------------------------------------------------------------/
classTFrmmain:
publicTForm
{
__published:
//IDE-managedComponents
TTimer*Timer1;
TImage*Image1;
void__fastcallFormCreate(TObject*Sender);
void__fastcallFormKeyDown(TObject*Sender,WORD&Key,
TShiftStateShift);
void__fastcallFormMouseDown(TObject*Sender,TMouseButtonButton,
TShiftStateShift,intX,intY);
void__fastcallFormCloseQuery(TObject*Sender,bool&CanClose);
void__fastcallFormClose(TObject*Sender,TCloseAction&Action);
void__fastcallImage1MouseDown(TObject*Sender,
TMouseButtonButton,TShiftStateShift,intX,intY);
void__fastcallImage1MouseMove(TObject*Sender,TShiftStateShift,
intX,intY);
void__fastcallTimer1Timer(TObject*Sender);
private:
//Userdeclarations
DWORDPWProtect;
DWORDVersion;
Stringpicdir;
intfrequence;
public:
//Userdeclarations
__fastcallTFrmmain(TComponent*Owner);
};
//---------------------------------------------------------------------------/
externPACKAGETFrmmain*Frmmain;
//---------------------------------------------------------------------------/
#endif
//---------------------------------------------------------------------------/
/*{*******************************}*/
/*{***** Unitmain.cpp ****}*/
/*{*******************************}*/
//---------------------------------------------------------------------------/
#include
#pragmahdrstop
#include
#include"Unitmain.h"
#include
//---------------------------------------------------------------------------/
#pragmapackage(smart_init)
#pragmaresource"*.dfm"
TFrmmain*Frmmain;
//---------------------------------------------------------------------------/
__fastcallTFrmmain:
:
TFrmmain(TComponent*Owner)
:
TForm(Owner)
{
}
//---------------------------------------------------------------------------/
void__fastcallTFrmmain:
:
FormCreate(TObject*Sender)
{
//使窗口成为最顶层的窗口
SetWindowPos(this->Handle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
//时窗口覆盖屏幕
this->Width=Screen->Width;
this->Height=Screen->Height;
this->Top=0;
this->Left=0;
Version=GetVersion();
TRegistry*Registry=newTRegistry;
try
{
if(Version>0x80000000){
Registry->RootKey=HKEY_CURRENT_USER;
Registry->OpenKey("\ControlPanel\Desktop",false);
PWProtect=Registry->ReadInteger("ScreenSaveUsePassword");//检测是否密码保护
Registry->CloseKey();}
Registry->RootKey=HKEY_CURRENT_USER;
Registry->OpenKey("\Software\CODEHUNTER",true);
picdir=Registry->ReadString("PicDir");//得到图片目录
frequence=Registry->ReadInteger("frequence");//得到图像显示的频率
if(picdir=="")picdir="no";
if(frequence<0||frequence>6)frequence=2;
Timer1->Interval=1000*frequence;设置定时器
}
__finally
{
deleteRegistry;
picdir="no";
}
//检测是否运行于NT下
if(Version!
=0)
if(PWProtect&&Version>0x80000000)//如果系统要求密码保护并此系统为非NT那么把系统设为屏保状态使光标消失
SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,0,0);
while(!
ShowCursor(false)<-5);
}
//---------------------------------------------------------------------------/
void__fastcallTFrmmain:
:
FormKeyDown(TObject*Sender,WORD&Key,
TShiftStateShift)
{
this->Close();
}
//---------------------------------------------------------------------------/
void__fastcallTFrmmain:
:
FormMouseDown(TObject*Sender,
TMouseButtonButton,TShiftStateShift,intX,intY)
{
this->Close();
}
//---------------------------------------------------------------------------/
void__fastcallTFrmmain:
:
FormCloseQuery(TObject*Sender,bool&CanClose)
{
if(PWProtect&&Version>0x80000000)
{
boolPassChck;
//显/示光标,并调用密码对话框
while(!
ShowCursor(True)>5);
//以/下是VerifyScreenSavePwd函数的动态调用
typedefUINT(CALLBACK*FUN)(HWND);
HINSTANCEhDll=LoadLibrary("password.cpl");
FUNmyfun;