Mega Code Archive

 
Categories / Delphi / Examples
 

How to create a screen saver

A screen saver is really just a Windows program. Screen savers can be divided into two types: full-screen and effects. The first type has a bsNone border style, the form usaully (not always, though) has a black background and is maximized. They always have the fsStayOnTop form style. The second type is harder to create because they don't really have a visible form. They perform graphical effects on the screen. These are thougher because there's a lot more code to write. Because screen savers are Windows applications they can freely access Ini files or the system Registry. They perform all the tasks a program can perform. The screen saver has a .scr extension. You set this (Delphi 4+) in the project's options or using the {$e 'scr'} directive. No file type conversions are needed. Windows controls the screen saver using parameters: - /c - The screen saver is started. Sometimes this parameter will be sent with additional options. The format is: /c:xxxx, where x is a decimal number. - /p - The screen saver is being installed or the Screen Saver page has been chosen. - /s - - No commandline options - The screen saver setup should execute. This example shows how to create a screen saver based on a maximized form with a black (usually) background. At design time set the WindowState property to wsNormal else there may be problems maximizing it programmatically. Set the form's BorderStyle property to bsNone. Now in the OnCreate event insert this code: ... WindowState := wsMaximized; { You can't maximize it properly earlier } ... Don't forget to include a TTimer component (or something more precise if you want) to control the screen saver's animation. You may want to include a "Low CPU Usage" option that won't take too much of the processor's precious :) time. When this option would be set the screen saver would perform less calculations or at least the TTimer component's interval property would be multiplied by 2 or 4. You can also do this by lowering the current thread's and process'es priority level. This option is very useful for users that use screen savers but often have programs running in the background and don't like the screen saver taking 100% of the CPU's time. Here is the code for a screensaver I've made: You can download my screensaver here: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, compound, mdp, RXCtrls, StdCtrls; type TInst = record NoOfLogos: 1..10; Interval: 1..10; end; TForm1 = class(TForm) Timer1: TTimer; MDP1: TMDP; MDP2: TMDP; mdp3: TMDP; MDP4: TMDP; MDP5: TMDP; MDP6: TMDP; MDP7: TMDP; MDP8: TMDP; MDP9: TMDP; MDP10: TMDP; Memo1: TMemo; RxLabel1: TRxLabel; Timer2: TTimer; procedure Timer1Timer(Sender: TObject); procedure FormClick(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormCreate(Sender: TObject); procedure SaveFile; procedure LoadFile; procedure Timer2Timer(Sender: TObject); procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); private Start: Boolean; F: file of TInst; Rad: Integer; { Private declarations } public Inst: TInst; { Public declarations } end; var Form1: TForm1; implementation uses Unit2; {$R *.DFM} { Windows controls the screen saver using parameters: - /c - The screen saver is started. Sometimes this parameter will be sent with additional options. The format is: /c:xxxx, where x is a decimal number. - /p - The screen saver is being installed or the Screen Saver page has been chosen. - /s - - No commandline options - The screen saver setup should execute. } procedure TForm1.Timer1Timer(Sender: TObject); var n: Integer; begin if (ParamStr(1) = '/s') and Start then begin WindowState:= wsMaximized; for n:= 1 to Inst.NoOfLogos do begin TMDP(FindComponent('MDP' + IntToStr(n))).Start; TMDP(FindComponent('MDP' + IntToStr(n))).Show; end; for n:= Inst.NoOfLogos + 1 to 10 do begin TMDP(FindComponent('MDP' + IntToStr(n))).Stop; TMDP(FindComponent('MDP' + IntToStr(n))).Hide; end; Timer1.Enabled:= true; end else if (ParamStr(1) = '/s') and not Start then begin for n:= 1 to Inst.NoOfLogos do begin TMDP(FindComponent('MDP' + IntToStr(n))).Left:= Random(700); TMDP(FindComponent('MDP' + IntToStr(n))).Top:= Random(450); end; end else begin Timer1.Enabled:= false; if MenuForm.ShowModal = mrOK then begin SaveFile; Close; end; end; Start:= false; end; procedure TForm1.FormClick(Sender: TObject); begin Close; end; procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin Close; end; procedure TForm1.FormCreate(Sender: TObject); begin LoadFile; Timer1.Interval:= Inst.Interval * 1000; Randomize; Height:= 0; Width:= 0; Rad:= 0; Timer1.Enabled:= true; Timer2.Enabled:= true; Start:= true; end; procedure TForm1.SaveFile; begin Inst.NoOfLogos:= MenuForm.SpinEdit1.Value; Inst.Interval:= MenuForm.SpinEdit2.Value; AssignFile(F, 'c:\mdpscr.dat'); Rewrite(F); Write(F, Inst); CloseFile(F); end; procedure TForm1.LoadFile; begin try AssignFile(F, 'c:\mdpscr.dat'); Reset(F); Read(F, Inst); CloseFile(F); except Inst.Interval:= 4; Inst.NoOfLogos:= 5; AssignFile(F, 'c:\mdpscr.dat'); Rewrite(F); Write(F, Inst); CloseFile(F); end; end; procedure TForm1.Timer2Timer(Sender: TObject); begin RxLabel1.Caption:= Memo1.Lines[Rad]; Inc(Rad); if Rad = 25 then Rad:= 0; end; procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin Close; end; end. unit Unit2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, compound, mdp, StdCtrls, Buttons, passoverbtn, RXCtrls, RXSpin, Spin; type TMenuForm = class(TForm) PassOverBtn1: TPassOverBtn; MDP1: TMDP; RxLabel1: TRxLabel; SpinEdit1: TSpinEdit; RxLabel2: TRxLabel; SpinEdit2: TSpinEdit; procedure PassOverBtn1Click(Sender: TObject); procedure FormActivate(Sender: TObject); private { Private declarations } public { Public declarations } end; var MenuForm: TMenuForm; implementation uses Unit1; {$R *.DFM} procedure TMenuForm.PassOverBtn1Click(Sender: TObject); begin ModalResult:= mrOK; end; procedure TMenuForm.FormActivate(Sender: TObject); begin SpinEdit1.Value:=Form1.Inst.NoOfLogos; SpinEdit2.Value:=Form1.Inst.Interval; end; end.