Wallpaper Changer

Wallpaper Changer: Wallpaper Genie

One of my hobbies is collecting wallpapers. This hobby inspired me to create an application that can automatically or manually change my computer's wallpaper. One more thing that inspired me to write this wallpaper changer was the fact that having a wallpaper changing frequently gives an entire different feel to the computer screen, as opposed to having one wallpaper for the entire year. This article will demonstrate how to create an application that changes your wallpapers after a specified period, as well as how to apply the Tile, Center, and Stretch wallpaper styles.

Design

The design is actually quite simple. The main controls you will need to have is a way to view the various wallpapers and their locations on the system; for this, you will use a Treeview. This Treeview displays all the folders as nodes, and then the contents of each particular folder as subnodes. You will need a PictureBox to preview the selection. Further, you also will need eight different Radiobuttons. Three of these Radio buttons will allow you to set the style for the wallpaper (Center, Stretch, Tile); Two Radiobuttons will be used to indicate what mode you want the wallpaper program to perform in. In Automatic mode, the wallpaper and style get applied without you having to do anything. Manual mode will allow you to select the wallpaper along with all the other settings, manually. Finally, the last three Radiobuttons will allow you to select how often you want the wallpaper to change (Daily, Weekly, or Monthly).

Add the following controls with their settings to your form:

Control Property Setting Description
Label Name lblDate Display Today's Date
  AutoSize True
  Text "" (Empty String)
Label Name lblNumFiles Displays How Many Items In Repository
  AutoSize True
  Text "" (Empty String)
Label Name lblCurrent Displays The Current Wallpaper
  AutoSize True
  Text "" (Empty String)
Treeview Name trGenie Displays All Folders, Sub Folders, and Files, so that you can make a selection
  Sorted True
PictureBox Name picPreview Displays a Thumbnail (smaller picture) of the selected picture
  BorderStyle Fixed3D
PictureBox Name picRealGenie Used to store the selected picture in its original size, so that you still can save the picture without modifying its size
  Visible False
  SizeMode AutoSize
ListBox Name lstFound Used to list all the picture files' names. Mainly used for the randomizing of the pictures, where you randomly select a listitem that stores the location of the picture
  Visible False
Panel Name Panel1 Holds the Styles radiobuttons
RadioButton (Inside Panel1) Name rdTile To Set Wallpaper Tiling
  Text Tile
RadioButton (Inside Panel1) Name rdCenter To set Wallpaper Centering
  Text Center
RadioButton (Inside Panel1) Name rdStretch To set Stretching of Wallpaper
  Text Stretch
RadioButton Name rdAuto Set Automatic mode
  Text Automatic
RadioButton Name rdManual Set Manual mode
  Text Manual
GroupBox Name gbAuto Stores the Automatic Options controls
  Text Automatic Options
Label (Inside gbAuto) Name Label1 Indicates where to enter Frequency
  Text Frequency:
Textbox (Inside gbAuto) Name txtFreq Allows you to enter the frequency, a number. For example: 1 may mean 1 day, 1 week, or 1 month
  Size 24, 21
RadioButton (Inside gbAuto) Name rdDay Allows you to set Day as a Period
  Text Day(s)
RadioButton (Inside gbAuto) Name rdWeek Allows you to set Week as a Period
  Text Week(s)
RadioButton (Inside gbAuto) Name rdMonth Allows you to set Month as a Period
  Text Month(s)
Button Name cmdEnd To Exit
  Text Exit
  Enabled False
Button Name cmdCancel To Cancel, hide the form
  Text Cancel
  DialogResult Cancel
Button Name cmdApply To Apply the Wallpaper with its settings
  Text Apply
NotifyIcon Name niGenie Allows you to change the settings, when minimised, in Automatic mode
  ContextMenu cmGenie
  Icon Set any icon of your Choice
  Text Wallpaper Genie
  Visible True
ContextMenu Name cmGenie Shows the Menu Items
MenuItem (on cmGenie) Name mnuSettings Allows you to return to the form, to set new settings
  Text Settings
MenuItem (on cmGenie) Name MenuItem1 Seperator
  Text -
MenuItem (on cmGenie) Name mnuExit Exit
  Text Exit

Your form's design should now look more or less like the following picture:

Figure 1

Wallpaper Changer

Coding

Variables

Because your application will make use of various File methods, Imaging methods, and the SystemParametersInfo API, you will need to create the following Imports at the top of your Form's class declaration:

'Import System.IO For File Operations In The TreeGenie Sub
Imports System.IO
'Import System.Draing.Imaging Saving The ImageFormat In The
'ApplyGenie Sub
Imports System.Drawing.Imaging
'Import For The SystemParametesInfo API
Imports System.Runtime.InteropServices

Next, add the SystemParametersInfo API, along with all its constants:

<DllImport("user32", EntryPoint:="SystemParametersInfo", _
   CharSet:=CharSet.Auto, SetLastError:=True)> _
'API Used for System Settings
Private Shared Function SystemParametersInfo(ByVal uAction As Integer, _
   ByVal uParam As Integer, ByVal lpvParam As String, _
   ByVal fuWinIni As Integer) As Integer End Function
Private Const SPI_SETDESKWALLPAPER = 20    'Set WallPaper
Private Const SPIF_UPDATEINIFILE = &H1     'Update The INI File
Private Const SPIF_SENDWININICHANGE As Int32 = &H2

Next, you need to create your own variables. Because you are going to save values to the Registry, and then load them again from the Registry, you need to know what to save as well as what the values are that you are loading. you will also need boolean flags to indicate whether or not a particular setting has been set.

'Treeview Selection ( SaveReg )
Private SelGenie As String
'Named Stored In Registry ( LoadReg )
Private SelGenieReg As String
'Period ( Day, Week, Month ) ( SaveReg )
Private GenPeriod As String
'Period From Registry ( Day, Week, Month ) ( LoadReg )
Private GenPeriodReg As String
'Duration ( SaveReg )
Private GenDur As String
'Duration ( LoadReg )
Private GenDurReg As String
'Mode ( Automatic / Manual ) ( SaveReg )
Private AutoGenie As String
'Mode ( Automatic / Manual ) ( LoadReg )
Private AutoGenieReg As String
'Wallpaper Saved
Private WallAutoReg As String
'Date From Reg
Private DateReg As String
'Wallpaper From Registry
Private GenStr As String
'Tag Of Each Node
Private TreeTagStr As String

'Location Of Pictures
'You Could Have Any Path Here, For Example : "C:\WallPapers"
Private DirName As String = Application.StartupPath

Private key As Microsoft.Win32.RegistryKey = _
   Microsoft.Win32.Registry.CurrentUser.OpenSubKey( _
   "Control Panel", True)

Private AppSettingsChanged As Boolean    'Did Settings Change
Private ApplyGen As Boolean              'Is Apply Clicked?
'EveryThing Is Fine, For Exit
Private Xit As Boolean
'Something Is Selected In Treeview
Private Tree As Boolean

Private WPStyle As Integer     'Wallpaper Style
Private NumFiles As Integer    'Number Of Files

Subs

The first sub you are going to add is the TreeGenie sub. The purpose of this sub is to scan the specified folder for any sub folders, and the contents of those folders. As it scans through all the files, it tests the file extensions to see whether the file extensions are extensions for valid picture types; if the current file is indeed a picture, it adds the file name to the Treeview. With this example, I only made use of the .bmp, .jpg, .jpe, and .gif extensions; feel free to add any extensions you may see fit.

The TreeGenie sub:

'Traverses DirName, And Loads All Picture Files Into The Treeview
Private Sub TreeGenie()
   Dim FolderNode As TreeNode         'Treeview Node
   Dim FilePath As String             'File Path
   Dim FolderPath As String           'Folder Path
   Dim Xtension As String             'File Extensions
   Dim diNext As DirectoryInfo        'Directory Information Object

   Me.Cursor = Cursors.WaitCursor     'Set Cursor

   'Search Folders In DirName
   For Each FolderPath In Directory.GetDirectories(DirName, "*")
   'Add Each Sub Folder As A TreeNode
      FolderNode = trGenie.Nodes.Add(Path.GetFileName(FolderPath))

      'Search Files Within Sub Folders
      For Each FilePath In Directory.GetFiles(FolderPath)
         'Identify File Extension
         Xtension = IO.Path.GetExtension(FilePath)

         If Xtension = ".bmp" OrElse Xtension = ".BMP" _
            OrElse Xtension = ".jpg" _
            OrElse Xtension = ".JPG" OrElse Xtension = ".jpe" _
            OrElse Xtension = ".JPE" _
            OrElse Xtension = ".gif" OrElse Xtension = ".GIF" _
            'Test For Valid File Extensions ( Pictures Only )
            Then

            'Get Each File's Path
            Dim TagNode As New TreeNode(Path.GetFileName(FilePath))
            'Add File Path To Node's Tag Property
            TagNode.Tag = Path.GetFileName(FilePath)
            FolderNode.Nodes.Add(TagNode)    'Add The Files
            NumFiles = NumFiles + 1          'Increment File Count

            'Add File Path To Invisible Listbox
            lstFound.Items.Add(FilePath)

         End If
      Next
   Next
   lblNumFiles.Text = "Select From " _    'Display Number Of Files
      & NumFiles.ToString() _
      & " Items In Repository"

End Sub

Wallpaper Changer

The LoadReg sub, your second sub, is used to extract all the information from the Registry. Once the sub has pulled the information from the Registry, it stores each particular setting into its own variable. If you already have stored information into the Registry on an earlier run of this program, it uses that information further. For example, this sub automatically selects the current selected wallpaper in the Treeview, and automatically shows a thumbnail representation of the selected wallpaper. Figure 2 shows all the settings that get stored into the Registry and loaded from the Registry.

Private Sub LoadReg()                'Load From Registry

   Me.Cursor = Cursors.WaitCursor    'Set Curosr To "Waiting"
   Try
      'If Value Stored, Obtain & Store Mode Value

      If Not (Application.UserAppDataRegistry.GetValue("Mode") _
      Is Nothing) Then
         AutoGenieReg = _
            Application.UserAppDataRegistry.GetValue( _
            "Mode").ToString()
      End If
      'If Value Stored, Obtain & Store WallAuto Value
      If Not (Application.UserAppDataRegistry.GetValue("WallAuto") _
         Is Nothing) Then
         WallAutoReg = _
            Application.UserAppDataRegistry.GetValue( _
            "WallAuto").ToString()
      End If
      'If Value Stored, Obtain &Store WallPaperName Value
      If Not (Application.UserAppDataRegistry.GetValue("WallPaperName") _
         Is Nothing) Then
            SelGenieReg = _
               Application.UserAppDataRegistry.GetValue( _
               "WallPaperName").ToString()

               'Is Mode Manual, Create Thumbnail For Display
               If AutoGenieReg = "Manual" Then

               Dim NewImage As Image = _
                  Image.FromFile(DirName & "\" & SelGenieReg)

               Dim DestSize As New Bitmap( _
                    CInt(picPreview.Width), _
                    CInt(picPreview.Height))

               Dim GenDest As Graphics = Graphics.FromImage(DestSize)

               GenDest.DrawImage(NewImage, 0, 0, _
                    DestSize.Width + 1, _
                    DestSize.Height + 1)
               picPreview.Image = DestSize
         Else
            'Is Mode Automatic, Create Thumbnail For Display
            '( Just In Case Form Becomes Active )
            Dim NewImage2 As Image = Image.FromFile(WallAutoReg)

            Dim DestSize2 As New Bitmap( _
            CInt(picPreview.Width), _
            CInt(picPreview.Height))

            Dim GenDest2 As Graphics = Graphics.FromImage(DestSize2)

            GenDest2.DrawImage(NewImage2, 0, 0, _
            DestSize2.Width + 1, _
            DestSize2.Height + 1)
            picPreview.Image = DestSize2
         End If
      End If
      'If Value Stored, Obtain & Store TimePeriod Value
      If Not (Application.UserAppDataRegistry.GetValue("TimePeriod") _
         Is Nothing) Then
            GenPeriodReg = _
               Application.UserAppDataRegistry.GetValue( _
               "TimePeriod").ToString()
      End If
      'If Value Stored, Obtain & Store Duration Value
      If Not (Application.UserAppDataRegistry.GetValue("Duration") _
         Is Nothing) Then
         GenDurReg = _
            Application.UserAppDataRegistry.GetValue( _
               "Duration").ToString()
      End If
      'If Value Stored, Obtain & Store Date Value
      If Not (Application.UserAppDataRegistry.GetValue("Date") _
         Is Nothing) Then
         DateReg = _
            Application.UserAppDataRegistry.GetValue( _
               "Date").ToString()
      End If
      'If Value Stored, Obtain & Store NodeTag Value
      If Not (Application.UserAppDataRegistry.GetValue("NodeTag") _
      Is Nothing) Then
         TreeTagStr = _
            Application.UserAppDataRegistry.GetValue("NodeTag")
         Dim TreeSelNode As New TreeNode(TreeTagStr)
         Dim TreeN As TreeNode
         Dim TreeSubN As TreeNode
         For Each TreeN In trGenie.Nodes
            For Each TreeSubN In TreeN.Nodes
               If TreeSubN.Text = TreeTagStr Then
                  'Expand Current Displayed Item In TreeView
                  TreeN.Expand()
                  'Select Current Displayed Item In TreeView
                  trGenie.SelectedNode = TreeSubN
               End If
            Next
         Next

         End If

      Catch ex As Exception
      MsgBox(ex.Message(), MsgBoxStyle.Exclamation)
      End Try

End Sub

[RegistrySettings.png]

Figure 2

The GenDWMCalc sub determines whether the current date is bigger than the stored date (DateReg). If the date stored in the Registry is smaller than the current date, it checks what time period is stored in the Registry (Days, Weeks, or Months). Based on this information, it calls the RandomAllGenie sub to randomize the pictures, and then ultimately applies the new wallpaper if necessary. If the period and date in the Registry are still in play, it doesn't apply anything:

Private Sub GenDWMCalc()                'Check If Duration Expired
   Try
      Dim DateGen As Date
      DateGen = CType(DateReg, Date)    'Date From Registry

      Select Case GenPeriodReg
         Case "Day(s)"      'Day(s)
            If DateDiff(DateInterval.Day, DateGen, Now) >= GenDurReg _
               Then         'If Today's Date > Than Registry Date
               RandomAllGenie()        'Randomise
            End If
         Case "Week(s)"     'Week(s)
            If DateDiff(DateInterval.Day, DateGen, Now) >= _
               (GenDurReg * 7) Then    '* 7 For Week
               RandomAllGenie()
            End If
         Case "Month(s)"    'Month(s)
            If DateDiff(DateInterval.Month, DateGen, Now) >= _
               GenDurReg Then
               RandomAllGenie()
            End If
      End Select

   Catch eg As Exception
      Exit Sub
   End Try
End Sub

The RandomAllGenie sub, as the name implies, randomises the pictures. You have loaded the picture locations into the listbox, and this makes it a tad easier to randomise these items. Whatever the random generator lands on gets stored and applied. Just a note here, this is probably not the most fantastic way of randomising items, but it still works; another noteworthy mention is the fact that, if you have very very few images in your collection, you may get duplicate results; meaning the wallpaper may be applied more often than if you have a lot of wallpapers in your collection. My collection stands just over 1600 wallpapers, so the chances of me getting the same wallpaper two days in a row are very very slim.

Private Sub RandomAllGenie()    'Randomize Pictures
   Dim RandGen As New Random    'Create New Random Object

   'Generate Random Number
   Dim RandNum As Integer = RandGen.Next(1, (NumFiles + 1))

   'Select Random Picture In Invisible ListBox
   lstFound.SetSelected(RandNum - 1, True)
   GenStr = lstFound.Text       'Obtain Picture Name


   picRealGenie.Image = Image.FromFile(GenStr)    'Set Image

   picPreview.Image = picRealGenie.Image          'Set Preview Image

   'Display Path In Label
   lblCurrent.Text = GenStr

   'Store Random Selection
   Application.UserAppDataRegistry.SetValue("WallAuto", GenStr)

   Application.UserAppDataRegistry.SetValue("Date", _
      lblDate.Text)    'Store Date

   ApplyGenie()        'Apply
End Sub

The ApplyGenie sub is where the real applying happens. The main drawback of the SystemParametersInfo API is the fact that it only seems to be able to apply .bmp files as wallpapers. This means that you must save the current selected (randomly/manually) wallpaper as a .bmp file, and then apply that saved image as the wallpaper. Now, another problem you are dealing with is the thumbnailing of the pictures. Making a thumbnail of the picture obviously reduces its size, meaning you need to find a way to save the picture in its original dimensions, so that when it gets applied as the wallpaper it hasn't shrunk in size. This is where the invisible picturebox (picRealGenie) gets used. If you can remember, you have two pictureboxes. One is for the preview of the pictures in a thumbnail view (picPreview). The other picturebox is used for saving (picRealgenie). Every time you load a picture into picPreview, you load the picture into the invisible picRealGenie as well, making saving the pictures easier. Figure 3 shows your saved bitmap named CurrentWall.bmp.

Private Sub ApplyGenie()

   'Generic Path And Name For The Image In The Picturebox To Save to
   Dim ImagePath As String = _
      Application.StartupPath & "\CurrentWall.bmp"

   'Image Must Be In Bitmap Format For It To Work With
   'SystemParametersInfo
   picRealGenie.Image.Save(ImagePath, ImageFormat.Bmp)    'Save

   'Set Parameters To Change The Wallpaper & To Update The
   'Windows Setting
   SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ImagePath, _
SPIF_SENDWININICHANGE Or SPIF_UPDATEINIFILE)
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ImagePath, _
SPIF_SENDWININICHANGE Or SPIF_UPDATEINIFILE)

   'Open Wallpaper Registry key
   key = key.OpenSubKey("Desktop", True)
   'Save New Wallpaper Location
   key.SetValue("Wallpaper", ImagePath)

   If AutoGenieReg = "Automatic" Then    'If Automatic

      'Just Save New Wallpaper
      Application.UserAppDataRegistry.SetValue("WallPaperName", _
                                               ImagePath)

      'Save New date
      Application.UserAppDataRegistry.SetValue("Date", lblDate.Text)

   Else    'If Manual
      Application.UserAppDataRegistry.SetValue("WallPaperName", _
                                               SelGenie) '
   End If

    GenieStyle()    'Apply Wallpaper Styles
End Sub

[CurrentWall.png]

Figure 3

Wallpaper Changer

The GenieStyle sub decides how the wallpaper should be applied. Is the wallpaper Tiled, Centered, or Stretched? It determines this by evaluating the Registry key where Windows stores this information.

'Gets & Sets Value In The HKEY_CURRENT_USER\Control Panel\Desktop
'Key In The Registry
Private Sub GenieStyle()
   'Open The Key
   Dim WallStyleReg As Microsoft.Win32.RegistryKey = _
      Microsoft.Win32.Registry.CurrentUser. _
      OpenSubKey("Control Panel").OpenSubKey("Desktop", True)

   Select Case WPStyle    'What Style Was Chosen?
      Case 1    'Tile
         WallStyleReg.SetValue("TileWallpaper", "1")
         WallStyleReg.SetValue("WallpaperStyle", "0")

      Case 2    'Center
         WallStyleReg.SetValue("TileWallpaper", "0")
         WallStyleReg.SetValue("WallpaperStyle", "0")

      Case 3    'Stretch
         WallStyleReg.SetValue("TileWallpaper", "0")
         WallStyleReg.SetValue("WallpaperStyle", "2")
   End Select
End Sub

Every time this application starts, you need to determine in which mode you are in. In other words, are you in Automatic mode where everything happens behind the scenes, or are you in Manual mode, where you have to select the new wallpaper and styles manually? Irrespective of which mode you are in, you still need to load your Treeview, just in case the form gets displayed. In Form_Load, you also must load the values from the Registry. How else will you determine the settings? Form_Load looks like the following code segment:

Private Sub frmGenie_Load(ByVal sender As Object, _
   ByVal e As System.EventArgs) Handles MyBase.Load
   lblDate.Text = DateTime.Today    'Today's Date
   Xit = True

   TreeGenie()    'Call The Sub That Fills The Treeview
   LoadReg()      'Call The Sub That Loads The Registry Values

   If AutoGenieReg = "Automatic" Then
     'Calculate If Wallpaper Should Be Changed Or Not
      GenDWMCalc()
      Me.WindowState = System.Windows.Forms.FormWindowState.Minimized
      'Enable Settings Menu Item (Only Available In Automatic Mode)
      mnuSettings.Enabled = True
   Else    'If Manual
      'Show The Form
      Me.WindowState = System.Windows.Forms.FormWindowState.Normal
      'Disable Settings Menu Item, Because The Form Is Already
      'Displayed With Manual Mode
      mnuSettings.Enabled = False
   End If

   Me.Cursor = Cursors.Hand    'Change Cursor

End Sub

Whenever a selection is made in a Treeview, you can use the AfterSelect event to obtain the selection and continue program flow. What I've done in the trGenie_AfterSelect event is mainly to set the both your pictureboxes' pictures, and set the Tree boolean flag to True (because a selection was made), and to set the AppSettingsChanged boolean variable to True as well:

Private Sub trGenie_AfterSelect(ByVal sender As Object, _
   ByVal e As System.Windows.Forms.TreeViewEventArgs) _
   Handles trGenie.AfterSelect

   Try
      SelGenie = trGenie.SelectedNode.FullPath
      If SelGenie.IndexOf(".") > 0 Then

         'Show Picture
         picPreview.Image = Image.FromFile(DirName & "\" & SelGenie)
         'Show Picture In Hidden PictureBox
         picRealGenie.Image = Image.FromFile(DirName & "\" & SelGenie)

         CreateThumbGenie()           'Thumbnail The Picture
         AppSettingsChanged = True    'Settings Have Changed
      Else
         picPreview.Text = "Nothing Selected"
      End If
      Tree = True    'We Have Selected Something From The Treeview
   Catch eg As Exception
      MsgBox(eg.ToString())
   End Try
End Sub

The CreateThumbGenie sub, as its name implies, is the sub you use to create a thumbnail representation of the currently selected picture. In here, you create a new Bitmap object with a smaller size (which is the size of the picPreview Picturebox), and then display the picture, with the new size, into picPreview. This basically causes the big picture to be shrunk to "fit" into the picPreview pictureBox.

Private Sub CreateThumbGenie()    'Create Thumbnail Picture
    'Selected Image In Treeview
   Dim NewImage As Image = Image.FromFile(DirName & "\" & SelGenie)

   ' Make Bitmap For The Result
   Dim DestSize As New Bitmap( _
      CInt(picPreview.Width), _
      CInt(picPreview.Height))

   ' Make A Graphics Object For The Result Bitmap
   Dim GenDest As Graphics = Graphics.FromImage(DestSize)

   ' Copy Source Image Into Destination Bitmap
   GenDest.DrawImage(NewImage, 0, 0, _
   DestSize.Width + 1, _
   DestSize.Height + 1)

   ' Display The Result
   picPreview.Image = DestSize

End Sub

With the following three events, you are setting the wallpaper styles. This later gets applied by the GenieStyle sub.

Private Sub rdTile_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdTile.Click
   WPStyle = 1    'Tile
   AppSettingsChanged = True
End Sub

Private Sub rdCenter_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdCenter.Click
   WPStyle = 2    'Center
   AppSettingsChanged = True

End Sub

Private Sub rdStretch_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdStretch.Click
   WPStyle = 3    'Stretch
   AppSettingsChanged = True

End Sub

Setting the Mode (Manual/Automatic) in the following two event procedures happens by saving which mode you have selected into the Registry:

Private Sub rdAuto_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdAuto.Click
   rdAuto.Checked = True        'Auto Is Clicked

   AppSettingsChanged = True    'Settings Have Changed
   AutoGenie = rdAuto.Text      'AutoGenie = "Automatic"

   'Store Today's Date
   Application.UserAppDataRegistry.SetValue("Date", lblDate.Text)

   'Store "Automatic" In Registry
   Application.UserAppDataRegistry.SetValue("Mode", "Automatic")

   'Enable Settings Menu Item (Only Available In Automatic Mode)
   mnuSettings.Enabled = True
End Sub

Private Sub rdManual_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdManual.Click
   rdManual.Checked = True      'Manual Is Selected

   AppSettingsChanged = True    'Settings Have Changed
   AutoGenie = rdManual.Text    'AutoGenie = "Manual"
   'Store "Manual" In Registry
   Application.UserAppDataRegistry.SetValue("Mode", "Manual")

   'Disable Settings Menu Item, Because The Form Is Already
   'Displayed With Manual Mode
   mnuSettings.Enabled = False
End Sub

If you have selected Automatic as the mode you want Wallpaper Genie to function in, you need to provide more information. You need to provide is the period (Days, Weeks, or Months) and how often you want different wallpapers. For example, setting the period to Day, and setting the Frequency to 1 will cause the program to change the wallpaper on a daily basis. If you set the mode to weeks, it will change the wallpaper once a week; it's the same with Months—once a month. With the following procedures, you are setting the Automatic Mode Options:

Private Sub rdWeek_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdWeek.Click
   rdWeek.Checked = True        'The Week(s) RadioButton Is Selected

   GenPeriod = rdWeek.Text      'GenPeriod = "Week(s)
   AppSettingsChanged = True    'Settings Have Changed
End Sub

Private Sub rdDay_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdDay.Click
   rdDay.Checked = True         'The Day(s) RadioButton Is Selected

   GenPeriod = rdDay.Text       'GenPeriod = "Day(s)"
   AppSettingsChanged = True    'Settings Have Changed

End Sub

Private Sub rdMonth_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles rdMonth.Click
   rdMonth.Checked = True       'The Month(s) RadioButton Is Selected

   GenPeriod = rdMonth.Text     'GenPeriod = "Month(s)"
   AppSettingsChanged = True    'Settinsg Have Changed

End Sub

Private Sub txtFreq_LostFocus(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles txtFreq.Leave
   If IsNumeric(txtFreq.Text) Then    'If Number Entered
      'GenDur = Whatever Entered Into txtFreq
      GenDur = txtFreq.Text.ToString
      AppSettingsChanged = True       'Settings Have Changed

   Else 'Not Numeric Data Entered
      'Warning To Enter Numeric Values ONLY
      MsgBox("ONLY Number Values Allowed!", _
         MsgBoxStyle.Information, "WallPaper Genie")
      txtFreq.Text = ""         'Clear The Text Entered
      txtFreq.Focus()           'Set the Focus Back To The Textbox
   End If

End Sub

Here, you apply all your settings. cmdApply_Click:

Private Sub cmdApply_Click(ByVal sender As Object, _
   ByVal e As System.EventArgs) Handles cmdApply.Click
   ApplyGen = True          'We Have Clicked Apply
   ApplyGenie()             'Apply The WallPaper & Set Style
   SaveReg()                'Save Everything To Registry
   cmdEnd.Enabled = True    'We Can Exit Now
End Sub

Wallpaper Changer

The SaveReg sub saves all your settings into the Registry at HKEY_CURRENT_USER\Software\Wallpaper_Genie, BUT it also makes 100% sure that all the necessary details have been filled in & selected. You can achieve these tests just by creating a few Boolean variables, and set them to True/False accordingly. Figure 4 shows the details that have been saved:

Private Sub SaveReg()    'Save To Registry
   Dim WP As Boolean     'WallPaper
   Dim GP As Boolean     'Period
   Dim GD As Boolean     'Duration
   Dim AG As Boolean     'Mode

   If AppSettingsChanged Then    'Settings Have Changed
      Try
         If ApplyGen = True Then      'Are We Applying?
            If SelGenie <> "" Then    'If Picture Selected
               Application.UserAppDataRegistry.SetValue("WallPaperName", _
                  SelGenie)

               WP = True    'Wallpaper Settings Are Fine, Continue
            Else 'Wallpaper Not Set
               MsgBox("You Must Select A Wallpaper!", _
                      MsgBoxStyle.Information)

                  WP = False
            End If
         End If

         If GenPeriod <>"" Then    'Is Period Selected?
            Application.UserAppDataRegistry.SetValue("TimePeriod", _
               GenPeriod)

            GP = True    'It Is, Continue
         Else 'No Period Selected
            MsgBox("You Must Select A Time Period!, " & vbCrLf _
            & "(Day(s), Week(s) Or Month(s))", MsgBoxStyle.Information)

            GP = False
         End If

         If GenDur <> "" Then    'Is Duration Entered?
            Application.UserAppDataRegistry.SetValue("Duration", _
               GenDur)

            GD = True    'It IS, Continue
         Else 'No Duration Entered
            MsgBox("You Must Fill in the Frequency (Duration)!", _
                   MsgBoxStyle.Information)

            GD = False
         End If

         If AutoGenie <> "" Then    'Is Mode Selected?
            Application.UserAppDataRegistry.SetValue("Mode", _
               AutoGenie)

            Application.UserAppDataRegistry.SetValue("WallAuto", _
               DirName & "\" & SelGenie)

            AG = True 'Mode Is Selected
         Else 'No Mode Was Selected
            MsgBox("You Must Select A Mode" & vbCrLf _
               & "(Automatic or Manual)!", MsgBoxStyle.Information)

            AG = False
         End If

         'Store Treeview Image Path
         If Tree Then Application.UserAppDataRegistry.SetValue("NodeTag", _
            trGenie.SelectedNode.Tag)

         'If Everything Is OK, Then We Can Exit
         If WP = True And GP = True And GD = True And AG = True Then
            Xit = True     'We Can Exit
         Else
            Xit = False    'We Cannot Exit
         End If

        Catch ex As Exception

         MsgBox(ex.Message.ToString())    'Just In case :)
      End Try
   End If
End Sub

[RegistrySettings.png]

Figure 4

The cmdCancel_Click event just minimises the form:

Private Sub cmdCancel_Click(ByVal sender As Object, _
   ByVal e As System.EventArgs) Handles cmdCancel.Click
   ApplyGen = False    ' Do Not Apply WallPaper
   Me.WindowState = FormWindowState.Minimized    'Minimise Form
End Sub

[NotifyIcon.png]

Figure 5

mnuSettings_Click shows the form from your NotifyIcon, as depicted in Figure 5:

Private Sub mnuSettings_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles mnuSettings.Click
   Me.Visible = True    'Show Form, Normally
   Me.WindowState = System.Windows.Forms.FormWindowState.Normal

End Sub

If all settings are correct, it is safe to exit the application in the cmdEnd_Click event:

Private Sub cmdEnd_Click(ByVal sender As Object, _
   ByVal e As System.EventArgs) Handles cmdEnd.Click
    If Xit = True Then    'If All Settings Correct
        Me.Close()        'Exit
    Else
        Exit Sub          'Else, Don't Exit
    End If
End Sub

mnuExit_Click:

Private Sub mnuExit_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles mnuExit.Click
   Application.Exit() 'Exit
End Sub

Running Your Application

When you run your application for the very first time, it should List one sub folder in the Treeview. This folder appears because of the Startup directory you have set for your application:

'Location Of Pictures
'You Could Have Any Path Here, For Example : "C:\WallPapers"
Private DirName As String = Application.StartupPath

Yes, it is probably a bad practise to hardcode certain things into a program (in this case DirName). It would have worked much better if you had included a FolderBrowserDialog. In my personal case, my wallpapers are stored at one place, and it will never change; that is the whole reasoning behind hardcoding the DirName's path. As stated earlier, when the application is run, it shows the Sample Wallpapers folder inside the Treeview. If you were to open this program's Bin folder, you will find the Sample Wallpapers in there. Inside Sample Wallpapers, I've included four wallpapers. If you were to expand Sample Wallpapers in the Treeview, you would see these wallpapers. These are sample wallpapers for you to work with, and see how the program functions before you customise it to suit your own needs. You can replace these wallpapers with your own (if you don't like my taste in music/women), and you don't have a limit as to how many pictures and folders are present in the main directory. You will also be able to set any mode, and set any style—everything I have described throughout this article when running this application.

I've found the best way to make this program do its funky stuff is to add a Shortcut (to the .exe file, in the Bin folder), to your Start Menu's Startup item. After the first run, the next time the computer starts up, Wallpaper Genie starts up in either Automatic mode (where it applies everything automatically, based on the timeframe), or in Manual mode, where you can choose the wallpaper & styles Manually (also based on the timeframe specified).

When I run my own wallpaper genie, on my home computer, I get a screen as shown in Figure 6.

[RunTime.jpg]

Figure 6

Conclusion

Well, that's all there is to it! You now have the fundamentals and whole logic behind creating wallpaper changing applications. I sincerely hope you have enjoyed reading this article, and learnt something useful from it.



About the Author

Hannes du Preez

Hannes du Preez is a Microsoft MVP for Visual Basic. He is a trainer at a South African-based company. He is the co-founder of hmsmp.co.za, a community for South African developers.

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds