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:)

Currently browsing [ScreensaverWrapper.zip] (11,763 bytes) - [TestScreensaver.cpp] - (7,922 bytes)

    #include "stdafx.h"
    #include "screensaver.h"

    class CTestScreensaver : public CScreensaverApp
    {
    public:

    	CTestScreensaver();
    	virtual ~CTestScreensaver();

    	// Accessors
    	bool	isFullscreen() const		{ return isFullscreen_; }
    	bool	isActive() const			{ return isActive_; }

    protected:

    	// Methods inherited from base class.
    	// Required for fullscreen rendering.
    	virtual HWND doCreateFullscreen();
    	virtual void doRenderFullscreen();
    	virtual void doDestroyFullscreen();
    	virtual void doRestoreFullscreen();

    	// Required for preview rendering.
    	virtual HWND doCreatePreview( HWND hParentWnd );
    	virtual void doRenderPreview();
    	virtual void doDestroyPreview();
    	virtual void doRestorePreview();

    	// Required for configuration
    	virtual void doRunConfiguration();

    	// Required for registering the application
    	// settings.  Typically, a company name.
    	virtual LPCTSTR	applicationRegistryKey() const;

    private:

    	// Canonical form revoked
    	CTestScreensaver( const CTestScreensaver ©Me );
    	CTestScreensaver &operator =( const CTestScreensaver ©Me );

    	// Helpers
    	bool		createWindow( bool fullscreen,HWND hParentWnd );
    	LPCTSTR		registerClass();
    	void		renderFrame();

    	// The window procedure is our friend
    	friend LRESULT CALLBACK WndProc( HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam );

    	// Data members
    	HWND	hRenderWnd_;
    	bool	isFullscreen_;
    	bool	isActive_;

    };

    // We need an application instance
    CTestScreensaver	theApp;

    // Our screensaver will need a window procedure.  This is it.
    LRESULT CALLBACK WndProc( HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam )
    {
    	switch( msg )
    	{
    		case WM_CREATE:
    		{
    			CTestScreensaver	*pApp=(CTestScreensaver *)AfxGetApp();
    			ASSERT( pApp );

    			// Hide mouse if fullscreen
    			if ( pApp->isFullscreen() )
    			{
    				::ShowCursor( FALSE );
    			}

    			// Window should always on the top
    			::SetWindowPos( hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE );
    			break;
    		}
    		case WM_LBUTTONDOWN:
    		case WM_RBUTTONDOWN:
    		case WM_MBUTTONDOWN:
    		case WM_KEYDOWN:
    		case WM_SYSKEYDOWN:
    		{
    			// Any sort of keyboard or mouse action
    			// closes our screensaver.
    			::SendMessage( hWnd,WM_CLOSE,0,0 );
    			break;
    		}
    		case WM_CLOSE:
    		{
    			// It's all over.
    			::DestroyWindow( hWnd );
    			break;
    		}
    		case WM_DESTROY:
    		{
    			CTestScreensaver	*pApp=(CTestScreensaver *)AfxGetApp();
    			ASSERT( pApp );

    			// Ensure we are properly shutdown
    			if ( pApp->isFullscreen() )
    			{
    				pApp->doDestroyFullscreen();
    			}
    			else
    			{
    				pApp->doDestroyPreview();
    			}

    			// Show mouse if we were in fullscreen mode
    			if ( pApp->isFullscreen() )
    			{
    				::ShowCursor( TRUE );
    			}

    			// Ensure the app knows that the window has gone
    			pApp->hRenderWnd_=NULL;
    			break;
    		}
    		case WM_PAINT:
    		{
    			// Very rudimentary painting.
    			static size_t	frameCounter=0;
    			PAINTSTRUCT		ps;
    			HDC				hDC=::BeginPaint( hWnd,&ps );
    			TCHAR			szBuff[256];
    			wsprintf( szBuff,_T("Frame: %u"),++frameCounter );
    			::FillRect( hDC,&ps.rcPaint,(HBRUSH)::GetStockObject(BLACK_BRUSH) );
    			::TextOut( hDC,0,0,szBuff,lstrlen(szBuff) );
    			::EndPaint( hWnd,&ps );
    			break;
    		}
    		default:
    			return ::DefWindowProc( hWnd,msg,wParam,lParam );
       }

       return 0;
    }

    // Implementation
    CTestScreensaver::CTestScreensaver() :
    	CScreensaverApp(),
    	hRenderWnd_( NULL ),
    	isFullscreen_( false ),
    	isActive_( false )
    {
    	// Ctor
    }

    // virtual
    CTestScreensaver::~CTestScreensaver()
    {
    	// Dtor.
    	// We should have already shut down properly
    	ASSERT( hRenderWnd_==NULL );
    	ASSERT( !isActive_ );
    }

    bool CTestScreensaver::createWindow( bool fullscreen,HWND hParentWnd )
    {
    	ASSERT( hRenderWnd_==NULL );
    	LPCTSTR		lpszClassName=registerClass();
    	const DWORD	dwStyles=(fullscreen ? WS_POPUP : WS_CHILD) | WS_VISIBLE;
    	const int	x=0;
    	const int	y=0;
    	int			width, height;
    	if ( fullscreen )
    	{
    		width	= ::GetSystemMetrics( SM_CXSCREEN );
    		height	= ::GetSystemMetrics( SM_CYSCREEN );
    	}
    	else
    	{
    		RECT	r;
    		ASSERT( hParentWnd!=NULL );
    		::GetClientRect( hParentWnd,&r );
    		width	= r.right;
    		height	= r.bottom;
    	}

    	hRenderWnd_ = ::CreateWindow( lpszClassName,_T(""),dwStyles,x,y,width,height,hParentWnd,NULL,::AfxGetInstanceHandle(),NULL );

    	return (hRenderWnd_!=NULL);
    }

    LPCTSTR CTestScreensaver::registerClass()
    {
    	// We must only ever register the class once
    	static bool		hasBeenRegistered=false;
    	static LPCTSTR	lpszClassName=_T("TestScreensaverClass");
    	if ( !hasBeenRegistered )
    	{
    		WNDCLASSEX		wc;

    		ZeroMemory( &wc,sizeof(wc) );
    		wc.cbSize			= sizeof(wc);
    		wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    		wc.lpfnWndProc		= (WNDPROC) WndProc;
    		wc.cbClsExtra		= 0;
    		wc.cbWndExtra		= 0;
    		wc.hInstance		= ::AfxGetInstanceHandle();
    		wc.hIcon			= NULL;
    		wc.hCursor			= ::LoadCursor(NULL, IDC_ARROW);
    		wc.hbrBackground	= NULL;
    		wc.lpszMenuName		= NULL;
    		wc.lpszClassName	= lpszClassName;

    		ATOM	atom=::RegisterClassEx( &wc );
    		ASSERT( atom!=0 );

    		hasBeenRegistered=true;
    	}

    	return lpszClassName;
    }

    void CTestScreensaver::renderFrame()
    {
    	ASSERT( hRenderWnd_ );
    	ASSERT( isActive_ );

    	// Render the Direct3D or OpenGL frame here.
    	// For our purposes, we simply invalidate
    	// the client area and have WM_PAINT sort it
    	// out.  Only cause a frame to be rendered
    	// every second though.
    	static clock_t	lastClock=0;
    	clock_t			thisClock=clock();
    	if ( thisClock-lastClock>1000 )
    	{
    		::InvalidateRect( hRenderWnd_,NULL,FALSE );
    		::UpdateWindow( hRenderWnd_ );

    		lastClock=thisClock;
    	}
    }

    // virtual
    LPCTSTR CTestScreensaver::applicationRegistryKey() const
    {
    	return _T("TestCompanyName");
    }

    // virtual
    HWND CTestScreensaver::doCreateFullscreen()
    {
    	// Create a window for fullscreen rendering
    	HWND	result=(createWindow(true,NULL) ? hRenderWnd_ : NULL);

    	if ( result!=NULL )
    	{
    		// Now's the time to create Direct3D or OpenGL.
    		// If everything is okay, set the isActive_ flag
    		// to say that the sub-system is activated.
    		isActive_=true;
    	}

    	return result;
    }

    // virtual
    void CTestScreensaver::doRenderFullscreen()
    {
    	// Called to render a frame.
    	renderFrame();
    }

    // virtual
    void CTestScreensaver::doRestoreFullscreen()
    {
    	// Called if the device has been lost
    	// e.g. after a power off on monitor
    	// and should be restored.
    }

    // virtual
    void CTestScreensaver::doDestroyFullscreen()
    {
    	// If we're active, shutdown any Direct3D
    	// or OpenGL objects.  Do NOT destroy
    	// the window - this is done automatically.
    	if ( isActive_ )
    	{
    		isActive_=false;
    	}
    }

    // virtual
    HWND CTestScreensaver::doCreatePreview( HWND hParentWnd )
    {
    	// Create a window for Preview rendering
    	HWND	result=(createWindow(false,hParentWnd) ? hRenderWnd_ : NULL);

    	if ( result!=NULL )
    	{
    		// Now's the time to create Direct3D or OpenGL.
    		// If everything is okay, set the isActive_ flag
    		// to say that the sub-system is activated.
    		isActive_=true;
    	}

    	return result;
    }

    // virtual
    void CTestScreensaver::doRenderPreview()
    {
    	// Called to render a frame.
    	renderFrame();
    }

    // virtual
    void CTestScreensaver::doRestorePreview()
    {
    	// Called if the device has been lost
    	// e.g. after a power off on monitor
    	// and should be restored.
    }

    // virtual
    void CTestScreensaver::doDestroyPreview()
    {
    	// If we're active, shutdown any Direct3D
    	// or OpenGL objects.  Do NOT destroy
    	// the window - this is done automatically.
    	if ( isActive_ )
    	{
    		isActive_=false;
    	}
    }

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

Currently browsing [ScreensaverWrapper.zip] (11,763 bytes) - [screensaver.h] - (3,555 bytes)

    // screensaver.h : main header file for the SCREENSAVER application
    //

    #if !defined(AFX_SCREENSAVER_H__F42F12B4_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_)
    #define AFX_SCREENSAVER_H__F42F12B4_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #ifndef __AFXWIN_H__
    	#error include 'stdafx.h' before including this file for PCH
    #endif

    /////////////////////////////////////////////////////////////////////////////
    // 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:

    	virtual ~CScreensaverApp();

    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CScreensaverApp)
    public:
    	virtual BOOL InitInstance();
    	//}}AFX_VIRTUAL

    // Implementation

    public:
    	//{{AFX_MSG(CScreensaverApp)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()

    protected:

    	// We can only be created by concrete classes
    	CScreensaverApp();

    	// 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;
    	virtual void doRenderFullscreen() = 0;
    	virtual void doDestroyFullscreen() = 0;
    	virtual void 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.
    	virtual void 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;
    	virtual void doRenderPreview() = 0;
    	virtual void doDestroyPreview() = 0;
    	virtual void 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;

    private:

    	// Canonical form revoked
    	CScreensaverApp( const CScreensaverApp ©Me );
    	CScreensaverApp &operator =( const CScreensaverApp ©Me );

    	// Internal methods
    	void	runScreensaver();
    	void	runConfiguration();
    	void	runPreview( HWND hParentWnd );
    	void	runChangePassword();
    	bool	verifyPassword( HWND hParentWnd );
    	HWND	createHelperWindow();

    };

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

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_SCREENSAVER_H__F42F12B4_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_)

Currently browsing [ScreensaverWrapper.zip] (11,763 bytes) - [StdAfx.cpp] - (213 bytes)

    // stdafx.cpp : source file that includes just the standard includes
    //	screensaver.pch will be the pre-compiled header
    //	stdafx.obj will contain the pre-compiled type information

    #include "stdafx.h"

Currently browsing [ScreensaverWrapper.zip] (11,763 bytes) - [StdAfx.h] - (999 bytes)

    // 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_

    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000

    #define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers

    #include <afxwin.h>         // MFC core and standard components
    #include <afxext.h>         // MFC extensions
    #include <afxdtctl.h>		// MFC support for Internet Explorer 4 Common Controls
    #ifndef _AFX_NO_AFXCMN_SUPPORT
    #include <afxcmn.h>			// MFC support for Windows Common Controls
    #endif // _AFX_NO_AFXCMN_SUPPORT

    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.

    #endif // !defined(AFX_STDAFX_H__F42F12B6_728D_11D3_B3DD_00A0C90F8EDC__INCLUDED_)

Currently browsing [ScreensaverWrapper.zip] (11,763 bytes) - [screensaver.cpp] - (11,985 bytes)

    // screensaver.cpp : Defines the class behaviors for the application.
    //

    #include "stdafx.h"
    #include "screensaver.h"

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

    /////////////////////////////////////////////////////////////////////////////
    // CScreensaverApp

    BEGIN_MESSAGE_MAP(CScreensaverApp, CWinApp)
    	//{{AFX_MSG_MAP(CScreensaverApp)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()

    /////////////////////////////////////////////////////////////////////////////
    // CScreensaverApp construction

    CScreensaverApp::CScreensaverApp()
    {
    	// Place all significant initialization in InitInstance
    }

    // virtual
    CScreensaverApp::~CScreensaverApp()
    {
    	// Intentionally empty
    }

    /////////////////////////////////////////////////////////////////////////////
    // 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

    	// Change the registry key under which our settings are stored.
    	SetRegistryKey( applicationRegistryKey() );

    	// 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();
    	}
    	else if ( cmdLine.Find(_T("/c")) != -1 )
    	{
    		// Run configuration
    		runConfiguration();
    	}
    	else if ( cmdLine.Find(_T("/a")) != -1 )
    	{
    		// Run password change
    		runChangePassword();
    	}
    	else if ( 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 );
    	}
    	else if ( cmdLine.Find(_T("/p")) != -1 )
    	{
    		// Run preview but we need to extract the HWND
    		// of the parent window
    		const int	index=cmdLine.Find( _T("/p") );
    		ASSERT( index!=-1 );

    		// We don't bother checking that the parent window is
    		// invalid - the preview method will verify and early
    		// out if there's a problem.  For debugging, we just
    		// do a sanity check
    		HWND		hParentWnd=(HWND)atoi( cmdLine.Mid(index+3) );
    		ASSERT( ::IsWindow(hParentWnd) );
    		runPreview( hParentWnd );
    	}
    	else
    	{
    		TRACE( "CScreensaverApp::InitInstance() Unrecognised command line parameters: '%s'\n",(LPCTSTR)cmdLine );
    		ASSERT( false );
    	}

    	return FALSE;
    }

    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;
    					}
    					else if ( 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;
    						}
    					}
    				}

    				// The normal translate and despatch stuff
    				PreTranslateMessage( &msg );
    				TranslateMessage( &msg );
    				DispatchMessage( &msg );
    			}
    		}

    		// Ensure the window is destroyed
    		if ( ::IsWindow(hWnd) )
    		{
    			::SendMessage( hWnd,WM_CLOSE,0,0 );
    		}
    		ASSERT( !::IsWindow(hWnd) );

    		// Prepare for the end.
    		// Restore Windows' view of what was running
    		::SystemParametersInfo( SPI_SCREENSAVERRUNNING,false,&originalSPISetting,0 );

    		// Allow the client to perform an orderly shutdown
    		doDestroyFullscreen();
    	}
    }

    void CScreensaverApp::runConfiguration()
    {
    	// Nothing really clever here - simply delegate to client
    	doRunConfiguration();
    }

    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;

    	// Verify the parent window
    	if ( !::IsWindow(hParentWnd) )
    	{
    		TRACE( "CScreensaverApp::runPreview() Parent window is invalid!\n" );
    		return;
    	}

    	// Wait for the parent window to become visible
    	while ( ::IsWindow(hParentWnd) && !::IsWindowVisible(hParentWnd) )
    	{
    		// Pump away
    		while ( ::PeekMessage(&msg,hParentWnd,0,0,PM_REMOVE) )
    		{
    			PreTranslateMessage( &msg );
    			TranslateMessage( &msg );
    			DispatchMessage( &msg );
    		}
    	}

    	// Allow the client to initialise itself
    	HWND		hWnd=doCreatePreview( hParentWnd );
    	if ( hWnd!=NULL )
    	{
    		// Process whilst we have a valid window
    		while ( ::IsWindow(hParentWnd) && ::IsWindowVisible(hParentWnd) && ::IsWindow(hWnd) )
    		{
    			// Only render if we have still got power
    			if ( isPowerOn )
    				doRenderPreview();

    			// 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;
    					}
    					else if ( msg.message==WM_PAINT )
    					{
    						// If we get this and power was off, let the
    						// client know that surfaces need to be
    						// restored
    						if ( !isPowerOn )
    						{
    							doRestorePreview();
    							isPowerOn=true;
    						}
    					}
    				}

    				// The normal translate and despatch stuff
    				PreTranslateMessage( &msg );
    				TranslateMessage( &msg );
    				DispatchMessage( &msg );
    			}
    		}

    		// Ensure the window is destroyed
    		if ( ::IsWindow(hWnd) )
    		{
    			::SendMessage( hWnd,WM_CLOSE,0,0 );
    		}
    		ASSERT( !::IsWindow(hWnd) );

    		// Allow the client to perform an orderly shutdown
    		doDestroyPreview();
    	}
    }

    void CScreensaverApp::runChangePassword()
    {
    	// We need to dynamically link to the password DLL since
    	// it contains the function to change the screensaver
    	// password.
    	HINSTANCE	hInst=::LoadLibrary( _T("MPR.DLL") );
    	if ( hInst==NULL )
    	{
    		TRACE( "CScreensaverApp::runChangePassword() Failed to load MPR.DLL\n" );
    	}
    	else
    	{
    		// Get hold of the correct function
    		typedef VOID (WINAPI *PSWCHANGER)( LPCSTR lpRegKey,HWND hWnd,UINT nReserved1,UINT nReserved2 );
    		PSWCHANGER	pswChanger=(PSWCHANGER)::GetProcAddress( hInst,_T("PwdChangePasswordA") );
    		if ( pswChanger==NULL )
    		{
    			TRACE( "CScreensaverApp::runChangePassword() Failed to get address of PwdChangePasswordA\n" );
    		}
    		else
    		{
    			// Change the password
    			pswChanger( _T("SCRSAVE"),::GetDesktopWindow(),0,0 );
    		}

    		// Free the library
    		::FreeLibrary( hInst );
    	}
    }

    bool CScreensaverApp::verifyPassword( HWND hParentWnd )
    {
    	// This method will optionally bring up the password
    	// verification dialog and verify the password
    	bool	result=false;

    	// If we're running on WinNT, it will handle the password
    	// verification for us so we don't need to bother with
    	// anything
    	OSVERSIONINFO		osv;
    	ZeroMemory( &osv,sizeof(osv) );
    	osv.dwOSVersionInfoSize=sizeof(osv);
    	::GetVersionEx( &osv );
    	if ( osv.dwPlatformId==VER_PLATFORM_WIN32_NT )
    	{
    		result=true;
    	}
    	else
    	{
    		// Use the password control panel applet
    		HINSTANCE	hInst=::LoadLibrary( _T("PASSWORD.CPL") );
    		if ( hInst==NULL )
    		{
    			TRACE( "CScreensaver::verifyPassword() Failed to load PASSWORD.CPL\n" );
    		}
    		else
    		{
    			// Get hold of the password verification function
    			typedef BOOL (WINAPI *PSWVERIFY)( HWND hWnd );
    			PSWVERIFY		pswVerify=(PSWVERIFY)::GetProcAddress( hInst,_T("VerifyScreenSavePwd") );
    			if ( pswVerify==NULL )
    			{
    				TRACE( "CScreensaver::verifyPassword() Failed to get address of VerifyScreenSavePwd\n" );
    			}
    			else
    			{
    				::ShowCursor( TRUE );

    				result = (pswVerify(hParentWnd)==TRUE);

    				::ShowCursor( FALSE );
    			}

    			// Release the library
    			::FreeLibrary( hInst );
    		}
    	}

    	return result;
    }

    // Test preview window procedure.  Nothing special, really.
    LRESULT CALLBACK PreviewHelperWndProc( HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam )
    {
    	switch( msg )
    	{
    		case WM_PAINT:
    		{
    			// Just draw a black background
    			PAINTSTRUCT		ps;
    			HDC				hDC=::BeginPaint( hWnd,&ps );
    			::FillRect( hDC,&ps.rcPaint,(HBRUSH)::GetStockObject(BLACK_BRUSH) );
    			::EndPaint( hWnd,&ps );
    			break;
    		}
    		default:
    			return ::DefWindowProc( hWnd,msg,wParam,lParam );
       }

       return 0;
    }

    HWND CScreensaverApp::createHelperWindow()
    {
    	// We need to create a little window
    	// to serve as the parent to a preview
    	// test.
    	static bool		hasBeenRegistered=false;
    	static LPCTSTR	lpszClassName=_T("ScreensaverPreviewHelperClass");
    	if ( !hasBeenRegistered )
    	{
    		WNDCLASSEX		wc;

    		ZeroMemory( &wc,sizeof(wc) );
    		wc.cbSize			= sizeof(wc);
    		wc.style			= CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    		wc.lpfnWndProc		= (WNDPROC) PreviewHelperWndProc;
    		wc.cbClsExtra		= 0;
    		wc.cbWndExtra		= 0;
    		wc.hInstance		= ::AfxGetInstanceHandle();
    		wc.hIcon			= NULL;
    		wc.hCursor			= ::LoadCursor(NULL, IDC_ARROW);
    		wc.hbrBackground	= NULL;
    		wc.lpszMenuName		= NULL;
    		wc.lpszClassName	= lpszClassName;

    		ATOM	atom=::RegisterClassEx( &wc );
    		ASSERT( atom!=0 );

    		hasBeenRegistered=true;
    	}

    	// Choose a size that befits the current resolution
    	const int	xScreen=::GetSystemMetrics( SM_CXSCREEN );
    	const int	yScreen=::GetSystemMetrics( SM_CYSCREEN );

    	// Set the width and height to a quarter that of the screen
    	const int	w=xScreen / 4;
    	const int	h=yScreen / 4;

    	// Centre the window
    	const int	x=(xScreen - w) / 2;
    	const int	y=(yScreen - h) / 2;

    	// Create the window.
    	LPCTSTR		lpszTitle=_T("Screensaver Preview Test");
    	DWORD		dwStyles=WS_CAPTION;
    	HWND		result=::CreateWindow( lpszClassName,lpszTitle,dwStyles,x,y,w,h,NULL,NULL,::AfxGetInstanceHandle(),NULL );
    	ASSERT( ::IsWindow(result) );
    	::ShowWindow( result,SW_SHOW );

    	return result;
    }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.