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

    // ScreenSaverWnd.cpp : implementation file
// Download by http://www.NewXing.com

#include "StdAfx.h"

#include "ScreenSaverWnd.h"

#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()
{
	sm_pTheScreenSaver = this;
	m_bAutoBlack = TRUE;
	m_pPalette = NULL;
}

CScreenSaverWnd::~CScreenSaverWnd()
{
	sm_pTheScreenSaver = NULL;
}

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

//
// Setting up the new screen saver window.
//

int CScreenSaverWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd::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

	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.
}

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

//
// The screen saver is made to paint.  We support OnDraw(), just like CView
// does, as a matter of convenience.
//
// Also for convenience, by the time an override of OnDraw() is called, the
// background has been blacked (if m_bAutoBlack), and the palette in
// m_pPalette has been realized properly.  These are optional.
//

BOOL CScreenSaverWnd::OnEraseBkgnd(CDC* pDC) 
{
	if (m_bAutoBlack)
	{
		CRect rcClient;
		GetClientRect(&rcClient);
		pDC->FillSolidRect(&rcClient, RGB(0, 0, 0));
	}
	return TRUE;
}

void CScreenSaverWnd::OnPaint() 
{
	CPaintDC dc(this);
	if (m_pPalette)
	{
		dc.SelectPalette(m_pPalette, FALSE);
		dc.RealizePalette();
	}

	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.
}

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

//
// There is nothing about CScreenSaverWnd which requires using a CPalette.
// As a convenience, it can hold onto a CPalette and realize it at the proper
// times according to WM_QUERYNEWPALETTE and WM_PALETTECHANGED notifications.
//
// Separately, a derived class can turn on and off the automatic black
// background behavior which is handled in OnEraseBkgnd(). When it is off,
// all of the user's windows will still be visible when the screen saver
// starts its OnDraw().
//

CPalette* CScreenSaverWnd::GetPalette() const
{
	return m_pPalette;
}

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);
	UINT uChanged=dc.RealizePalette();

	return TRUE;
}

void CScreenSaverWnd::OnPaletteChanged(CWnd* pFocusWnd) 
{
	if (pFocusWnd == this)
		return;

	OnQueryNewPalette();
}

BOOL CScreenSaverWnd::IsAutoBlack() const
{
	return m_bAutoBlack;
}

void CScreenSaverWnd::SetAutoBlack(BOOL bAutoBlack /* = TRUE */)
{
	m_bAutoBlack = bAutoBlack;
}

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

//
// The message routing for screen saver windows is nonstandard.  Calling the
// regular default window proc is not appropriate.  These overrides will
// route the messages properly.
//
// For example, when the user hits a key or moves the mouse, if it's not
// handled by the screen saver in some way, it should go to the default
// ::DefScreenSaverProc() which will end the screen saver cleanly.
//

LRESULT CScreenSaverWnd::WindowProc(UINT uMsg,
                                    WPARAM wParam,
                                    LPARAM lParam)
{
	return CWnd::WindowProc(uMsg, wParam, lParam);
}

LRESULT CScreenSaverWnd::DefWindowProc(UINT uMsg,
                                       WPARAM wParam,
                                       LPARAM lParam)
{
	return ::DefScreenSaverProc(m_hWnd, uMsg, wParam, lParam);
}

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

// ::ScreenSaverProc():
// This API must be exported to be recognized as a screen saver.  This serves
// as the window message proc called by Windows to display the screen saver
// window.  Not all messages that go to the window actually get sent to our
// proc.
//
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;
}

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