屏幕保护程序
青岛理工大学
课程设计
院(系): 计算机工程学院 专业: 计算机科学与技术 学生姓名: 谯朝禄 班级: 计算102 学号: 201007054 题目: 屏幕保护程序
起迄日期: 2012.06.18—2012.06.29 设计地点: 计算机学院机房 指 导 教 师: 李 兰
完成日期: 2010 年 6月 29日
目录:
一、设计目的2„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„ 二、需求
2 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„三、运行环境2 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„四、功能要求2 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„五、总体设计4 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„
1.系统功能模块图 4 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„
2. 程序流程图4 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„
3(类的继承关系5 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„
4(关键代码5 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„六、运行效果9„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„ 七、设计总结9 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„八、用户使用手册10 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„九、参考文献10 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„十、附录10 „„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„
~ 1 ~
一、设计目的
windows屏幕保护是因为普通非液晶显示期是用阴极管发射电子来击打屏幕产生图像的,如果长期固定在一个画面不动,会对显示器造成损害,现在的液晶显示器就没有了这个问题,而大多数人为了好看还设置了屏幕保护,但是这也让各种花样屏幕保护应运而生。并且自己觉得写屏幕保护程序是一件很有趣的事情。
二、需求分析
1( 选作屏幕保护程序的设计题目,主要是基于了解在电脑上的屏幕保护的功能是
如何实现的,以及在MFC平台是怎么实现功能调用的,从而可以进一步的了解到c++是
如何面向对象的程序设计,以及学习一些基本的MFC相关的知识。熟练掌握类的继承、
多态和构造函数,以及在VC++6.0的软件的一些扩展功能。了解编程的实际用处,增加
对编程更深入的了解,对自己所学的知识更加深入的学习与掌握。
2( 通过本次实验主要实现屏幕保护程序的基本功能,本程序可以安装在
windowsXP/7中并且像windows系统里面的屏幕保护程序一样运行。因为屏幕保护程序
并不是真的是个应用程序,它只不过是操作系统在你离开键盘和鼠标后才调用的一段代
码,而且它不需要WINMAIN函数。当这段代码被调用的时候就会在屏幕上显示一张背景
图片,而且在背景图片上面还会出现一些不同方向移动的红色心型图案。 三、运行环境
Windows XP/7
四、功能要求
屏幕保护程序是一种特殊的windows应用程序。当系统检测到一段时间内没有鼠标和键盘消息输入(即空闲了一段时间,此长度可以设置)时就自动进入屏幕保护程序,以避免长时间显示静止画面而引起荧光体损坏,以及删除留在屏幕上的敏感信息。一旦有鼠标或键盘输入,就自动关闭屏幕保护程序。
~ 2 ~
五、总体设计
1.系统功能模块图 屏幕保护程序
设置
无键盘和鼠标响应
显示小图标 显示背景图片
图1 系统功能图
2.程序流程图
开始
无响应发送WM_PAINT消息
调用DefWindowProc()
播放背景音乐
画背景图片
N
Y
~ 3 ~
图2 系统流程图
3.类的继承关系
class CScreenSaverWnd : public CWnd //CWnd是MFC窗口类的基类,提供了微软基础类库中所有窗口类的基本功能
class CMfcSaver : public CScreenSaverWnd class CScreenSaverDlg : public CDialog //CDialog类是在屏幕上显示的对话框基类 class CMfcSaverDlg : public CScreenSaverDlg 4.关键代码
(1)实现用画背景
void CScreenSaverWnd::OnPaint() {
CPaintDC dc(this);
if (m_pPalette)//如果m_pPalette非空,则自动处理调色板
{
dc.SelectPalette(m_pPalette, FALSE);
dc.RealizePalette();
}
//以下实现画背景图片
CRect rect;
GetClientRect(&rect);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BITMAP2); //IDB_BITMAP2是图对应的ID
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);
dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,
bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
OnDraw(&dc);
}
(2)实现画小图标
void CMfcSaver::OnDraw(CDC* pDC)
~ 4 ~
{
int i;
for (i = 0; i < m_nIcons; i++)
{
EraseMfcSaverIcon(i, pDC);
UpdateMfcSaverIconPosition(i);
if (IsMfcSaverIconOffscreen(i))
SetupMfcSaverIcon(i);
DrawMfcSaverIcon(i, pDC);
}
}
void CMfcSaver::EraseMfcSaverIcon(int i, CDC* pDC)
{
CRect rcIcon = CRect(m_aIcon[i].ptP, CSize(64, 64)); //CSize(64,64)剪切图标大小
}
void CMfcSaver::DrawMfcSaverIcon(int i, CDC* pDC)
{
m_ilIcons.Draw(pDC, m_aIcon[i].iImage, m_aIcon[i].ptP, ILD_NORMAL);
}
(3)判断图标相撞并弹回
BOOL CMfcSaver::IsMfcSaverIconColliding(int i, CPoint ptP)
{
CRect rcI = CRect(ptP, CSize(64, 64));
int j;
for (j = 0; j < m_nIcons; j++)
{
if (j == i)
continue;
CRect rcJ = CRect(m_aIcon[j].ptP, CSize(64, 64));
if (rcJ.IntersectRect(&rcJ, &rcI))
return TRUE;
}
return FALSE;
}
void CMfcSaver::BounceMfcSaverIcon(int i) {
do
{
m_aIcon[i].szV.cx = (rand() % 5) - 2;//x轴的随机速度
~ 5 ~
m_aIcon[i].szV.cy = (rand() % 5) - 2;//y轴的随机速度
} while (m_aIcon[i].szV.cx == 0 && m_aIcon[i].szV.cy == 0);
}
(4)在屏幕上随机产生一个图标
void CMfcSaver::SetupMfcSaverIcon(int i) {
int count = max(1, m_ilIcons.GetImageCount());//GetImageCount()获得位图中图标个数
do
{
m_aIcon[i].iImage = (rand() % count);
m_aIcon[i].ptP.x =
(rand() % ::GetSystemMetrics(SM_CXSCREEN));//产生随机x坐标
m_aIcon[i].ptP.y =
(rand() % ::GetSystemMetrics(SM_CXSCREEN));//产生随机y坐标
BounceMfcSaverIcon(i);
m_aIcon[i].nStuck = 0;
} while (IsMfcSaverIconColliding(i, m_aIcon[i].ptP));
}
(5)保存设置参数
//返回当前图标数量
int CMfcSaver::GetIconCount() const {
return m_nIcons;
}
//获得设置参数图标数量
void CMfcSaver::SetIconCount(int nIcons) {
m_nIcons = nIcons;
OnInitialUpdate();
}
//返回当前图标速度
int CMfcSaver::GetIconSpeed() const {
return m_nSpeed;
}
//获得设置参数图标速度
~ 6 ~
void CMfcSaver::SetIconSpeed(int nSpeed) {
m_nSpeed = nSpeed;
OnInitialUpdate();
}
//以下SaveOptions()和RestoreOptions()两个函数是设置对话框和
//屏幕保护程序实现通讯,因为它们不可能同时出现
//将各项参数保存在系统注册表中
void CMfcSaver::SaveOptions()//用来保存当前参数
{
CString s;
s.Format("%d", GetIconCount());
::WritePrivateProfileString(
"MfcSaver", "Count", s, "mfcsaver.ini");
s.Format("%d", GetIconSpeed());
::WritePrivateProfileString(
"MfcSaver", "Speed", s, "mfcsaver.ini"); }
void CMfcSaver::RestoreOptions()//用来保存设置参数
{
SetIconCount(::GetPrivateProfileInt(
"MfcSaver", "Count", 8, "mfcsaver.ini"));
SetIconSpeed(::GetPrivateProfileInt(
"MfcSaver", "Speed", 8, "mfcsaver.ini")); }
(6)更新当前图标位置
void CMfcSaver::UpdateMfcSaverIconPosition(int i)
{
CPoint ptP;
ptP = m_aIcon[i].ptP + m_aIcon[i].szV;
if (IsMfcSaverIconColliding(i, ptP))
{
m_aIcon[i].nStuck++;
BounceMfcSaverIcon(i);
if (m_aIcon[i].nStuck > 5)
SetupMfcSaverIcon(i);
return;
}
m_aIcon[i].nStuck = 0;
~ 7 ~
m_aIcon[i].ptP = ptP;
}
六、运行效果
能在屏幕上显示很多跳动的心,很漂亮哦。
七、设计总结
通过本次实验使我对可视化编程有了进一步的了解。了解了MFC的基本框架和怎样用MFC进行开发。熟悉了绘制图形的一些常用函数。因为以前没有接触过MFC,在设计的过程中遇到了很多很多的问题,许多问题都得一个一个的解决。在解决问题的过程中,和同学商量、上网查、问老师等,学到了很多的东西,虽说程序实现的功能非常的简单简陋,但从熟悉MFC到编码到调试,在做的过程中还要不断的修改,不断的增加功能,有时一个问题可能很久都解决不了。在做的过程中我对C++的面向对象的思想有了更深的理解,所有的数据和方法都有封装在类的内部,而且一个类的设计非常重要。类之间的继承关系要理清楚。我对MFC的消息映射和各种响应事件有了初步了解,对窗口的初始化和重绘有了一些了解。我感觉这两周的课设天天泡在机房,有时候晚上不睡觉,埋头编码的感觉很好,虽说一天下来会很累,但觉得过的很充实。两周的课设转眼结束了,觉得时间过的很快,课设时间可能有些短,要是时间再长些我们可能能做出更好的程序,因为平时上课的时候很少有这种机会,也没有时间。总之这次课设很有意义,也学到了很多的东西,让我在今后更加注意了软件设计的过程。
~ 8 ~
八、用户使用手册
本程序安装后便可在系统里面使用
右键scr文件,点击安装
然后就会出现
设置显示时间,点“确定”
九、参考文献
(1)MFC视频讲解 作者:孙鑫
(2)Visual C++编程技巧典型案例解析——基础与应用篇(下) 作者:《电脑编程技巧与维护》杂志社 出版社:中国电力出版社
(3)MFC Windows程序设计(第2版) 作者:Jeff Prosise 出版社:清华大学出版社 (4)C++面向对象程序设计 作者:李兰、任凤华 出版社:西安电子科技大学出版社
十、附录:
(1)ScreenSaverWnd.h
#ifndef __SCREENSAVERWND_H__
#define __SCREENSAVERWND_H__
~ 9 ~
#include
class CScreenSaverWnd : public CWnd {
DECLARE_DYNAMIC(CScreenSaverWnd) public:
CScreenSaverWnd();
protected:
CPalette* m_pPalette;
public:
CPalette* GetPalette() const;
CPalette* SetPalette(CPalette* pPalette);
public:
public:
virtual void OnDraw(CDC* pDC);
virtual void OnInitialUpdate();
virtual void SaveOptions();
virtual void RestoreOptions();
public:
//{{AFX_VIRTUAL(CScreenSaverWnd)
//}}AFX_VIRTUAL
public:
virtual ~CScreenSaverWnd();
static CScreenSaverWnd* sm_pTheScreenSaver;
protected:
virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
//{{AFX_MSG(CScreenSaverWnd)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnPaint();
afx_msg BOOL OnQueryNewPalette();//此函数与OnPaletteChanged一起处理调色板
afx_msg void OnPaletteChanged(CWnd* pFocusWnd);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
~ 10 ~
};
inline CScreenSaverWnd* AfxGetScreenSaverWnd()
{
return CScreenSaverWnd::sm_pTheScreenSaver;//sm_pTheScreenSaver是类CScreenSaverWnd的指针
}
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
#endif
ScreenSaverWnd.cpp
#include "StdAfx.h"
#include "resource.h"
#include "ScreenSaverWnd.h"
#include
#pragma comment(lib,"winmm.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
IMPLEMENT_DYNAMIC(CScreenSaverWnd, CWnd)
BEGIN_MESSAGE_MAP(CScreenSaverWnd, CWnd)
//{{AFX_MSG_MAP(CScreenSaverWnd)
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_PALETTECHANGED()
ON_WM_QUERYNEWPALETTE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/* static */ CScreenSaverWnd* CScreenSaverWnd::sm_pTheScreenSaver = NULL;
CScreenSaverWnd::CScreenSaverWnd() {
~ 11 ~
sm_pTheScreenSaver = this;
m_pPalette = NULL;//m_pPalette为空时自己处理调色板
}
CScreenSaverWnd::~CScreenSaverWnd() {
sm_pTheScreenSaver = NULL;
}
int CScreenSaverWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
#ifdef _DEBUG
SetWindowPos(&CWnd::wndNoTopMost,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); #endif
RestoreOptions();
OnInitialUpdate();
return 0;
}
void CScreenSaverWnd::OnInitialUpdate() {
// Base version does nothing.
// A derived class can set up basic data structures.
}
void CScreenSaverWnd::SaveOptions() {
// Base version does nothing.
// A derived class can store options in the registry or ini files.
}
void CScreenSaverWnd::RestoreOptions() {
// Base version does nothing.
// A derived class can retrieve options from the registry or ini files.
}
~ 12 ~
BOOL CScreenSaverWnd::OnEraseBkgnd(CDC* pDC) {
CRect rcClient;
GetClientRect(&rcClient);
PlaySound((LPCSTR) IDR_WAVE1,0,SND_RESOURCE |SND_ASYNC); //加音乐
return TRUE;
}
void CScreenSaverWnd::OnPaint() {
CPaintDC dc(this);
if (m_pPalette)//如果m_pPalette非空,则自动处理调色板
{
dc.SelectPalette(m_pPalette, FALSE);
dc.RealizePalette();
}
//以下实现画背景图片
CRect rect;
GetClientRect(&rect);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_BITMAP2); //IDB_BITMAP2是图对应的ID
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);
dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,
bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
OnDraw(&dc);
}
void CScreenSaverWnd::OnDraw(CDC* pDC) {
// Base version does nothing.
// A derived class can use the DC to paint in any manner on the screen.
}
CPalette* CScreenSaverWnd::GetPalette() const {
return m_pPalette;
}
~ 13 ~
CPalette* CScreenSaverWnd::SetPalette(CPalette* pPalette) {
// At no time does the CScreenSaverWnd take 'ownership' of a palette
// object; i.e., it will never delete or create them. It's just holding.
CPalette* pOldPalette = m_pPalette;
m_pPalette = pPalette;
OnQueryNewPalette();
return pOldPalette;
}
BOOL CScreenSaverWnd::OnQueryNewPalette() {
if (!m_pPalette)
return FALSE;
CClientDC dc(this);
dc.SelectPalette(m_pPalette, FALSE);//FALSE,RealizePalette使逻辑调色板
拷贝到设备调色板中
UINT uChanged = dc.RealizePalette();
return TRUE;
}
void CScreenSaverWnd::OnPaletteChanged(CWnd* pFocusWnd) {
if (pFocusWnd == this)
return;
OnQueryNewPalette();
}
LRESULT CScreenSaverWnd::WindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
return CWnd::WindowProc(uMsg, wParam, lParam); }
LRESULT CScreenSaverWnd::DefWindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam) {
~ 14 ~
return ::DefScreenSaverProc(m_hWnd, uMsg, wParam, lParam); }
LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
// There should be one global instance of a CScreenSaverWnd derivative.
ASSERT(CScreenSaverWnd::sm_pTheScreenSaver);
if (!CScreenSaverWnd::sm_pTheScreenSaver)
return 0L;
// Since we don't have a CWinApp object, we need to initialize the MFC
// internals ourselves, and terminate them when the window is destroyed.
if (!CScreenSaverWnd::sm_pTheScreenSaver->m_hWnd)
{
AfxWinInit((HINSTANCE)::GetWindowLong(hWnd, GWL_HINSTANCE),
NULL, "", SW_SHOWNORMAL);
CScreenSaverWnd::sm_pTheScreenSaver->Attach(hWnd);
}
LRESULT lResult =
::AfxCallWndProc(
CScreenSaverWnd::sm_pTheScreenSaver,
CScreenSaverWnd::sm_pTheScreenSaver->m_hWnd,
uMsg, wParam, lParam);
if (uMsg == WM_NCDESTROY)
{
ASSERT(!CScreenSaverWnd::sm_pTheScreenSaver ||
!CScreenSaverWnd::sm_pTheScreenSaver->m_hWnd);
AfxWinTerm();
}
return lResult;
}
(2)ScreenSaverDlg.h
#ifndef __SCREENSAVERDLG_H__
#define __SCREENSAVERDLG_H__
~ 15 ~
#include
class CScreenSaverDlg : public CDialog
{
DECLARE_DYNAMIC(CScreenSaverDlg)
public:
CScreenSaverDlg();
protected:
public:
//{{AFX_VIRTUAL(CScreenSaverDlg)
//}}AFX_VIRTUAL
virtual BOOL OnInitDialog();
public:
virtual ~CScreenSaverDlg();
static CScreenSaverDlg* sm_pTheConfigureDialog;
protected:
virtual LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM
lParam);
//{{AFX_MSG(CScreenSaverDlg)
afx_msg void OnNcDestroy();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
inline CScreenSaverDlg* AfxGetScreenSaverDialog()
{
return CScreenSaverDlg::sm_pTheConfigureDialog;
}
BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam);
BOOL WINAPI RegisterDialogClasses(HANDLE hInstance);
#endif
ScreenSaverDlg.cpp
~ 16 ~
#include "StdAfx.h"
#include "ScreenSaverWnd.h"
#include "ScreenSaverDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
///////////////////////////////////////////////////////////////////
//////////
IMPLEMENT_DYNAMIC(CScreenSaverDlg, CDialog)
// MFC's normal processing would have CDialog and CWnd handle any
messages
// not handled by the CScreenSaverDlg. Some are not appropriate for
a
// screen saver's configuration dialog, so we skip CDialog and CWnd in
the
// line below, and have all unhandled messages go to the CCmdTarget. // The WindowProc() below will forward the reasonable messages to
CDialog.
//
BEGIN_MESSAGE_MAP(CScreenSaverDlg, CCmdTarget)
//{{AFX_MSG_MAP(CScreenSaverDlg)
ON_WM_NCDESTROY()
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_COMMAND(IDOK, OnOK)
ON_COMMAND(IDCANCEL, OnCancel)
ON_MESSAGE(WM_INITDIALOG, HandleInitDialog)
END_MESSAGE_MAP()
// There should be only one CScreenSaverDlg instantiated at a time. // The helper function AfxGetScreenSaverDlg() returns this pointer. //
/* static */ CScreenSaverDlg* CScreenSaverDlg::sm_pTheConfigureDialog
= NULL;
CScreenSaverDlg::CScreenSaverDlg()
{
~ 17 ~
ASSERT(!sm_pTheConfigureDialog);
sm_pTheConfigureDialog = this;
}
CScreenSaverDlg::~CScreenSaverDlg()
{
sm_pTheConfigureDialog = NULL;
}
void CScreenSaverDlg::OnNcDestroy()
{
CDialog::OnNcDestroy();
}
BOOL CScreenSaverDlg::OnInitDialog()
{
if (AfxGetScreenSaverWnd())
AfxGetScreenSaverWnd()->RestoreOptions();
return CDialog::OnInitDialog();
}
int CScreenSaverDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
#ifdef _DEBUG
// Screen savers should be TOPMOST to block out any other windows,
// such as other topmost windows created previously. However, if you
// are trying to debug a screen saver, it can get in the way.
// We remove the topmost status from this window only if we're _DEBUG.
//
SetWindowPos(&CWnd::wndNoTopMost,
0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
#endif
return 0;
}
LRESULT CScreenSaverDlg::WindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam)
~ 18 ~
{
return CDialog::WindowProc(uMsg, wParam, lParam);
}
LRESULT CScreenSaverDlg::DefWindowProc(UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
return 0L;
}
///////////////////////////////////////////////////////////////////
//////////
// ::ScreenSaverConfigureDialog():
// This API must be exported to be recognized as a configurable screen // saver. This serves as the dialog message proc called by Windows to // display the configuration dialog for the screen saver. Not all
messages
// that go to the dialog actually get sent to our proc. //
BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
// There should be one global instance of a CScreenSaverDlg derivative.
ASSERT(AfxGetScreenSaverDialog());
if (!AfxGetScreenSaverDialog())
return 0L;
if (!AfxGetScreenSaverDialog()->m_hWnd)
AfxGetScreenSaverDialog()->Attach(hDlg);
// MFC does a lot of helpful but nonstandard things with WM_INITDIALOG.
//
// Since a screen saver's configuration dialog proc is dictated to us,
// we need to manually perform the ->OnInitDialog() call ourselves.
//
// This is equivalent to MFC4.2's ::AfxDlgProc() [which is not exported
// nor used by the sanctioned exported public ::AfxCallWndProc()
// function].
//
LRESULT lResult;
if (uMsg == WM_INITDIALOG)
~ 19 ~
{
// special case for WM_INITDIALOG
CDialog* pDlg =
DYNAMIC_DOWNCAST(CDialog,
CWnd::FromHandlePermanent(hDlg));
if (pDlg != NULL)
lResult = pDlg->OnInitDialog();
else
lResult = 1;
}
else
{
lResult =
AfxCallWndProc(
AfxGetScreenSaverDialog(),
AfxGetScreenSaverDialog()->m_hWnd,
uMsg, wParam, lParam);
}
if (uMsg == WM_NCDESTROY)
{
ASSERT(!AfxGetScreenSaverDialog() ||
!AfxGetScreenSaverDialog()->m_hWnd);
}
return lResult;
}
// ::RegisterDialogClasses():
// This API must be exported to be recognized as a configurable screen
// saver. It is called upon startup to register any WNDCLASS structures
// that would later be necessary to display a configuration dialog.
//
BOOL WINAPI RegisterDialogClasses(HANDLE hInstance) {
// We rely on the default registered window class used by MFC
// dialogs. Therefore, we have nothing to do here.
//
return TRUE;
}
(3)resource.h
#define IDD_MFCSAVER_DIALOG 102
#define IDR_MAINFRAME 128
~ 20 ~
#define IDB_ICONS 129 #define IDB_BITMAP2 130 #define IDR_WAVE1 131 #define IDC_BUTTON1 1000 #define IDC_SLIDER1 1001 #define IDC_SLIDER2 1002 #define IDgfC_STATIC1 1003 #define IDC_STATIC1 1005 #define IDC_STATIC2 1006
// Next default values for new objects //
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 134 #define _APS_NEXT_COMMAND_VALUE 32771 #define _APS_NEXT_CONTROL_VALUE 1007 #define _APS_NEXT_SYMED_VALUE 101 #endif
#endif
(4)MfcSaver.h
#ifndef __MFCSAVER_H__
#define __MFCSAVER_H__
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h"
///////////////////////////////////////////////////////////////////
//////////
#include "ScreenSaverWnd.h"
class CMfcSaver : public CScreenSaverWnd
{
// Construction
public:
~ 21 ~
CMfcSaver();
// Attributes
protected:
struct _icon { int iImage; CPoint ptP; CSize szV; int nStuck; };
CImageList m_ilIcons;//CImageList调用图标库
CArray<_icon,_icon&> m_aIcon;
int m_nIcons;
int m_nSpeed;
public:
int GetIconCount() const;
void SetIconCount(int nIcons);
//
int GetIconSpeed() const;
void SetIconSpeed(int nSpeed);
// Operations
public:
void EraseMfcSaverIcon(int i, CDC* pDC);
BOOL IsMfcSaverIconColliding(int i, CPoint ptP);
BOOL IsMfcSaverIconOffscreen(int i);
void UpdateMfcSaverIconPosition(int i);
void DrawMfcSaverIcon(int i, CDC* pDC);
void BounceMfcSaverIcon(int i);
void SetupMfcSaverIcon(int i);
// Overrides
public:
virtual void OnDraw(CDC* pDC);
virtual void OnInitialUpdate();
virtual void SaveOptions();
virtual void RestoreOptions();
//{{AFX_VIRTUAL(CMfcSaver)
//}}AFX_VIRTUAL
// Implementation
public:
virtual ~CMfcSaver();
protected:
//{{AFX_MSG(CMfcSaver)
afx_msg void OnTimer(UINT nIDEvent);
~ 22 ~
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif // __MFCSAVER_H__
MfcSaver.cpp
#include "StdAfx.h"
#include "MfcSaver.h" #include "MfcSaverDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW #undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_MESSAGE_MAP(CMfcSaver, CScreenSaverWnd)
//{{AFX_MSG_MAP(CMfcSaver)
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMfcSaver theSaver;
CMfcSaverDlg theSaverDialog;
CMfcSaver::CMfcSaver() {
m_nIcons = 8;//最初的图标个数
m_nSpeed = 8;//最初图标速度
srand(time(NULL));
}
CMfcSaver::~CMfcSaver() {
}
//返回当前图标数量
int CMfcSaver::GetIconCount() const
{
~ 23 ~
return m_nIcons;
}
//获得设置参数图标数量
void CMfcSaver::SetIconCount(int nIcons) {
m_nIcons = nIcons;
OnInitialUpdate();
}
//返回当前图标速度
int CMfcSaver::GetIconSpeed() const {
return m_nSpeed;
}
//获得设置参数图标速度
void CMfcSaver::SetIconSpeed(int nSpeed) {
m_nSpeed = nSpeed;
OnInitialUpdate();
}
//以下SaveOptions()和RestoreOptions()两个函数是设置对话框和 //屏幕保护程序实现通讯,因为它们不可能同时出现
//将各项参数保存在系统注册表中
void CMfcSaver::SaveOptions()//用来保存当前参数
{
CString s;
s.Format("%d", GetIconCount());
::WritePrivateProfileString(
"MfcSaver", "Count", s, "mfcsaver.ini");
s.Format("%d", GetIconSpeed());
::WritePrivateProfileString(
"MfcSaver", "Speed", s, "mfcsaver.ini"); }
void CMfcSaver::RestoreOptions()//用来保存设置参数
{
SetIconCount(::GetPrivateProfileInt(
"MfcSaver", "Count", 8, "mfcsaver.ini"));
SetIconSpeed(::GetPrivateProfileInt(
"MfcSaver", "Speed", 8, "mfcsaver.ini"));
~ 24 ~
}
void CMfcSaver::OnInitialUpdate() {
if (!m_hWnd)
return;
// Flush all the icons we have, if any.
m_aIcon.RemoveAll();
if (m_ilIcons.m_hImageList)
m_ilIcons.DeleteImageList();
// Set up for the desired number of icons.
m_aIcon.SetSize(m_nIcons);
m_ilIcons.Create(IDB_ICONS, 64, 0, RGB(128, 0, 128));//颜色屏蔽位为紫色
int i;
for (i = 0; i < m_nIcons; i++)
SetupMfcSaverIcon(i);
m_nSpeed = max(1, m_nSpeed);
SetTimer(0,2000/m_nSpeed, NULL);//NULL默认的回调函数OnTimer }
void CMfcSaver::OnDraw(CDC* pDC) {
int i;
for (i = 0; i < m_nIcons; i++)
{
EraseMfcSaverIcon(i, pDC);
UpdateMfcSaverIconPosition(i);
if (IsMfcSaverIconOffscreen(i))
SetupMfcSaverIcon(i);
DrawMfcSaverIcon(i, pDC);
}
}
void CMfcSaver::EraseMfcSaverIcon(int i, CDC* pDC)
{
CRect rcIcon = CRect(m_aIcon[i].ptP, CSize(64, 64)); //CSize(64,64)剪切图标大小
}
void CMfcSaver::DrawMfcSaverIcon(int i, CDC* pDC)
~ 25 ~
{
m_ilIcons.Draw(pDC, m_aIcon[i].iImage, m_aIcon[i].ptP, ILD_NORMAL);
}
void CMfcSaver::OnTimer(UINT nIDEvent) //nIDvent为计时器的名字
{
CScreenSaverWnd::OnTimer(nIDEvent);
Invalidate(FALSE);
}
//实现图标相撞的范围
BOOL CMfcSaver::IsMfcSaverIconColliding(int i, CPoint ptP)//
{
CRect rcI = CRect(ptP, CSize(64, 64));
int j;
for (j = 0; j < m_nIcons; j++)
{
if (j == i)
continue;
CRect rcJ = CRect(m_aIcon[j].ptP, CSize(64, 64));
if (rcJ.IntersectRect(&rcJ, &rcI))
return TRUE;
}
return FALSE;
}
BOOL CMfcSaver::IsMfcSaverIconOffscreen(int i) {
CRect rcI = CRect(m_aIcon[i].ptP, CSize(64, 64));
CRect rcC;
GetClientRect(&rcC);
return !rcC.IntersectRect(&rcC, &rcI); }
void CMfcSaver::UpdateMfcSaverIconPosition(int i) {
CPoint ptP;
ptP = m_aIcon[i].ptP + m_aIcon[i].szV;
~ 26 ~
if (IsMfcSaverIconColliding(i, ptP))
{
m_aIcon[i].nStuck++;
BounceMfcSaverIcon(i);
if (m_aIcon[i].nStuck > 5)
SetupMfcSaverIcon(i);
return;
}
m_aIcon[i].nStuck = 0;
m_aIcon[i].ptP = ptP;
}
void CMfcSaver::BounceMfcSaverIcon(int i) {
do
{
m_aIcon[i].szV.cx = (rand() % 5) - 2;//x轴的随机速度
m_aIcon[i].szV.cy = (rand() % 5) - 2;//y轴的随机速度
} while (m_aIcon[i].szV.cx == 0 && m_aIcon[i].szV.cy == 0);
}
void CMfcSaver::SetupMfcSaverIcon(int i) {
int count = max(1, m_ilIcons.GetImageCount());//GetImageCount()获得位图中图标个数
do
{
m_aIcon[i].iImage = (rand() % count);
m_aIcon[i].ptP.x =
(rand() % ::GetSystemMetrics(SM_CXSCREEN));//产生随机x坐标
m_aIcon[i].ptP.y =
(rand() % ::GetSystemMetrics(SM_CXSCREEN));//产生随机y坐标
BounceMfcSaverIcon(i);
m_aIcon[i].nStuck = 0;
} while (IsMfcSaverIconColliding(i, m_aIcon[i].ptP));
}
(5)MfcSaverDlg.h
#ifndef __MFCSAVERDLG_H__
~ 27 ~
#define __MFCSAVERDLG_H__
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
#include "ScreenSaverDlg.h"
class CMfcSaverDlg : public CScreenSaverDlg
{
// Construction
public:
CMfcSaverDlg();
// Dialog Data
public:
//{{AFX_DATA(CMfcSaverDlg)
enum { IDD = DLG_SCRNSAVECONFIGURE };
//}}AFX_DATA
// Overrides
public:
//{{AFX_VIRTUAL(CMfcSaverDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
//{{AFX_MSG(CMfcSaverDlg)
virtual BOOL OnInitDialog();
afx_msg void OnURL();
// afx_msg void OnOutofmemorySlider1(NMHDR* pNMHDR, LRESULT*
pResult);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#endif // __MFCSAVERDLG_H__
MfcSaverDlg.cpp
~ 28 ~
#include "StdAfx.h"
#include "MfcSaver.h"
#include "MfcSaverDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
BEGIN_MESSAGE_MAP(CMfcSaverDlg, CScreenSaverDlg)
//{{AFX_MSG_MAP(CMfcSaverDlg)
ON_BN_CLICKED(IDC_BUTTON1, OnURL)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMfcSaverDlg::CMfcSaverDlg() {
//{{AFX_DATA_INIT(CMfcSaverDlg)
//}}AFX_DATA_INIT
}
BOOL CMfcSaverDlg::OnInitDialog() {
CScreenSaverDlg::OnInitDialog();
return TRUE;
}
void CMfcSaverDlg::OnURL()
{
CString sURL;
GetDlgItemText(IDC_BUTTON1, sURL);
::ShellExecute(m_hWnd, NULL, sURL, NULL, NULL, 0);
}
//实现设置图标速度和数量
void CMfcSaverDlg::DoDataExchange(CDataExchange* pDX)
{
CScreenSaverDlg::DoDataExchange(pDX);
~ 29 ~
//{{AFX_DATA_MAP(CMfcSaverDlg)
//}}AFX_DATA_MAP
CMfcSaver* pSaver = (CMfcSaver*)AfxGetScreenSaverWnd();
if (!pSaver)
return;
CSliderCtrl* pSlider;
if (!pDX->m_bSaveAndValidate)
{
pSaver->RestoreOptions();
pSlider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER1);
pSlider->SetRange(1, 50);
pSlider->SetPos(pSaver->GetIconCount());
pSlider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER2);
pSlider->SetRange(1, 50);
pSlider->SetPos(pSaver->GetIconSpeed());
}
else
{
pSlider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER1);//如果函数调用成功则
返回值为给定控件的窗口句柄
pSaver->SetIconCount(pSlider->GetPos());
pSlider = (CSliderCtrl*)GetDlgItem(IDC_SLIDER2);
pSaver->SetIconSpeed(pSlider->GetPos());
pSaver->SaveOptions();
}
}
(6)StdAfx.h
#ifndef __STDAFX_H__
#define __STDAFX_H__
///////////////////////////////////////////////////////////////////////////
//
#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
~ 30 ~
#define VC_EXTRALEAN
#include // MFC core and standard components #include // MFC extensions
//#include // MFC support for Windows Common Controls #include // MFC support for template collection classes
#pragma warning(disable:4100) // unreferenced formal parameter
/////////////////////////////////////////////////////////////////////////////
#endif // __STDAFX_H__
StdAfx.cpp
#include "StdAfx.h"
~ 31 ~