community.borland.com

Article #19534: Creating a 32-Bit Screen Saver in 32-bit Delphi

 Technical Information Database

TI4534D.txt - Creating a 32-Bit Screen Saver in 32-bit Delphi

Category   :Miscellaneous
Platform   :All-32Bit
Product    :All32Bit,   

Description:
This TI shows how you can write a 32-bit screen saver in 32 bit Delphi. 
The screen saver contains support for preview mode (the little monitor 
in Display Properties | Screen Saver), as well as password protection 
and a configuration dialog. 

First, a brief overview of what a screen saver is. For a more complete overview, 
consult the MSDN (Microsoft Developers Network), books and articles on the subject. 
There are also web sites with screen saver information and source code. 

A screen saver is just an executable that has an extension of SCR instead of EXE. In Delphi 3, you can set
this using the $E compiler directive. 

A screen saver can be launched in several ways: 

When the screen saver timeout happens 
By going to the Screen Saver tab in Display Properties (preview) 
By configuring it 
By previewing it (full screen) 
By changing the screen saver password (Win95) 

The screen saver is launched with different parameters depending on how it's launched: 

When the screen saver timeout happens, it's launched with ParamStr(1) containing either '/S', '-S', or
just 'S'. 

When you go to the Screen Saver tab in Display Properties the screen saver is supposed to preview
itself in the little monitor. ParamStr(1) will contain '/P', '-P', or just 'P'. At the same time, ParamStr(2) will
contain the window handle for the little monitor window. 

When you configure the screen saver it's launched either with no parameters at all, or ParamStr(1) will
contain '/C', '-C', or just 'C'. 

When previewing the screen saver in full screen mode, it's launched just as if the screen saver
timeout happened. ParamStr(1) will contain either '/S', '-S', or just 'S'. 

When you change the screen saver password (Win95) ParamStr(1) will contain either '/A', '-A', or just
'A'. 

A screen saver has to make sure it's not launched several times. In this screen saver this is accomplished by
way of a semaphore (see Simple.dpr below). 

A couple of things to look out for when it comes to the little preview window: 

You have to wait until the window is visible 
You have to kill the previewing when the window is made invisible 

You'll see how both of these things are handled in Simple.dpr below. 

As you know a screen saver has to respond to mouse events and key presses. When you don't have a
password, it should simply shut down. When you have a password set, it should ask for the password.
You'll see this as part of the SSave unit (see SSave.pas below). 

One final note before we create the screen saver: 
Debugging a screen saver can be very tricky, so make sure you save 
your code before you run the screen saver in any way... If it locks 
up, you will most likely have to reboot, or at least kill Delphi 3 
using the Task Manager... 

OK, now let's go ahead and create the screen saver! 

1.Create a new folder, e.g. C:\Foo. Launch Delphi 3, and start a brand new application. From the Project Manager, delete Unit1 and Form1 from the project. Do a File | Save Project As, and save the project as Simple.dpr in the newly created folder. 

2.Do a File | New | Form. Select Unit1 in the Code Editor. Do a File | Save As, and save the new form as  SSetup.pas. 

3.Do a File | New | Form. Select Unit2 in the Code Editor. Do a File | Save As, and save the new form as
SSave.pas. 

4.Do a File | New | Unit. Select Unit3 in the Code Editor. Do a File | Save As, and save the new unit as
Globals.pas. 

5.Do a File | New | Unit. Select Unit3 in the Code Editor. Do a File | Save As, and save the new unit as
CodeSpot.pas. 

6.Select the form SSetup. Right click on the form and select View As Text. Replace all the text in the
editor with the code for SSetup.dfm below. Right click and select View As Form. Now go to the unit
SSetup.pas in the editor and replace all the code with the code for SSetup.pas below. 

7.Select the form SSave. Right click on the form and select View As Text. Replace all the text in the
editor with the code for SSave.dfm below. Right click and select View As Form. Now go to the unit
SSave.pas in the editor and replace all the code with the code for SSave.pas below. 

8.Select the unit Globals.pas. Replace all the code with the code for Globals.pas below. 

9.Select the unit CodeSpot.pas. Replace all the code with the code for CodeSpot.pas below. 

10.Do a View | Project Source. Replace all the code with the code for Simple.dpr below. 

11.Do a Project | Build All. 

12.Copy the compiled screen saver Simple.Scr into your system directory (Something like
C:\WinNT\System32 or C:\Win95\System). You can right click on Simple.Scr in the Explorer and select
Install. 

13.Have lots of fun with your new screen saver project! 

SSetup.pas
**********

unit Ssetup;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls, ExtCtrls, Buttons, Spin, ExtDlgs;

type
  TSetup = class(TForm)
    Ball1Box: TGroupBox;
    Label3: TLabel;
    xPos1: TSpinEdit;
    yPos1: TSpinEdit;
    xVel1: TSpinEdit;
    yVel1: TSpinEdit;
    Label5: TLabel;
    Size1: TSpinEdit;
    Label7: TLabel;
    Label4: TLabel;
    Label8: TLabel;
    Random1: TCheckBox;
    OKButton: TBitBtn;
    CancelButton: TBitBtn;
    TestButton: TBitBtn;
    procedure TestButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure OKButtonClick(Sender: TObject);
    procedure CancelButtonClick(Sender: TObject);
    procedure Random1Click(Sender: TObject);
    procedure Size1Change(Sender: TObject);
  private
    { Private declarations }
    Loading : Boolean;
  public
    { Public declarations }
  end;

var
  Setup: TSetup;

implementation

uses
  SSave, Globals;

{$R *.DFM}

procedure TSetup.TestButtonClick(Sender: TObject);
begin
  DefRandom := Random1.Checked;
  DefSize := Size1.Value;
  DefPosX := xPos1.Value;
  DefPosY := yPos1.Value;
  DefVelX := xVel1.Value;
  DefVelY := yVel1.Value;

  TestMode := True;
  Scrn := TScrn.Create(Application);
  Scrn.LoadingApp := True;
  Scrn.Left := -1000;
  Scrn.Top := -1000;
  Scrn.Width := 0;
  Scrn.Height := 0;
  Scrn.ShowModal;
  Scrn.Free;
  SetFocus;
  TestMode := False;
end;

procedure TSetup.FormCreate(Sender: TObject);
begin
  Loading := True;
end;

procedure TSetup.FormActivate(Sender: TObject);
begin
  if Loading then begin
    Loading := False;

    ReadIniFile;

    Size1.Value := DefSize;
    xPos1.Value := DefPosX;
    yPos1.Value := DefPosY;
    xVel1.Value := DefVelX;
    yVel1.Value := DefVelY;

    Random1.Checked := DefRandom;

    xPos1.MinValue := (DefSize*SpotSize div 2)+1;
    xPos1.MaxValue := Screen.Width-(DefSize*SpotSize div 2);
    yPos1.MinValue := (DefSize*SpotSize div 2)+1;
    yPos1.MaxValue := Screen.Height-(DefSize*SpotSize div 2);
  end;
end;

procedure TSetup.OKButtonClick(Sender: TObject);
begin
  DefRandom := Random1.Checked;
  DefSize := Size1.Value;
  DefPosX := xPos1.Value;
  DefPosY := yPos1.Value;
  DefVelX := xVel1.Value;
  DefVelY := yVel1.Value;

  WriteIniFile;
  Close;
end;

procedure TSetup.CancelButtonClick(Sender: TObject);
begin
  Close;
end;

procedure TSetup.Random1Click(Sender: TObject);
var
  NewColor : TColor;
begin
  NewColor := clWindow;
  with Random1 do begin
    if Checked then
      NewColor := clBtnFace;

    DefRandom := Checked;

    Size1.Enabled := not Checked;
    xPos1.Enabled := not Checked;
    yPos1.Enabled := not Checked;
    xVel1.Enabled := not Checked;
    yVel1.Enabled := not Checked;
  end;

  Size1.Color := NewColor;
  xPos1.Color := NewColor;
  yPos1.Color := NewColor;
  xVel1.Color := NewColor;
  yVel1.Color := NewColor;
end;

procedure TSetup.Size1Change(Sender: TObject);
begin
  xPos1.MinValue := (Size1.Value*SpotSize div 2)+1;
  xPos1.MaxValue := Screen.Width-(Size1.Value*SpotSize div 2);
  yPos1.MinValue := (Size1.Value*SpotSize div 2)+1;
  yPos1.MaxValue := Screen.Height-(Size1.Value*SpotSize div 2);

  xPos1.Value := xPos1.Value;
  yPos1.Value := yPos1.Value;
end;

end.

**********
SSetup.dfm
**********


object Setup: TSetup
  Left = 260
  Top = 188
  BorderIcons = []
  BorderStyle = bsDialog
  Caption = 'Simple Saver Setup'
  ClientHeight = 145
  ClientWidth = 345
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clBlack
  Font.Height = -12
  Font.Name = 'Arial'
  Font.Style = []
  Position = poScreenCenter
  ShowHint = True
  OnActivate = FormActivate
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 15
  object Ball1Box: TGroupBox
    Left = 8
    Top = 8
    Width = 329
    Height = 89
    Caption = 'Settings'
    TabOrder = 0
    object Label3: TLabel
      Left = 72
      Top = 40
      Width = 30
      Height = 15
      Caption = 'x-pos'
    end
    object Label5: TLabel
      Left = 8
      Top = 40
      Width = 23
      Height = 15
      Caption = 'Size'
    end
    object Label7: TLabel
      Left = 136
      Top = 40
      Width = 30
      Height = 15
      Caption = 'y-pos'
    end
    object Label4: TLabel
      Left = 200
      Top = 40
      Width = 24
      Height = 15
      Caption = 'x-vel'
    end
    object Label8: TLabel
      Left = 264
      Top = 40
      Width = 24
      Height = 15
      Caption = 'y-vel'
    end
    object xPos1: TSpinEdit
      Left = 72
      Top = 56
      Width = 57
      Height = 24
      MaxLength = 4
      MaxValue = 9999
      MinValue = 0
      TabOrder = 2
      Value = 0
    end
    object yPos1: TSpinEdit
      Left = 136
      Top = 56
      Width = 57
      Height = 24
      MaxLength = 4
      MaxValue = 9999
      MinValue = 0
      TabOrder = 3
      Value = 0
    end
    object xVel1: TSpinEdit
      Left = 200
      Top = 56
      Width = 57
      Height = 24
      MaxLength = 4
      MaxValue = 10
      MinValue = -10
      TabOrder = 4
      Value = 0
    end
    object yVel1: TSpinEdit
      Left = 264
      Top = 56
      Width = 57
      Height = 24
      MaxLength = 4
      MaxValue = 10
      MinValue = -10
      TabOrder = 5
      Value = 0
    end
    object Size1: TSpinEdit
      Left = 8
      Top = 56
      Width = 57
      Height = 24
      MaxLength = 4
      MaxValue = 4
      MinValue = 1
      TabOrder = 1
      Value = 1
      OnChange = Size1Change
    end
    object Random1: TCheckBox
      Left = 8
      Top = 16
      Width = 97
      Height = 17
      Caption = 'Randomize'
      TabOrder = 0
      OnClick = Random1Click
    end
  end
  object OKButton: TBitBtn
    Left = 8
    Top = 104
    Width = 73
    Height = 33
    Caption = 'Ok'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clBlack
    Font.Height = -12
    Font.Name = 'Arial'
    Font.Style = []
    ParentFont = False
    TabOrder = 1
    OnClick = OKButtonClick
    Kind = bkOK
  end
  object CancelButton: TBitBtn
    Left = 136
    Top = 104
    Width = 73
    Height = 33
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clBlack
    Font.Height = -12
    Font.Name = 'Arial'
    Font.Style = []
    ParentFont = False
    TabOrder = 2
    OnClick = CancelButtonClick
    Kind = bkCancel
  end
  object TestButton: TBitBtn
    Left = 264
    Top = 104
    Width = 73
    Height = 33
    Caption = 'Test'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clBlack
    Font.Height = -12
    Font.Name = 'Arial'
    Font.Style = []
    ParentFont = False
    TabOrder = 3
    OnClick = TestButtonClick
    Glyph.Data = {
      76010000424D7601000000000000760000002800000020000000100000000100
      0400000000000001000000000000000000001000000010000000000000000000
      800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
      FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333000000
      033333FFFF77777773F330000077777770333777773FFFFFF733077777000000
      03337F3F3F777777733F0797A770003333007F737337773F3377077777778803
      30807F333333337FF73707888887880007707F3FFFF333777F37070000878807
      07807F777733337F7F3707888887880808807F333333337F7F37077777778800
      08807F333FFF337773F7088800088803308073FF777FFF733737300008000033
      33003777737777333377333080333333333333F7373333333333300803333333
      33333773733333333333088033333333333373F7F33333333333308033333333
      3333373733333333333333033333333333333373333333333333}
    NumGlyphs = 2
  end
end

*********
SSave.pas
*********

unit Ssave;

interface

uses WinTypes, WinProcs, Graphics, Forms, Messages, Classes, Controls,
  ExtCtrls, StdCtrls, SysUtils;

type
  TScrn = class(TForm)
    Image1: TImage;
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormActivate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    Mouse : TPoint;
    procedure StartSaver(var WinMsg : TMessage); message WM_USER+1;
    procedure StopSaver(var WinMsg : TMessage); message WM_USER+2;
    procedure GetPassword;
    procedure Trigger(Sender : TObject; var Done : Boolean);
  public
    { Public declarations }
    LoadingApp : Boolean;
  end;

var
  Scrn : TScrn;
  DesktopBitmap : TBitmap;

implementation

uses
  CodeSpot, Globals, Registry;

const
  IgnoreCount : Integer = 0;

{$R *.DFM}

procedure CursorOff;
begin
  ShowCursor(False);
end;

procedure CursorOn;
begin
  ShowCursor(True);
end;

procedure TScrn.StartSaver(var WinMsg : TMessage);
begin
  DrawSpot;
end;

procedure TScrn.StopSaver(var WinMsg : TMessage);
begin
  GetPassword;
end;

procedure TScrn.GetPassword;
var
  MyMod     : THandle;
  PwdFunc   : function (Parent : THandle) : Boolean; stdcall;
  SysDir    : String;
  NewLen    : Integer;
  MyReg     : TRegistry;
  OkToClose : Boolean;
begin
  if (SSMode <> ssRun) or TestMode then begin
    Close;
    Exit;
  end;

  IgnoreCount := 5;
  OkToClose := False;
  MyReg := TRegistry.Create;
  MyReg.RootKey := HKEY_CURRENT_USER;
  if MyReg.OpenKey('Control Panel\Desktop',False) then begin
    try
      try
        ShowCursor(True);
        if MyReg.ReadInteger('ScreenSaveUsePassword') <> 0 then begin
          SetLength(SysDir,MAX_PATH);
          NewLen := GetSystemDirectory(PChar(SysDir),MAX_PATH);
          SetLength(SysDir,NewLen);
          if (Length(SysDir) > 0) and (SysDir[Length(SysDir)] <> '\') then
            SysDir := SysDir+'\';
          MyMod := LoadLibrary(PChar(SysDir+'PASSWORD.CPL'));
          if MyMod = 0 then
            OkToClose := True
          else begin
            PwdFunc := GetProcAddress(MyMod,'VerifyScreenSavePwd');
            if PwdFunc(Handle) then
              OkToClose := True;
            FreeLibrary(MyMod);
          end;
        end
        else
          OkToClose := True;
      finally
        ShowCursor(False);
      end;
    except
      OkToClose := True;
    end;
  end
  else
    OkToClose := True;

  MyReg.Free;

  if OkToClose then
    Close;
end;

procedure TScrn.Trigger(Sender : TObject; var Done : Boolean);
begin
  PostMessage(Handle,WM_USER+1,0,0);
end;

procedure TScrn.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  GetPassword;
end;

procedure TScrn.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if IgnoreCount > 0 then begin
    Dec(IgnoreCount);
    Exit;
  end;

  if (Mouse.X = -1) and (Mouse.Y = -1) then begin
    Mouse.X := X;
    Mouse.Y := Y;
  end
  else
    if (Abs(X-Mouse.X) > 2) and (Abs(Y-Mouse.Y) > 2) then begin
      Mouse.X := X;
      Mouse.Y := Y;
      GetPassword;
    end;
end;

procedure TScrn.FormCreate(Sender: TObject);
begin
  LoadingApp := True;
end;

procedure TScrn.FormActivate(Sender: TObject);
var
  Dummy : Boolean;
begin
  if LoadingApp then begin
    LoadingApp := False;
    Scrn.Color := clBlack;
    Scrn.Top := 0;
    Scrn.Left := 0;
    Scrn.Width := Screen.Width;
    Scrn.Height := Screen.Height;
    InitSpot;
    Mouse.X := -1;
    Mouse.Y := -1;
    Application.OnIdle := Trigger;
    SetWindowPos(Handle,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE + SWP_NOMOVE);
    SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,@Dummy,0);
    CursorOff;
    Scrn.Visible := True;
    SetCapture(Scrn.Handle);
  end;
end;

procedure TScrn.FormMouseDown(Sender: TObject; Button: TMouseButton;
                              Shift: TShiftState; X, Y: Integer);
begin
  GetPassword;
end;

procedure TScrn.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Dummy : Boolean;
begin
  SystemParametersInfo(SPI_SCREENSAVERRUNNING,0,@Dummy,0);
  Application.OnIdle := nil;
  ReleaseCapture;
  CursorOn;
end;

end.

*********
SSave.dfm
*********

object Scrn: TScrn
  Left = 314
  Top = 376
  HorzScrollBar.Visible = False
  BorderIcons = [biSystemMenu]
  BorderStyle = bsNone
  ClientHeight = 130
  ClientWidth = 457
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -13
  Font.Name = 'System'
  Font.Style = []
  OnActivate = FormActivate
  OnClose = FormClose
  OnCreate = FormCreate
  OnKeyDown = FormKeyDown
  OnMouseDown = FormMouseDown
  OnMouseMove = FormMouseMove
  PixelsPerInch = 96
  TextHeight = 16
  object Image1: TImage
    Left = 0
    Top = 0
    Width = 457
    Height = 130
    Align = alClient
    Visible = False
  end
end

***********
Globals.pas
***********

unit Globals;

interface

type
  TSSMode = (ssSetPwd,ssPreview,ssConfig,ssRun);

const
  SSMode      : TSSMode = ssRun;

  TestMode    : Boolean = False;

  Section     = 'Screen Saver.Simple Screen Saver';

  SpotSize    = 50;

  DefSize     : Integer = 2;
  DefPosX     : Integer = 51;
  DefPosY     : Integer = 51;
  DefVelX     : Integer = 1;
  DefVelY     : Integer = 1;

  DefRandom   : Boolean = True;

procedure ReadIniFile;
procedure WriteIniFile;

implementation

uses
  IniFiles;

procedure ReadIniFile;
var
  IniFile : TIniFile;
begin
  IniFile := TIniFile.Create('CONTROL.INI');

  DefSize := IniFile.ReadInteger(Section,'Size1',DefSize);
  DefPosX := IniFile.ReadInteger(Section,'PosX1',DefPosX);
  DefPosY := IniFile.ReadInteger(Section,'PosY1',DefPosY);
  DefVelX := IniFile.ReadInteger(Section,'VelX1',DefVelX);
  DefVelY := IniFile.ReadInteger(Section,'VelY1',DefVelY);

  DefRandom := IniFile.ReadBool(Section,'Rand1',DefRandom);

  IniFile.Free;
end;

procedure WriteIniFile;
var
  IniFile : TIniFile;
begin
  IniFile := TIniFile.Create('CONTROL.INI');

  IniFile.WriteInteger(Section,'Size1',DefSize);
  IniFile.WriteInteger(Section,'PosX1',DefPosX);
  IniFile.WriteInteger(Section,'PosY1',DefPosY);
  IniFile.WriteInteger(Section,'VelX1',DefVelX);
  IniFile.WriteInteger(Section,'VelY1',DefVelY);

  IniFile.WriteBool(Section,'Rand1',DefRandom);

  IniFile.Free;
end;

end.

************
CodeSpot.pas
************

unit Codespot;

interface

uses
  WinTypes, WinProcs, Graphics, Forms, Controls, Classes, Sysutils, Dialogs;

var
  zx, zy  : Integer;
  cx, cy,
  vx, vy,
  d       : Real;
  Picture : HBitmap;

procedure InitSpot;
procedure DrawSpot;

implementation

uses
  SSave, Globals;

procedure InitSpot;
begin
  Randomize;

  if not TestMode then
    ReadIniFile;

  zx := Screen.Width;
  zy := Screen.Height;

  d  := (Random(4)+1)*SpotSize;
  cx := Random((zx div 2)-Round(d)-1)+1;
  cy := Random(zy-Round(d)-1)+1;
  vx := Random(2)+1;
  vy := Random(2)+1;
  if Random(2) = 0 then
    vx := -vx;
  if Random(2) = 0 then
    vy := -vy;

  if not DefRandom then begin
    d := DefSize*SpotSize;
    cx := DefPosX-d/2;
    cy := DefPosY-d/2;
    vx := DefVelX;
    vy := DefVelY;
  end;

  Scrn.Image1.Picture.Bitmap := DesktopBitmap;
  Picture := Scrn.Image1.Picture.Bitmap.Handle;
end;

procedure DrawSpot;
var
  WinDC, MemDC : HDC;
  Rgn1, Rgn3   : HRgn;
begin
  WinDC := GetDC(Scrn.Handle);
  MemDC := CreateCompatibleDC(WinDC);

  SelectObject(MemDC,Picture);

  if ((cx+vx <= 0) or (cx+d+vx >= zx)) then
    vx := -vx;

  if ((cy+vy <= 0) or (cy+d+vy >= zy)) then
    vy := -vy;

  cx := cx+vx;
  cy := cy+vy;

  Rgn3 := CreateRectRgn(0,0,zx,zy);
  Rgn1 := CreateEllipticRgn(Round(cx),Round(cy),
                            Round(cx+d),Round(cy+d));

  CombineRgn(Rgn3,Rgn3,Rgn1,RGN_DIFF);
  FillRgn(WinDC,Rgn3,GetStockObject(BLACK_BRUSH));

  SelectObject(WinDC,Rgn1);
  BitBlt(WinDC,0,0,zx,zy,MemDC,0,0,SRCCOPY);

  DeleteObject(Rgn3);
  DeleteObject(Rgn1);

  DeleteDC(MemDC);
  ReleaseDC(Scrn.Handle,WinDC);
end;

end.

**********
Simple.dpr
**********

program Simple;

uses
  Forms,
  SysUtils,
  Windows,
  Graphics,
  Classes,
  Ssave in 'SSave.pas' {Scrn},
  Codespot in 'CodeSpot.pas',
  Ssetup in 'SSetup.pas' {Setup},
  Globals in 'Globals.pas';

{$E SCR}
{$R *.RES}

var
  MySem       : THandle;
  Arg1,
  Arg2        : String;
  DemoWnd     : HWnd;
  MyRect      : TRect;
  MyCanvas    : TCanvas;
  x, y,
  dx, dy      : Integer;
  MyBkgBitmap,
  InMemBitmap : TBitmap;
  ScrWidth,
  ScrHeight   : Integer;
  SysDir      : String;
  NewLen      : Integer;
  MyMod       : THandle;
  PwdFunc     : function (a : PChar; ParentHandle : THandle; b, c : Integer) : 
                    Integer; stdcall;

begin
  Arg1 := UpperCase(ParamStr(1));
  Arg2 := UpperCase(ParamStr(2));

  if (Copy(Arg1,1,2) = '/A') or (Copy(Arg1,1,2) = '-A') or
     (Copy(Arg1,1,1) = 'A') then
    SSMode := ssSetPwd;

  if (Copy(Arg1,1,2) = '/P') or (Copy(Arg1,1,2) = '-P') or
     (Copy(Arg1,1,1) = 'P') then
    SSMode := ssPreview;

  if (Copy(Arg1,1,2) = '/C') or (Copy(Arg1,1,2) = '-C') or
     (Copy(Arg1,1,1) = 'C') or (Arg1 = '') then
    SSMode := ssConfig;

  if SSMode = ssSetPwd then begin
    SetLength(SysDir,MAX_PATH);
    NewLen := GetSystemDirectory(PChar(SysDir),MAX_PATH);
    SetLength(SysDir,NewLen);
    if (Length(SysDir) > 0) and (SysDir[Length(SysDir)] <> '\') then
      SysDir := SysDir+'\';
    MyMod := LoadLibrary(PChar(SysDir+'MPR.DLL'));
    if MyMod <> 0 then begin
      PwdFunc := GetProcAddress(MyMod,'PwdChangePasswordA');
      if Assigned(PwdFunc) then
        PwdFunc('SCRSAVE',StrToInt(Arg2),0,0);
      FreeLibrary(MyMod);
    end;
    Halt;
  end;

  MySem := CreateSemaphore(nil,0,1,'SimpleSaverSemaphore');
  if ((MySem <> 0) and (GetLastError = ERROR_ALREADY_EXISTS)) then begin
    CloseHandle(MySem);
    Halt;
  end;

  Application.Initialize;

  if SSMode = ssPreview then begin
    DemoWnd := StrToInt(Arg2);
    while not IsWindowVisible(DemoWnd) do
      Application.ProcessMessages;
    GetWindowRect(DemoWnd,MyRect);
    ScrWidth := MyRect.Right-MyRect.Left+1;
    ScrHeight := MyRect.Bottom-MyRect.Top+1;
    MyRect := Rect(0,0,ScrWidth-1,ScrHeight-1);
    MyCanvas := TCanvas.Create;
    MyCanvas.Handle := GetDC(DemoWnd);
    MyCanvas.Pen.Color := clWhite;
    x := (ScrWidth div 2)-16;
    y := (ScrHeight div 2)-16;
    dx := 1;
    dy := 1;
    MyBkgBitmap := TBitmap.Create;
    with MyBkgBitmap do begin
      Width := ScrWidth;
      Height := ScrHeight;
    end;
    MyBkgBitmap.Canvas.FillRect(Rect(0,0,ScrWidth-1,ScrHeight-1));
    InMemBitmap := TBitmap.Create;
    with InMemBitmap do begin
      Width := ScrWidth;
      Height := ScrHeight;
    end;
    while IsWindowVisible(DemoWnd) do begin
      InMemBitmap.Canvas.CopyRect(MyRect,MyBkgBitmap.Canvas,MyRect);
      InMemBitmap.Canvas.Draw(x,y,Application.Icon);
      MyCanvas.CopyRect(MyRect,InMemBitmap.Canvas,MyRect);
      Sleep(10);
      Application.ProcessMessages;
      if (x = 0) or (x = (ScrWidth-33)) then
        dx := -dx;
      if (y = 0) or (y = (ScrHeight-33)) then
        dy := -dy;
      x := x+dx;
      y := y+dy;
    end;
    MyBkgBitmap.Free;
    InMemBitmap.Free;
    MyCanvas.Free;
    CloseHandle(MySem);
    Halt;
  end;

  DesktopBitmap := TBitmap.Create;
  with DesktopBitmap do begin
    Width := Screen.Width;
    Height := Screen.Height;
  end;
  BitBlt(DesktopBitmap.Canvas.Handle,0,0,Screen.Width,Screen.Height,
          GetDC(GetDesktopWindow),0,0,SrcCopy);

  if SSMode = ssConfig then begin
    Application.CreateForm(TSetup, Setup);
  end else
    Application.CreateForm(TScrn,Scrn);

  Application.Run;

  DesktopBitmap.Free;
  CloseHandle(MySem);
end.

Reference:
None

4/22/99 4:08:08 PM
 

Last Modified: 01-SEP-99