Fév 26

Chaque flocon s’anime de façon autonome… Du fait d’utiliser les animations, je n’ai pas eu besoin d’allouer et d’initialiser moi-même des threads pour les gérer.
Un flocon est codé ainsi :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
unit uSnowflake;

interface

uses FMX.Objects, FMX.Types, System.Classes, Winapi.Windows, System.Math, FMX.Ani, FMX.Filter.Effects;

type
  TSnowflake = class(TImage)
    private
      FloatAnimationHorizontal: TFloatAnimation;
      FloatAnimationVertical  : TFloatAnimation;
      hue                     : THueAdjustEffect;
      FloatAnimationHue       : TFloatAnimation;
      procedure FloatAnimationVerticalFinish(Sender: TObject);
    public
      constructor GenerateSnowflake(AOwner: TComponent; parent: TFMXObject; sSprite: string);
  end;

implementation

{ TSnowflake }

uses uShared;

procedure TSnowflake.FloatAnimationVerticalFinish(Sender: TObject);
begin
  Self.Free;
end;

constructor TSnowflake.GenerateSnowflake(AOwner: TComponent; parent: TFMXObject; sSprite: string);
var
  rsSnowflake : TResourceStream;
  cParent     : TControl;
  dSize       : Double;
begin
  inherited Create(AOwner);
  Self.Parent  := parent;
  Self.HitTest := False;

  cParent := (parent as TControl);

  rsSnowflake := TResourceStream.Create(HInstance, sSprite, RT_RCDATA);
  try
    try
      rsSnowflake.Position := 0;
      Self.Bitmap.LoadFromStream(rsSnowflake);
      dSize := TConfig.Size;
      Self.Width  := Self.Bitmap.Width  * dSize;
      Self.Height := Self.Bitmap.Height * dSize;
      Self.Position.X := RandomRange(0, Round(cParent.Width));
      Self.Position.Y := -Self.Height;

      FloatAnimationHorizontal               := TFloatAnimation.Create(Self);
      FloatAnimationHorizontal.Parent        := Self;
      FloatAnimationHorizontal.StartValue    := Self.Position.X;
      FloatAnimationHorizontal.StopValue     := Self.Position.X + RandomRange(5, 100);
      FloatAnimationHorizontal.PropertyName  := 'Position.X';
      FloatAnimationHorizontal.AnimationType := TAnimationType.atInOut;
      FloatAnimationHorizontal.Interpolation := TInterpolationType.itElastic;
      FloatAnimationHorizontal.Loop          := True;
      FloatAnimationHorizontal.AutoReverse   := True;
      FloatAnimationHorizontal.Duration      := RandomRange(2, 10);

      FloatAnimationVertical              := TFloatAnimation.Create(Self);
      FloatAnimationVertical.Parent       := Self;
      FloatAnimationVertical.OnFinish     := FloatAnimationVerticalFinish;
      FloatAnimationVertical.StartValue   := Self.Position.Y;
      FloatAnimationVertical.StopValue    := cParent.Height;
      FloatAnimationVertical.PropertyName := 'Position.Y';
      FloatAnimationVertical.Duration     := RandomRange(10, 15);

      hue         := THueAdjustEffect.Create(Self);
      hue.Parent  := Self;
      hue.Hue     := 0.3;
      hue.Enabled := True;
      FloatAnimationHue              := TFloatAnimation.Create(Self);
      FloatAnimationHue.Parent       := Hue;
      FloatAnimationHue.StartValue   := -0.2;
      FloatAnimationHue.StopValue    :=  0.3;
      FloatAnimationHue.PropertyName := 'Hue';
      FloatAnimationHue.Duration     := RandomRange(5, 20);
      FloatAnimationHue.AutoReverse  := True;
      FloatAnimationHue.Loop         := True;

      FloatAnimationHorizontal.Start;
      FloatAnimationVertical.Start;
      FloatAnimationHue.Start;
    except
      begin
        Self.Free;
      end;
    end;
  finally
    rsSnowflake.Free;
  end;

//  Self.Free;
end;

end.

La fiche principale qui va afficher l’écran de veille, frmMain, est très simple. C’est une fiche avec un BorderStyle défini à bsNone, qui a un fond noir et qui est toujours au dessus des autres (TopMost := True). Je lui ai ajouté un TRectangle pour gérer les événements de la souris et un TTimer pour l’ajout à intervalle régulier de nouveaux flocons :

Conception de la fenêtre principale

Conception de la fenêtre principale

Puisque l’on peut avoir plusieurs écrans sur un même ordinateur, et que l’écran de veille doit tous les recouvrir, j’ai repris quatre fonctions existant dans la VCLW : DesktopHeight, DesktopLeft, DesktopTop & DesktopWidth.
Je surcharge également la procédure KeyDown pour détecter les frappes sur le clavier afin de pouvoir fermer l’écran de veille.
L’ensemble du code se présente ainsi :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
unit main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Math,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, Winapi.Windows, Winapi.MultiMon, FMX.Objects, FMX.Ani, FMX.Filter.Effects;

type
  TfrmMain = class(TForm)
    recBG: TRectangle;
    tmrSnowFlake: TTimer;
    procedure recBGMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
    procedure recBGClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure tmrSnowFlakeTimer(Sender: TObject);
  private
    pMouse  : TPointF;
    function DesktopHeight: Integer;
    function DesktopLeft: Integer;
    function DesktopTop: Integer;
    function DesktopWidth: Integer;
    { Private declarations }
  public
    { Public declarations }
    procedure KeyDown(var Key: Word; var KeyChar: Char; Shift: TShiftState); override;
  end;

const
  DELTA_MOUSE = 5;

var
  frmMain: TfrmMain;

implementation

{$R *.fmx}

uses uShared, uSnowflake;

{ TfrmMain }

{$region 'Taille du bureau virtuel'}
function TfrmMain.DesktopLeft: Integer;
begin
  Result := GetSystemMetrics(SM_XVIRTUALSCREEN);
end;

function TfrmMain.DesktopWidth: Integer;
begin
  Result := GetSystemMetrics(SM_CXVIRTUALSCREEN);
end;

function TfrmMain.DesktopTop: Integer;
begin
  Result := GetSystemMetrics(SM_YVIRTUALSCREEN);
end;

function TfrmMain.DesktopHeight: Integer;
begin
  Result := GetSystemMetrics(SM_CYVIRTUALSCREEN);
end;
{$endregion}

procedure TfrmMain.KeyDown(var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
  inherited;

  // On ferme la fenêtre pour quitter l'application
  Self.Close;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Randomize;

  Self.Left    := DesktopLeft;
  Self.Width   := DesktopWidth;
  Self.Top     := DesktopTop;
  Self.Height  := DesktopHeight;

  pMouse.X := Pred(Self.Left);
  pMouse.Y := Pred(Self.Top);

  ShowCursor(False);

  tmrSnowFlake.Interval := TConfig.Frequency;
  tmrSnowFlake.Enabled  := True;
end;

procedure TfrmMain.recBGClick(Sender: TObject);
begin
  // On ferme la fenêtre pour quitter l'application
  Self.Close;
end;

procedure TfrmMain.recBGMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single);
begin
  if ((pMouse.X <> Pred(Self.Left)) or (pMouse.Y <> Pred(Self.Top))) then // Valeur initiale
  begin
    if ((Abs(pMouse.X - X) > DELTA_MOUSE) or (Abs(pMouse.Y - Y) > DELTA_MOUSE)) then // Tolérance à un léger décalage...
    begin
      // La souris a bougé... on ferme la fenêtre pour quitter l'application
      Self.Close;
    end;
  end;

  // On met à jour les coordonnées
  pMouse.X := X;
  pMouse.Y := Y;
end;

procedure TfrmMain.tmrSnowFlakeTimer(Sender: TObject);
begin
  // Affichage d'un flocon
  TSnowflake.GenerateSnowflake(Self, recBG, 'sf' + IntToStr(RandomRange(1, 25))); // Affichage aléatoire d'un des 24 flocons
end;

end.

Voila 8-) Avec ces quelques lignes de code, je me suis créé mon propre écran de veille…
Il ne me reste plus qu’à modifier l’extension de mon application en scr au lieu de exe, et je pourrais ensuite l’installer ! (y)

Extension du fichier généré

Extension du fichier généré

Concrètement, si vous souhaitez tester le résultat, vous pouvez également le télécharger depuis ce lien ;) Vous pouvez également télécharger un autre écran de veille basé sur le même code qui utilise encore plus d’effet !

 

Écrans de veille développés avec Embarcadero Delphi XE2.

Développé en Delphi

Share

Pages : 1 2 3 4

Lien permanent vers Ecran de veille avec FireMonkey Rédigé par Whiler \\ Tags : , , , ,

6 réponses pour “Ecran de veille avec FireMonkey”

  1. Whiler a dit :

    Version 1.0.1.1 :

    • Ajout de l’affichage d’informations :si l’on appuie sur la touche i de son clavier, les infos sont affichées/masquées

    Informations

    Répondre

  2. philgoodgood a dit :

    bonjour
    @Whiler : j’adore mais au lieu de gérer un flocon (on en a assez eu cet hiver non ! |-( ) mois j’aimerais bien avec une petite araignée
    Si on pouvait choisir son bitmap (bow)

    ps : ton répertoire http://www.whiler.com/freewares/dl/ est accessible …et par là à ta liste de dvd 8-) normal ?

    bonne fin de semaine

    Répondre

  3. Whiler a dit :

    @ philgoodgood : Merci pour la sécurité du répertoire… c’est corrigé… (y)

    Pour ce qui est du bitmap, j’y ai pensé.. mais typiquement, une araignée, ça peut aller dans tous les sens (lol) pas seulement descendre… ça serait bizarre… |-(
    Si tu me files une jolie araignée sur fond transparent, et encore mieux, des sprites pour lui faire bouger les pattes… pourquoi pas ;)

    Répondre

  4. philgoodgood a dit :

    @Whiler : Ah ben tu es plus rapide que le fbi … déjà verrouillé …

    oui a l’occasion j’dis pas non (lol)

    ++

    Répondre

  5. Whiler a dit :

    @ philgoodgood : Pour info, en bas à droite de chaque message, il y a un bouton Répondre… si tu cliques dessus, ça t’évitera de taper le @user comme tu sembles le faire ;)

    Répondre

  6. philgoodgood a dit :

    @ Whiler : à yes While … comme je suis strong (devil)

    Répondre

Laisser une réponse

(requis)

(requis)

*

;) (lol) (y) |-( (hi) 8-) (angel) :s (clap) (bow) (tmi) (:| plus »

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.