Back to Amir Israeli Homepage

[Screen-Savering] Screen-Saver base classes (MFC classes)

This article was contributed by Amir Israeli Amir Israeli.
Amir Israeli Web Site

Environment: Win 95/98 VC6 SP4

This article describes 3 classes which are base class and 2 examples for MFC screen savers:
CSSBaseWnd (Screen-Saver-Base-Window) : base class for any screen-saver application.
CSSBounceWnd: example screen saver based on previous class (it does "MTMDI" MSDN example graphics
CSSBrowserWnd : a class derived from "CSSBaseWnd" contains an active web-browser control (child window) and relies its engines to do graphics . (an example uses DHTML do do some effects)

CSSBaseWnd
This class provides all the basic functionality of screen saver application:
This class is derived from CWnd (Therefore behaves as a window-a topmost one) An app can be invoked by several sources :
(a) from within the shell, explorer : in such case a screen saver works in a full screen
(b) from control-panel when sufficient interval past since last [mouse,keyboard] event ,in such case -again- screen saver works in a full screen.
(c) from Display dialog box of control panel : here window is limited (not full screen)
Screen savers should terminate whenever [mouse,keyboard] events happen. The framwork allows to ignore some events (such as not terminating when WM_MOUSEMOVE occurs)
Creation of window is done by Create(UINT nID); you need to supply ID of window, You also need to send argc,argv parameters : they indicate how app was invoked :
'p' for Control-panel(invoked by control panel)
'c' : config window (Display dialog of control panel)
's' : Full window (normal situation: time expired since last event)

//Creation of window from within CWinApp::InitInstance()
CSSBaseWnd  *pSSWnd = new CSSBaseWnd;
if (!pSSWnd) return FALSE;
pSSWnd->SetParameters( FALSE, __argc, __argv); //false = accepts no events :
//every [mouse,keyboard] events terminate app. 
return pSSWnd->Create(ID_SCREENSAVER_WND); //window id

This class contains an internal function to check parameters and set proper flags.
CSSBaseWnd contains another member of type CWnd , in normal condition : when you implementyour drawings in OnPaint , you dont use this window, Instead you may craete there an ActiveX control (member name is "m_wndBrowser" as for WebBrowser) that will occupy entire client area and do graphics itself.CSSBrowserWnd class which is derived from this class does that. You can determine the type of window by deriving a new class and override function as:
RegisterWndClass : to change entirly the type of class
GetBrush : change only type of default brush (of class)
Whenever you want to terminate screen-saver you need to call Close() : This function calls PostMessage(WM_CLOSE) , and therefore closes the window.
Some other service functions are used :
 //function to install screen-saver 
BOOL UnInstall() { return InternalInstall(FALSE); }
BOOL Install() { return InternalInstall(TRUE); }

//function to create window and control in one line :
//gets window id ( nID) control id (nCtlID) and guid.
BOOL CreateControl(UINT nID, UINT nCtlID, REFCLSID clsid);
	
//whether this screen-saver contains child control
BOOL ContainsControl() { return ::IsWindow(m_wndBrowser.m_hWnd); }

//determines if invoked by control panel (limited window)
BOOL InControlPanel() {  return (iStatus == CPANEL_WINDOW); }
Whenever you need to show your configure dialog : you override "virtual void DoConfig();" there you instantiate your own dialog that configures it ...
void CMyClass::DoConfig()
{
	CDialog  dlg(ID_DLG,this); //instantiate on stack
	dlg.DoModal(); //show
}
In general keyboard/mouse messages cause to termination of app. : this whenever we are in full window or every messages call close().
void CSSBaseWnd::OnLButtonDown(UINT nFlags, CPoint point) 
{
	if (!InControlPanel()) {
	    Close();
		return;
	}
	CWnd::OnLButtonDown(nFlags, point);
}
... //more message handlers

CSSBounceWnd This class implemets custom drawing for the previous class. It creates ball that travels on the screen . Animation uses a timer , (and is based on MTMDI mfc example within the MSDN) in DoConfig() I put about dialog as an example of configure dialog (of course it does nothing). as for animation itself : code is simply copied : (you see that I added nothing : even flickering was left as it is ).
//(Again)Creation of window from within CWinApp::InitInstance()

CSSBounceWnd  *pSSWnd = new CSSBounceWnd;
if (!pSSWnd) return FALSE;
pSSWnd->SetParameters( FALSE, __argc, __argv); // no messages
return pSSWnd->Create(ID_SCREENSAVER_WND);

CSSBrowserWnd
This class is derived from CSSBaseWnd and it also creates a web Browser control to do graphics instead of doing it in OnPaint().
Several functions are copied from MFC source : function that load HTML resources and naviation

BOOL LoadFromResource(LPCTSTR lpszResource);
BOOL LoadFromResource(UINT nRes);
void Navigate(LPCTSTR URL, DWORD dwFlags = 0,
	LPCTSTR lpszTargetFrameName = NULL,
	LPCTSTR lpszHeaders = NULL, LPVOID lpvPostData = NULL,
	DWORD dwPostDataLen = 0);
//Navigate is useful in case you want to load a page that isn't
//contained in resources : but outside : on the net so your screen-saver users be able to load it
//(if they are online) , and you are able to modify it once for a while ...
//(and so your clients will have a changing screen saver - updated ...)
Also I override the default brush of window (black brush instead of white)
virtual HBRUSH GetBrush() //virtual : change brush (background) color
	{	return (HBRUSH) ::GetStockObject(BLACK_BRUSH); }
A member function "BOOL Create(UINT nID, UINT nCtlID);" creates a main window , creates WebBrowser CLSID_WebBrowser (for that it uses base class "BOOL CSSBaseWnd::CreateControl(UINT nID, UINT nCtlID, REFCLSID clsid)" (it also set control IUnknown).
Since top window is now Browser window , we hook window messages (mouse and keyboard) and control which messages return to WebBrowser window.
Hook functions call 2 functions :
*) BOOL InputCallsHook((UINT)wp))
*) BOOL InputCallsClose((UINT)wp))
These functions map messages : InputCallsHook return TRUE for every message that we need to send back to web-browser control , FALSE when not !(in that way we prevent messages such as WM_RBUTTONDOWN : that invoke web-browsers' context menu.
InputCallsClose return TRUE whenever input message needs to terminate app.
LRESULT CALLBACK
CSSBrowserWnd::MouseMessageFilter(int code, WPARAM wp, LPARAM lp)
{
	LRESULT lResult = (LRESULT)TRUE;
	...
}
LRESULT CALLBACK
CSSBrowserWnd::KeyboardMessageFilter(int code, WPARAM wp, LPARAM lp)
{
	LRESULT lResult = (LRESULT)TRUE;
	...
}
Creation of screen saver :
CSSBrowserWnd *pSSWnd = new CSSBrowserWnd;
if (!pSSWnd) return FALSE;
pSSWnd->SetParameters( TRUE, __argc, __argv);
if (pSSWnd->Create(ID_SCREENSAVER_WND,ID_WEBBROWSER_WND)) {

	//Notice there are 2 HTML file resources in project : small.htm
	//that is used in limited window size ,  and big.htm for full-screen window.
	if (pSSWnd->InControlPanel()) 
		pSSWnd->LoadFromResource(_T("small.htm"));
	else 	pSSWnd->LoadFromResource(_T("big.htm"));
	return TRUE;
}
For more documentation see source code.
Questions -mail me Amir Israeli

Downloads

Download demo project - 49 Kb
Download source - 13 Kb
Download demo Executables - 23 Kb

History

Date Posted: October 7, 2000

Home  |  Links  |  About