How to Create a Windows XP Screen Saver with Delphi 7
by CrashCodes of
www.CrashCodes.com
In addition to Delphi 7, you'll need a resource editor.
I recommend
PE Resource Explorer.
Okay, let's get started.
-
Start a new Delphi 7 Project (New|Application).
The project name should be 8 characters or less.
The first two characters should be "ss".
The project name should be all lowercase.
Not doing this may cause Windows to not properly display the screen saver's name in the Screen Saver tab of Display Settings.
- Goto the Application tab under Project|Options and change the target file extension to ".scr".
- Set the WindowState of the main form to
wsMaximized wsNormal (see Item 9).
- Set the BorderStyle of the main form to bsNone.
- Create an OnMouseMove Event for the Form.
The basic idea here is that when the mouse moves the application should exit with a couple of exceptions.
First, the Event shouldn't close the app on the very first time it is called. For some reason, the app gets a MouseMove event when it starts up.
Second, build in some tolerance for mouse movement. I make sure the mouse has moved by at least 2 pixels before closing the app.
I know that my optical mouse registers small movements even with my hand clear of my mouse and desk.
procedure TFormMain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
const Sensitivity = 2;
begin
if FFirstMouseMove then
begin
FFirstMouseMove := False;
FOldMouseX := X;
FOldMouseY := Y;
end
else
begin
if (Abs(FOldMouseX - X) > Sensitivity) or
(Abs(FOldMouseY - Y) > Sensitivity) then
Application.Terminate;
end;
end;
- Set the name to show up in the Screen Saver tab of Display Settings.
Edit the project's resource file (.res). Again, I recommend using PE Resource Explorer.
Add a string table. Add a string with an ID of 1 to the string table. This string is the name that will show up.
I think this may be restricted to 25 characters.
- Insure only one instance of your app is running. In the dpr's source file incorportae something like this:
Windows.CreateMutex(nil, True, 'scrnsave');
if (Windows.GetLastError <> Windows.ERROR_ALREADY_EXISTS) then
- Handle different command line parameters.
Windows will use these different command line options:
/c - Screen Saver Settings. When a user selects your screen saver and clicks the Settings button on the Screen Saver tab in Display Options.
/p - Screen Saver Preview. This is what Windows uses to call your app for display in that little monitor on the Screen Saver tab in Display Options. This is not what is used when the preview button is called.
/s - Screen Saver Show. This is what Windows will use when it wants to display your app as a screen saver. (includes the Preview button on the Screen Saver tab in Display Options)
/a - Screen Saver Password. I don't know anything about this yet except that it has something to do with setting or challenging the user for a password.
I do the branching in the Project's source (Project|View Source):
...
procedure ShowSettings;
begin
Application.CreateForm(TFormSettings, FormSettings);
end;
procedure ShowScreenSaver;
begin
...
end;
...
begin
Windows.CreateMutex(nil, True, 'scrnsave');
if (Windows.GetLastError <> Windows.ERROR_ALREADY_EXISTS) then
begin
Application.Initialize;
if ParamCount > 0 then
begin
Option := LowerCase(Copy(ParamStr(1), 1, 2));
if Option = '/c' then
ShowSettings
else if Option = '/p' then
ShowPreview
else if Option = '/s' then
ShowScreenSaver
else
ShowSettings;
end
else
ShowSettings;
Application.Run;
end;
end.
- Handle Multiple Monitors
You can deal with this anyway you'd like in your application, but for the time being this is how I decided to deal with it:
...
procedure ShowScreenSaver;
var
I: Integer;
begin
for I := 0 to Screen.MonitorCount - 1 do
begin
Application.CreateForm(TFormMain, FormMain);
FormMain.Left := Screen.Monitors[I].Left;
FormMain.WindowState := wsMaximized;
end;
end;
...
I create the TFormMain then I move it to the monitor's left position.
This will put the form in the right place for the next line that maximizes the window.
You'll notice I'm losing track of the FormMain pointer, but I don't need to use it anymore.
Depending on what you decide to do with your MainForm, having multiple copies of it may not work for you.
- Make the main form do something.
If you add components to the form the OnMouseMove event needs to be set for them too.
Remember this is suppose to be a screen saver. So you don't want anything CPU intensive or any pixels constantly lit at the same color.
- Compile
- Copy to your system32 directory usually c:\windows\system32\
Here's my current template/example for a screen saver:
ScreenSaverTemplate.zip
Article TODO List:
- Keep the screen saver as the top screen.
- Explain how to code the for the command line option /p.
- Explain how to handle someone right-clicking on the .scr file and clicking install.
- Clean-up the source code.
by CrashCodes of
www.CrashCodes.com