Random Screensaver for windows

This screensaver randomly chooses screensavers when it starts. You can choose which folders to use, how long of a delay between screensavers and which ones you don’t want running.

Screensaver settings screenshot
program randomss;
{$RESOURCE RANDOMSCREENSAVER.RES}
(*
  This is the main file for random screensaver
  it starts the configuration window (TScreenSaverConfig)
  it starts choosing screensavers.
*)
uses
  SysUtils,
  windows,
  Classes,
  filectrl,
  forms,
  graphics,
  shellapi,
  randomssUnit1 in 'randomssUnit1.pas' {ScreenSaverConfig};
{$E scr}
label nextscr;
const RUNNING_HINT:pchar='Delete this key to allow the screensaver to run again';
type
TGetProcessId=function(handle:THandle):DWord;stdcall;
//The function GetProcessId wasn't defined in Delphi 4
var
hkRunning:hkey;
screc,scrpid:dword;
I:integer;
used:tstringlist;
exec:shellexecuteinfo;
preview:TCanvas;
GetProcessId:tgetprocessid;
previewRect:TRect;
randomized:boolean;
dir:array[0..max_path]of char;
Icon:TIcon;

function AlreadyRunning:boolean;
var disp,pid:dword;
hkrunning:hkey;
begin
disp:=maxdword;
pid:=getcurrentprocessid;
regcreatekeyex(hkey_current_user,reg_running,0,nil,reg_option_volatile,key_write,
nil,hkrunning,@disp);regsetvalueex(hkrunning,nil,0,reg_sz,running_hint,(1+strlen(
running_hint))*sizeof(char));
result:=(disp=reg_opened_existing_key);
if not result then regsetvalueex(hkrunning,reg_processid,0,reg_dword,@pid,4);
regclosekey(hkrunning);
end;

begin
randomize;
regcreatekeyex(hkey_current_user,'Software\Justin\RandomSCR',0,nil,
reg_option_non_volatile,key_all_access,nil,hkapp,nil);
bRunOnce:=(regqueryvalueex(hkapp,reg_norunonce,nil,nil,nil,nil)<>error_success);
rs:=4;
bnoshuffle:=(regqueryvalueeX(hkapp,reg_randomseed,nil,nil,@randseed,@rs)=error_success);
rs:=4;
getwindowsdirectory(windir,max_path);
maxtime:=60000;
regqueryvalueex(hkapp,reg_runtime,nil,nil,@maxtime,@rs);
randomized:=(maxtime=random_time);
rs:=sizeof(szExcluded);
regqueryvalueeX(hkapp,reg_excluded,nil,nil,Pointer(strcopy(szexcluded,'')),@rs);
excluded:=tstringlist.Create;
excluded.CommaText:=strpas(szexcluded);
excluded.Append(paramstr(0));
directories:=tstringlist.create;
rs:=sizeof(szdirectories);
directories.Append(windir);//for windows 9x/Me(Even though  this tool won't work with that OS)
if directoryexists(strfmt(dir,'%s\system32',[windir]))then directories.Append(
dir);//for NT-type screensavers
if directoryexists(strfmt(dir,'%s\SysWOW64',[windir]))then directories.Append(
dir);//for 64-bit windows
if directoryexists(strfmt(dir,'%s\system',[windir]))then directories.Append(dir);
//just in case there screensavers in that folder
regqueryvalueex(hkapp,reg_dirlist,nil,nil,pointer(strplcopy(szDirectories,
directories.commatext,1024)),@rs);
directories.commatext:=strpas(szdirectories);
screensavers:=tstringlist.Create;
for i:=0to directories.count-1do begin
if findfirst(format('%s\*.scr',[directories[i]]),faanyfile,findscr)=0then begin
if(excluded.IndexOf(findscr.finddata.cfilename)=-1)and(-1=excluded.Indexof(
extractfilename(findscr.FindData.cFileName))) then
screensavers.Append(Directories[i]+'\'+findscr.FindData.cFileName);
while findnext(findscr)=0do
if(excluded.IndexOf(findscr.finddata.cfilename)=-1)and(-1=excluded.Indexof(
extractfilename(findscr.FindData.cFileName))) then
screensavers.Append(directories[i]+'\'+findscr.FindData.cFileName);
sysutils.FindClose(findscR);
end;
end;
if(comparetext('/p',paramstr(1))<>0)and(comparetext(paramstr(1),'/s')<>0)and(
comparetext('/debug',paramstr(1))<>0)then
begin(* This code is executed when the Settings button has been clicked or
        Configure has been choosen from the file menu *)
application.Initialize;
Application.CreateForm(Tscreensaverconfig, screensaverconfig);
application.Run;
exitprocess(0);
end;
regclosekey(hkapp);
if comparetext('/p',paramstr(1))=0then
begin(* executes this code when being previewed in control panel *)
icon:=ticon.Create;
icon.Handle:=loadicon(hinstance,MakeIntResource(1));
preview:=tcanvas.Create;
preview.Handle:=getwindowdc(strtoint(paramstr(2)));
getclientrect(strtoint(paramstr(2)),previewrect);
while iswindow(strtoint(paramstr(2)))do
begin
for I:=0to high(randomss_about)do
preview.TextOut(0,i*16,randomss_about[i]);
with previewrect.BottomRight do
preview.Draw(x div 2,y div 2,icon);//draw the icon in the middle of the preview window
sleep(100);
end;
releasedc(strtoint(paramstr(2)),preview.handle);
exitprocess(0);
 end;
 if alreadyrunning then exitprocess(wait_timeout);
 //Don't allow more than one process of this screensaver running.
 @GetProcessId:=getprocaddress(getmodulehandle(kernel32),'GetProcessId');
 zeromemory(@exec,sizeof(exec));
exec.cbSize:=sizeof(exec);
exec.fMask:=see_mask_nocloseprocess;
exec.lpFile:=stralloc(MAX_PATH+1);
exec.lpParameters:='/S';
exec.nShow:=sw_show;
if screensavers.Count=0then begin messagebox(0,'No screensavers found',appname,
mb_iconwarning);exitprocess(error_file_not_found);end;
used:=tstringlist.Create;
(* Starts choosing screensavers *)
regopenkeyex(hkey_current_user,reg_running,0,key_all_access,hkrunning);
(*Assumes that the key "HKEY_CURRENT_USER\Software\Justin\RandomSCR\Running" exists
  or created by the alreadyrunning function *)
nextscr:if randomized then maxtime:=60000+random(15*60000);
if used.Count=screensavers.Count then used.Clear;
if(used.IndexOf(strpcopy(exec.lpFile,screensavers[random(screensavers.count)]))>-1)
then goto nextscr;
if brunonce then used.Append(exec.lpFile);
if not shellexecuteex(@Exec) then(* Use ShellExecuteEx to start the screensaver *)
begin regclosekey(hkrunning);exitprocess(1);end;
if assigned(getprocessid)then scrpid:=getprocessid(exec.hProcess);
regsetvalueex(hkrunning,reg_scrpid,0,reg_dword,@scrpid,4);
case waitforsingleobject(exec.hProcess,maxtime)of(* wait for timeout or screensaver exit *)
wait_timeout:begin terminateprocess(exec.hProcess,0);closehandle(exec.hProcess);
goto nextscr; end;
wait_failed:messagebox(0,pchar('WaitForScreensaver: '+syserrormessage(
getlasterror)),exec.lpfile,mb_iconwarning);
else screc:=0;getexitcodeprocess(exec.hprocess,screc);terminateprocess(
exec.hProcess,0);closehandle(exec.hProcess);if screc=wait_timeout then
goto nextscr;
end;
if hkrunning<>0then regclosekey(hkrunning);
regdeletekey(hkey_current_user,reg_running);
exitprocess(getlasterror);
end.

unit randomssUnit1;
(*
  Settings form unit.
*)
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Menus, ComCtrls;
const appname='Random Screensaver';
REG_RUNNING='Software\Justin\RandomSCR\Running';
reg_runtime='RunTime';
reg_excluded='Excluded';
reg_processid='ProcessID';
reg_scrpid='SCRProcessID';
random_time=maxdword-1;
RandomSS_About:Array[0..2]of string=(
'delphijustin Random ScreenSaver v1.0',
'By Justin Roeder','2021');
reg_dirlist='Directories';
reg_randomseed='RandomSeed';
reg_NoRunOnce='NoRunOnce';
type
EBadTimeout=class(Exception)
end;
  TScreenSaverConfig = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Memo1: TMemo;
    Button1: TButton;
    MainMenu1: TMainMenu;
    Help1: TMenuItem;
    About1: TMenuItem;
    Button2: TButton;
    Label3: TLabel;
    Memo2: TMemo;
    Button3: TButton;
    OpenDialog1: TOpenDialog;
    CheckBox1: TCheckBox;
    Label4: TLabel;
    StatusBar1: TStatusBar;
    ComboBox1: TComboBox;
    CheckBox2: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure About1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
function StrToTimeout(const s:string):dword;
var
  ScreenSaverConfig: TScreenSaverConfig;
  bRunOnce,bNoShuffle:boolean;
maxTime,rs:dword;
ScreenSavers,excluded,directories:Tstringlist;
findscr:tsearchrec;
windir:array[0..max_path]of char;
szdirectories,szExcluded:array[0..1024]of char;
hkApp:hkey;
implementation

{$R *.DFM}

function TimeoutToStr(timeout:dword):string;
begin
case timeout of //Converts the timeout(in milliseconds)to a readable string
infinite:result:='INF';
RANDOM_TIME:result:='RANDOM';
ELSE result:=formatdatetime('hh:mm:ss',timeout*EncodeTime(0,0,0,1));
END;
end;

function StrToTimeout(const s:string):dword;
begin
try//does the opposite of TimeoutToStr
if comparetext(s,'INF')=0then result:=infinite else
if comparetext(s,'RANDOM')=0Then result:=random_time else
result:=round(strtotime(s)/encodetime(0,0,0,1));
if(result<60000)then
raise EBadTimeout.Create(
'To prevent system crashes, the time cannot be less than 1 minute');
except on E:EConvertError do result:=60000;end;
end;

procedure TScreenSaverConfig.FormCreate(Sender: TObject);
begin//initializes the configuration form.
regdeletekey(hkey_current_user,reg_running);
with excluded do delete(indexof(paramstr(0)));
icon.Handle:=loadicon(hinstance,makeintresource(1));
application.Icon.Handle:=icon.Handle;
application.Title:=caption;
opendialog1.InitialDir:=strpas(windir);
checkbox1.Checked:=brunonce;
checkbox2.Checked:=bNoShuffle;
combobox1.Text:=timeouttostr(maxtime);
memo1.Text:=directories.Text;
memo2.Text:=excluded.text;
statusbar1.SimpleText:=format(statusbar1.SimpleText,[screensavers.count]);

end;

procedure TScreenSaverConfig.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
regclosekey(hkapp);
exitprocess(0);
end;

procedure TScreenSaverConfig.About1Click(Sender: TObject);
var msgbox:msgboxparams;
I:integer;
begin
zeromemory(@msgbox,sizeof(msgboX));
msgbox.cbSize:=sizeof(msgbox);
msgbox.hwndOwner:=handle;
msgbox.hInstance:=hinstance;
msgbox.lpszText:=strcopy(stralloc(2048),'');
for I:=0to high(randomss_about)do
strpcopy(strend(msgbox.lpsztext),randomss_about[i]+#13#10);
msgbox.lpszCaption:='About';
msgbox.dwStyle:=mb_usericon;
msgbox.lpszIcon:=makeintresource(1);
messageboxindirect(msgbox);
strdispose(msgbox.lpszText);
end;

procedure TScreenSaverConfig.Button1Click(Sender: TObject);
begin
(* Saves settings in the registry under the following key:
   HKEY_CURRENT_USER\Software\Justin\RandomSCR
   NoRunOnce         If exists the screensaver list wont act like a deck of cards.
   Excluded          Comma seperated list of screensavers to not run.
   Directories       Comma seperated list of screensaver directories
   RandomSeed        If exists the list won't be shuffled and its seed is initialed by that value.
   RunTime           Timeout in milliseconds or one of the following values:
                     0xFFFFFFFF Unlimited time
                     0xFFFFFFFE Random time in between(1 and 15 minutes)
*)
if checkbox1.Checked then regdeletevalue(hkapp,reg_norunonce)else
regsetvalueex(hkapp,reg_norunonce,0,reg_binary,nil,0);
maxtime:=strtotimeout(combobox1.text);
with memo2.Lines do
regsetvalueex(hkapp,reg_excluded,0,reg_sz,strpcopy(szExcluded,commatext),(1+
length(commatext))*sizeof(chaR));
regsetvalueex(hkapp,reg_runtime,0,reg_dword,@maxtime,4);
with memo1.Lines do
regsetvalueex(hkapp,reg_dirlist,0,reg_sz,strpcopy(szdirectories,commatext),(1+
length(commatext))*sizeof(char));
if checkbox2.Checked then regsetvalueex(hkapp,reg_randomseed,0,reg_dword,
@randseed,4)else regdeletevalue(hkapp,reg_randomseed);
close;
end;

procedure TScreenSaverConfig.Button2Click(Sender: TObject);
begin
close;
end;

procedure TScreenSaverConfig.Button3Click(Sender: TObject);
begin
(* Exclude list browse button *)
if not opendialog1.Execute then exit;
memo2.Lines.Add(extractfilename(opendialog1.filename));
end;

end.

Published by Justin Roeder

I am an electronics engineer and computer programmer that has autism. I learned by myself

Leave a comment

Your email address will not be published. Required fields are marked *