A Screen Saver class library
A screen saver provides four services: preview, configuration, password change and running the screen saver itself. The system starts the screen saver with a command-line parameter to indicate which service to provide. Some of the services also make use of a second command-line parameter which is a window handle. Extra steps have to be taken in order to debug the screen saver when providing these services (Debugging your screen saver).
The Screen Saver
TScreenSaver
extracts the command line parameter
and creates the object that handles the specified service, as shown in Listing
1.
To create your own screen saver, derive from TScreenSaver
and override the abstract methods MakePreviewMode,
MakeSaverMode, MakePasswordMode
and MakeConfigMode.
Config mode
TConfigMode
provides a window handle that is extracted
from the command line parameters. However, the window handle is undocumented
and I am unsure what its use is. It's available in the Handle property if a
use for it arises. TFormConfigMode
displays a single
form. For most screen savers this should suffice. Simply pass the name of your
form class to the constructor Create.
Password mode
If a password is enabled for the screen saver, then Windows asks the screen
saver to set it. TPasswordMode
uses a TScreenSaverPassword
which is initialized to a TDefaultScreenSaverPassword
object by default. This class uses Windows routines to store and retrieve a
password. TScreenSaverForm
also uses it by default
to check the password before exiting. If you want to provide your own password
storage/retrieval mechanism, then make a new descendent of TScreenSaverPassword
and override MakePassword in TPasswordMode
.
Preview mode
When the user selects a screen saver, Windows tells it to show a preview on the 'Display Properties' dialog. The system passes the window handle in which to display on the command line. Any application responding to it must idle until the window becomes visible, display the preview, then exit when the window is hidden.
TPreviewMode
handles this in Listing 2.
The Start, Step,
and Stop methods are filled in by descendents.
For example, TCanvasPreviewMode
prepares a TCanvas
that paints on the preview window. Descendents need only redefine Step
to provide the custom painting. TWinControlPreviewMode
attaches a windows control to the preview window, sizing it correctly and displaying
it.
Saver mode
The screen saver should guard against being launched full screen multiple times.
Windows will usually try at least once to relaunch the saver once it is running.
If the saver allows multiple instances to be launched, Windows will launch again
for the new instance and soon dozens of instances will be running. TSaverMode
prevents multiple launches with a TPreviousInstance
,
which uses a Windows atom to guarantee detect previous instances, as shown in
Listing 3.
Descendant classes override the OnExecute method
to display the screen saver itself. The behavior of a standard screen saver
is encapsulated in TScreenSaverForm
, which automatically
grows to the size of the screen and takes care of detecting mouse movements
and keystrokes. When user action is detected, it closes if the password (if
enabled) is properly entered. Most screen savers will be able to customize this
form.
Listing 4 shows the Descendant forms should provide
startup code in SetUpScreenSaver, because overriding
OnFormCreate doesn't work. DetectMouse
and DetectKeyboard can also be customized. They
both return True by default. Password is initialized
to TDefaultScreenSaverPassword
by default, which
simply uses the default Windows screen saver password.
TFormSaverMode
displays a single form. If you only
want to display a form for the screen saver, then pass the name of your form
class to the constructor Create.
Debugging
[not finished]
Using the Screen Saver Library - Flash Screen Saver
The screen saver library provides a layer that creates a working screen saver. It's up to descendant classes to build on this layer to create a useful screen saver. Most screen savers display some sort of repeating animation. For this purpose, the Flash® player from Macromedia is ideal. It is also packaged as an ActiveX® control, and is easily imported into Delphi.
We'll want the user to be able to select a Flash® file to play as well
as play that file in the preview mode as well as the screen saver mode. We will
make use of several classes from the library, including TScreenSaver
,
TScreenSaverForm
, TFormConfigMode
,
TPasswordMode
, TWinControlPreviewMode
and TFormSaverMode
What about playing the Flash file at original size?
Listings
Listing 1
constructor TScreenSaver.Create;
var
command: string;
begin
command := UpperCase (ParamStr (1));
if is_switch (command, 'P') then
FMode := MakePreviewMode
else if is_switch (command, 'S') then
FMode := MakeSaverMode
else if is_switch (command, 'A') then
FMode := MakePasswordMode
else if is_switch (command, 'C') or (command = '') then
FMode := MakeConfigMode;
end;
Listing 2
procedure TPreviewMode.Execute;
begin
while not IsWindowVisible (Handle) do begin
Application.ProcessMessages;
end;
try
Start;
while IsWindowVisible (Handle) do begin
Step;
Application.ProcessMessages;
end;
finally
Stop;
end;
end;
Listing 3
procedure TSaverMode.Execute;
var
finder: TAppFinder;
begin
finder := TAppFinder.Create;
try
if finder.exists then
finder.select_existing_app
else
OnExecute;
end;
finally
finder.Free;
end;
end;
Listing 4
TScreenSaverForm = class (TForm)
{code omitted}
protected
procedure SetupScreenSaver; virtual;
function MakePassword: TScreenSaverPassword; virtual;
function GetDetectMouse: Boolean; virtual;
function GetDetectKeyboard: Boolean; virtual;
public
property DetectMouse: Boolean read GetDetectMouse;
property DetectKeyboard: Boolean read GetDetectKeyboard;
end;