Bonjour,
Étant lassé de voir toujours le même fond d'écran et n'ayant pas envie de le changer constamment manuellement, je me suis mis à la création d'une application faisant varier mon fond d'écran aléatoirement sur base de photo se trouvant dans un répertoire donné. Cette application est prévue pour WinXP (Win7 prévoyant déjà cette fonctionnalité pour les fonds d'écran)
Mon programme fonctionne comme suit :
- l'utilisateur définit un répertoire source d'où l'application puisera les photos
- pour chaque photo, l'application l'ouvre dans une picturebox cachée, la redimensionne et la sauve dans un répertoire de travail pour ne pas utiliser directement les photos de l'utilisateur
- une fois la source de photo définie, l'utilisateur défini un interval de temps via un contrôle numericupdown
- l'utilisateur clique sur le bouton start ce qui lance le timer avec l'interval définit et qui, à chaque interval, fera varier l'écran de fond de windows
Voici maintenant un peu de code (certains passages ont été repris de codes existants trouvés sur le net):
point 1point 2
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 Private Sub DefineTheSourceFolderToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DefineTheSourceFolderToolStripMenuItem.Click If fbdSourcefolder.ShowDialog = Windows.Forms.DialogResult.OK Then sourceDir = fbdSourcefolder.SelectedPath For Each file As String In IO.Directory.GetFiles(WallpaperDir) IO.File.Delete(file) Next Form1.InitializePictureBox() MessageBox.Show("Transfert and resizing pictures done") End If End Subpoint 3 et 4
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
120
121 Dim Sw, Sh As Integer Dim Pw1, Ph1, Pw2, Ph2 As Integer Dim newName As String = "" Public Sub InitializePictureBox() Sw = getScreenWidth() Sh = getScreenHeight() If Sw >= Sh Then ResizeEnFonctionDeH() Else ResizeEnFonctionDeW() End If End Sub Public Sub ResizeEnFonctionDeH() For Each filename As String In Directory.GetFiles(Main.sourceDir) 'PictureBox1 doit etre posé sur le form 'c genant de pouvoir voir le picturebox1, qui sert uniquement pour 'qualculer le ration de l'image a transformer ' Set picturebox1 not visible Me.PictureBox1.Visible = False ' Set the SizeMode property. Me.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize PictureBox1.Image = System.Drawing.Image.FromFile(filename) 'get W1 and H1 pour calculer le ratio Pw1 = Me.PictureBox1.Width Ph1 = Me.PictureBox1.Height 'nouveau size pour picturebox2 (uniquement si la hauteur de la photo est plus grande que la hauteur de l'écran) If Ph1 > Sh Then Ph2 = Sh Pw2 = CInt(Math.Round(Ph2 * Pw1 / Ph1)) Else Ph2 = Ph1 Pw2 = Pw1 End If 'et maintenant la transformation : ' Get the source bitmap. Dim bm_source As New Bitmap(Me.PictureBox1.Image) ' bitmap pour le resultat. Dim bm_dest As New Bitmap(Pw2, Ph2) ' Creer un GraphicsOject pour le resultat du Bitmap. Dim gr_dest As Graphics = Graphics.FromImage(bm_dest) ' Copy l'image source dans le bitmap. gr_dest.DrawImage(bm_source, 0, 0, Pw2, Ph2) ' Display result in picturebox2. ' Picturebox2 contient l'image transformé et avec le meme ratio 'location of Picturebox2 Me.PictureBox2.Left = 5 Me.PictureBox2.Top = 5 'stretch ne deforme pas l'image ici parceque le ration a ete calculé Me.PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage 'Adjust size of picturebox2 to custome size Me.PictureBox2.Width = Pw2 Me.PictureBox2.Height = Ph2 Me.PictureBox2.Image = bm_dest ' sauvegarder l'image en jpg newName = Main.WallpaperDir & filename.Substring(filename.LastIndexOf("\")) Me.PictureBox2.Image.Save(newName, System.Drawing.Imaging.ImageFormat.Jpeg) 'on peut auusi sauvegarder in gif, bmp etc. bm_source.Dispose() bm_dest.Dispose() gr_dest.Dispose() 'GC.Collect() Next End Sub Public Sub ResizeEnFonctionDeW() For Each filename As String In Directory.GetFiles(Main.sourceDir) 'PictureBox1 doit etre posé sur le form 'c genant de pouvoir voir le picturebox1, qui sert uniquement pour 'qualculer le ration de l'image a transformer ' Set picturebox1 not visible Me.PictureBox1.Visible = False ' Set the SizeMode property. Me.PictureBox1.SizeMode = PictureBoxSizeMode.AutoSize PictureBox1.Image = System.Drawing.Image.FromFile(filename) 'get W1 and H1 pour calculer le ratio Pw1 = Me.PictureBox1.Width Ph1 = Me.PictureBox1.Height 'nouveau size pour picturebox2 (uniquement si la largeur de la photo est plus grande que la largeur de l'écran) If Pw1 > Sw Then Pw2 = Sw Ph2 = CInt(Math.Round(Pw2 * Ph1 / Pw1)) Else Pw2 = Pw1 Ph2 = Ph1 End If 'et maintenant la transformation : ' Get the source bitmap. Dim bm_source As New Bitmap(Me.PictureBox1.Image) ' bitmap pour le resultat. Dim bm_dest As New Bitmap(Pw2, Ph2) ' Creer un GraphicsOject pour le resultat du Bitmap. Dim gr_dest As Graphics = Graphics.FromImage(bm_dest) ' Copy l'image source dans le bitmap. gr_dest.DrawImage(bm_source, 0, 0, Pw2, Ph2) ' Display result in picturebox2. ' Picturebox2 contient l'image transformé et avec le meme ratio 'location of Picturebox2 Me.PictureBox2.Left = 5 Me.PictureBox2.Top = 5 'stretch ne deforme pas l'image ici parceque le ration a ete calculé Me.PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage 'Adjust size of picturebox2 to custome size Me.PictureBox2.Width = Pw2 Me.PictureBox2.Height = Ph2 Me.PictureBox2.Image = bm_dest ' sauvegarder l'image en jpg newName = Main.WallpaperDir & filename.Substring(filename.LastIndexOf("\")) Me.PictureBox2.Image.Save(newName, System.Drawing.Imaging.ImageFormat.Jpeg) 'on peut auusi sauvegarder in gif, bmp etc. bm_source.Dispose() bm_dest.Dispose() gr_dest.Dispose() 'GC.Collect() Next End SubLe plus gros problème se situe au niveau du point 2. Si le répertoire désigné par l'utilisateur contient un nombre trop important de photo, il en résultera une erreur dont le message est "Out of memory". Effectivement, lorsque je regarde les infos du process dans le gestionnaire des tâches, la mémoire utilisée augmente très vite et sans jamais redescendre. J'ai pourtant ajouté un appel à la méthode Dispose pour chaque new qui est fait précédent dans l'application mais rien n'y fait. J'ai également tenté de faire appel au GarbageCollector mais cela ne change rien non plus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 Private Const SPI_SETDESKWALLPAPER As Integer = &H14 Private Const SPIF_UPDATEINIFILE As Integer = &H1 Private Const SPIF_SENDWININICHANGE As Integer = &H2 Public WallpaperDir As String = Application.ExecutablePath.Substring(0, Application.ExecutablePath.LastIndexOf("\") + 1) & "Wallpaper" Public sourceDir As String = "" Dim images As New ArrayList Dim randomNumber As New Random Dim newNumber, oldNumber As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click For Each image As String In IO.Directory.GetFiles(WallpaperDir) images.Add(image) Next Randomize() timer.Interval = nudInterval.Value * 1000 timer.Enabled = True End Sub Private Sub Timer1_Elapsed(ByVal sender As System.Object, ByVal e As System.Timers.ElapsedEventArgs) Handles timer.Elapsed bgwWallPaper.RunWorkerAsync() End Sub Private Sub bgwWallPaper_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwWallPaper.DoWork Dim sfilename As String oldNumber = newNumber newNumber = randomNumber.Next(images.Count) While oldNumber = newNumber newNumber = randomNumber.Next(images.Count) End While sfilename = images(newNumber).ToString SetWallpaper(Image.FromFile(sfilename)) End Sub Private Declare Auto Function SystemParametersInfo Lib "user32.dll" ( _ ByVal uAction As Integer, ByVal uParam As Integer, _ ByVal lpvParam As String, ByVal fuWinIni As Integer) As Integer ' change this to whatever filename you want to use Const WallpaperFile As String = "MovieCollectionImage.bmp" ''' <SUMMARY> ''' Sets the background of your Windows desktop. ''' The image will be saved in MyPictures and the background ''' wallpaper updated. ''' </SUMMARY> ''' The image to be set as the background. ''' <REMARKS></REMARKS> Friend Sub SetWallpaper(ByVal img As Image) Dim imageLocation As String imageLocation = My.Computer.FileSystem.CombinePath( _ My.Computer.FileSystem.SpecialDirectories.MyPictures, WallpaperFile) Try img.Save(imageLocation, System.Drawing.Imaging.ImageFormat.Bmp) SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, _ SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE) Catch Ex As Exception MsgBox("There was an error setting the wallpaper: " & Ex.Message) End Try End Sub
J'avoue que c'est un des aspects de la programmation qui reste encore très flou pour moi. Je n'ai jamais eu aucune formation sur ce qui concerne la gestion des ressources et le peu que j'en sais, je l'ai appris en parcourant ce forum et manifestement, ce n'est pas suffisant.
Bref, pouvez-vous m'aider à ce sujet ?
Merci d'avance.
Griftou.
Partager