|
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 :
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
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 ! 
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.






Version 1.0.1.1 :
bonjour
) mois j’aimerais bien avec une petite araignée
@Whiler : j’adore mais au lieu de gérer un flocon (on en a assez eu cet hiver non !
Si on pouvait choisir son bitmap
ps : ton répertoire http://www.whiler.com/freewares/dl/ est accessible …et par là à ta liste de dvd
normal ?
bonne fin de semaine
@ philgoodgood : Merci pour la sécurité du répertoire… c’est corrigé…
Pour ce qui est du bitmap, j’y ai pensé.. mais typiquement, une araignée, ça peut aller dans tous les sens
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
@Whiler : Ah ben tu es plus rapide que le fbi … déjà verrouillé …
oui a l’occasion j’dis pas non
++
@ 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
@ Whiler : à yes While … comme je suis strong
modifié/traduit par Whiler
Politique de confidentialité