This section of the archives stores flipcode's complete Developer Toolbox collection,
featuring a variety of mini-articles and source code contributions from our readers.

Screensaver Framework
Submitted by

A simple screensaver framework which implements much of
the Windows fluff that's required of a screensaver.
This leaves you to do the interesting OpenGL/DirectX rendering.
See the readme in the zip.
--
Cheers,
Roc (CyberFrog) 8:)

// virtual
void CTestScreensaver::doRunConfiguration()
{
// Pull up a dialog to alter your
// screensaver's settings.
// You must also persist them in the registry
// yourself.
::MessageBox( NULL,_T("This should be a configuration dialog!"),_T("TestScreensaver"),MB_OK );
}

/////////////////////////////////////////////////////////////////////////////
// CScreensaverApp:
//
// This ABC forms the basis of the Screensaver skeleton. You should derive
// a concrete class from this base and implement the pure virtual functions
// to carry out the necessary implementation of your screensaver.
//
class CScreensaverApp : public CWinApp
{
public:

// Concretes of this class MUST override these pure virtuals.
// The virtuals are broken down into groups based upon their
// requirement.
// These are for fullscreen operation.
// Initialise fullscreen mode (typically creates a window)
// and return the HWND. If there is an error, return NULL.
// The render call is made once per frame.
// If the monitor power is lost, the doRestoreFullscreen()
// method is called. This should re-create any device
// objects as required.
virtual HWND doCreateFullscreen() = 0;
virtualvoid doRenderFullscreen() = 0;
virtualvoid doDestroyFullscreen() = 0;
virtualvoid doRestoreFullscreen() = 0;

// These are for running any configuration dialog
// and for the persistence mechanism for screensaver
// settings. In running the configuration, the
// client should automatically persist any settings
// it needs.
virtualvoid doRunConfiguration() = 0;

// These are for running the preview mode.
// The client should use the parent HWND to
// create a child window of the same dimensions
// and render to that target. It is ASSUMED
// that this will be a windowed and not fullscreen
// render target.
// The render call is made once per frame.
// If the monitor power is lost, the doRestorePreview()
// method is called. This should re-create any device
// objects as required.
virtual HWND doCreatePreview( HWND hParentWnd ) = 0;
virtualvoid doRenderPreview() = 0;
virtualvoid doDestroyPreview() = 0;
virtualvoid doRestorePreview() = 0;

// Return the name to use for the registry stub key.
// Typically, this would be the name of the company.
virtual LPCTSTR applicationRegistryKey() const = 0;

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__F42F12B6_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_)
#define AFX_STDAFX_H__F42F12B6_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_

/////////////////////////////////////////////////////////////////////////////
// CScreensaverApp initialization
BOOL CScreensaverApp::InitInstance()
{
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

// When we are invoked, there are a number of command line parameters
// which govern how we are to operate. They are as follows:
//
// /s - Run the screensaver in fullscreen mode
// /c - Run any configuration settings
// /a - Change the password
// /p <HWND> - Run the screensaver in preview mode with HWND
// being the parent window we are to run within.
//
// As a special debugging aid, we can test the preview option
// by running the screensaver in a debugger using /testpreview.
// In this case, the app will create a parent window internally
// solely to test the preview. To test fullscreen, simply supply
// the /s switch as normal.
// Determine the command line parameters
CString cmdLine=m_lpCmdLine;
cmdLine.MakeLower();
if ( cmdLine.Find(_T("/s")) != -1 )
{
// Run screensaver proper
runScreensaver();
}
elseif ( cmdLine.Find(_T("/c")) != -1 )
{
// Run configuration
runConfiguration();
}
elseif ( cmdLine.Find(_T("/a")) != -1 )
{
// Run password change
runChangePassword();
}
elseif ( cmdLine.Find(_T("/testpreview")) != -1 )
{
// Run the preview but in test mode.
// For this, we need to create a
// window to act as the parent of
// the screensaver.
HWND hParentWnd=createHelperWindow();
ASSERT( ::IsWindow(hParentWnd) );
runPreview( hParentWnd );
::DestroyWindow( hParentWnd );
}
elseif ( cmdLine.Find(_T("/p")) != -1 )
{
// Run preview but we need to extract the HWND
// of the parent window
constint index=cmdLine.Find( _T("/p") );
ASSERT( index!=-1 );

void CScreensaverApp::runScreensaver()
{
// This will run the screensaver in fullscreen mode.
// We simply handle the drudgery here and defer the
// actual work to the concrete class.
MSG msg;
int originalSPISetting;
bool isPowerOn=true;

// Allow the client to initialise itself
HWND hWnd=doCreateFullscreen();
if ( hWnd!=NULL )
{
// We should be initialised okay so let Windows
// know that a screensaver is running.
::SystemParametersInfo( SPI_SCREENSAVERRUNNING,true,&originalSPISetting,0 );

// Process whilst we have a valid window
while ( ::IsWindow(hWnd) || !verifyPassword(hWnd) )
{
// Only render if we have still got power
if ( isPowerOn )
doRenderFullscreen();

// Operate a standard message pump
while ( ::PeekMessage(&msg,NULL,0,0,PM_REMOVE) )
{
// For Win98 and Win2K systems, we could have the
// monitor powered off. If this happens, Direct3D/OpenGL
// can loose their surfaces, etc.
if ( _winver >= 0x0400 )
{
if ( msg.message==WM_SYSCOMMAND && msg.wParam==SC_MONITORPOWER )
{
// We've lost power
isPowerOn=false;
}
elseif ( msg.message==WM_PAINT )
{
// If we get this and power was off, let the
// client know that surfaces need to be
// restored
if ( !isPowerOn )
{
doRestoreFullscreen();
isPowerOn=true;
}
}
}

void CScreensaverApp::runPreview( HWND hParentWnd )
{
// This will run the preview mode.
// As in the case of fullscreen, we handle alot
// of the mudane stuff here and delegate the
// juicy bits to the client.
MSG msg;
bool isPowerOn=true;