www.gusucode.com > 一个有创意的VC++屏幕保护源码源码程序 > 一个有创意的VC++屏幕保护源码源码程序\code\MfcSaver.cpp

    // MfcSaver.cpp : Defines the class behaviors for the application.
// Download by http://www.NewXing.com

#include "StdAfx.h"

#include "MfcSaver.h"
#include "MfcSaverDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////

//
// The screen saver controls a number of icon graphics that bounce around
// on a black background.  Set some basic defaults and initialize the random
// number generator with srand().  Later, our RestoreOptions() will be called
// to recall earlier option settings.
//

BEGIN_MESSAGE_MAP(CMfcSaver, CScreenSaverWnd)
	//{{AFX_MSG_MAP(CMfcSaver)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// As required of CScreenSaverWnd-based screen savers, these are the two
// global instances of screen saver objects.  One is the saver itself,
// and one is the dialog for configuring the options of the screen saver.
//
// Unlike most MFC applications, there is no instance of any CWinApp object.
//
CMfcSaver theSaver;
CMfcSaverDlg theSaverDialog;

CMfcSaver::CMfcSaver()
{
	m_nIcons = 6;
	m_nSpeed = 100;
	srand(time(NULL));
}

CMfcSaver::~CMfcSaver()
{
}

/////////////////////////////////////////////////////////////////////////////

//
// The CMfcSaverDlg will need to be able to access our customizable
// attributes.  We call OnInitialUpdate() again to reorganize internally if
// any of these change.
//
// The options need to be saved and restored between runs.
// Probably the biggest thing you might miss from having no CWinApp object
// will be CWinApp::WriteProfileInt() which saves things to the registry
// without complicated registry code.
//
// For simplicity, we just create an mfcsaver.ini file with the options.
//

int CMfcSaver::GetIconCount() const
{
	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();
}

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"));
}

/////////////////////////////////////////////////////////////////////////////

//
// While this is just demonstrating how to override the virtual functions of
// CScreenSaverWnd, it also shows something about using CImageList to
// draw from a library of simple images.
//
// When our timer goes off, we just invalidate the window.  The OnDraw()
// override will be called appropriately when the system has some free cycles
// to spend on drawing.  Remember:  a screen saver should share the CPU, so
// the computer can work on other tasks like downloading or numbercrunching.
//

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, 32, 0, RGB(128, 0, 128));

	int i;
	for (i = 0; i < m_nIcons; i++)
		SetupMfcSaverIcon(i);

	m_nSpeed = max(1, m_nSpeed);
	SetTimer(1, 2000 / m_nSpeed, NULL);
}

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(32, 32));
	pDC->FillSolidRect(&rcIcon, RGB(0, 0, 0));
}

void CMfcSaver::DrawMfcSaverIcon(int i, CDC* pDC)
{
	m_ilIcons.Draw(pDC, m_aIcon[i].iImage, m_aIcon[i].ptP, ILD_NORMAL);
}

void CMfcSaver::OnTimer(UINT nIDEvent) 
{
	CScreenSaverWnd::OnTimer(nIDEvent);

	Invalidate(FALSE);
}
/////////////////////////////////////////////////////////////////////////////

//
// Compute the movement of these little square icons.
// They move until they fall offscreen, then are reinitialized randomly.
// If they would collide on any move, they don't move but they change
// direction instead.  If they seem hopelessly stuck, they are recycled.
//
// With a bit more work, you could make these icons pass over each other
// smoothly, or you could double-buffer them to draw with less flicker.
//

BOOL CMfcSaver::IsMfcSaverIconColliding(int i, CPoint ptP)
{
	CRect rcI = CRect(ptP, CSize(32, 32));

	int j;
	for (j = 0; j < m_nIcons; j++)
	{
		if (j == i)
			continue;

		CRect rcJ = CRect(m_aIcon[j].ptP, CSize(32, 32));
		if (rcJ.IntersectRect(&rcJ, &rcI))
			return TRUE;
	}

	return FALSE;
}

BOOL CMfcSaver::IsMfcSaverIconOffscreen(int i)
{
	CRect rcI = CRect(m_aIcon[i].ptP, CSize(32, 32));
	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;
	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;
		m_aIcon[i].szV.cy = (rand() % 5) - 2;
	} 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());

	int breakout = 10;
	do
	{
		m_aIcon[i].iImage = (rand() % count);
		m_aIcon[i].ptP.x =
			(rand() % ::GetSystemMetrics(SM_CXSCREEN));
		m_aIcon[i].ptP.y =
			(rand() % ::GetSystemMetrics(SM_CXSCREEN));
		BounceMfcSaverIcon(i);
		m_aIcon[i].nStuck = 0;

	} while (breakout > 0 &&
	         IsMfcSaverIconColliding(i, m_aIcon[i].ptP));
}