Introduction
I have always been curious; curiosity might one day be the end of me…. Today, I will cover a fun and exciting topic that is also a tad complicated. Today, you will learn how to change your screen’s wallpaper, screensaver, and its settings as well as change your screen’s resolution. We have a lot of work, so let’s get started.
Design
Start Visual Basic and create a new Windows Forms Project. Design your form to resemble Figure 1.

Figure 1: Our Busy design
Code
Add the required namespaces to your project:
Imports System.Runtime.InteropServices
Imports System.IO 'Import System.IO For File Operations
Imports Microsoft.Win32
The first Namespace enables us to properly work with APIs. If you do not know what APIs are, I suggest you read the following articles:
System.IO enables us to properly work with Files; here is more information on files:
The last Namespace, Micorsoft.Win32, enables you to work with your system, such as the Registry. Seeing the fact that all of these screen settings are stored in and read from the Registry, I suggest that you read up on the Registry here:
Add the following fields to your project:
Dim ChangeRes As Resolution.CResolution
Private FixHeight As Integer '= 1024 'default height
Private FixWidth As Integer '= 768 'default width
Dim XRes As Short
Dim YRes As Short
Dim DidResChange As Boolean
Private DirName As String = "C:\WINDOWS\system32\"
Private StyleDir As String = "C:\WINDOWS\Resources\Themes"
Private StyleColorDir As String
Private ScreenNames() As String
Private StyleNames() As String
Private StyleFont As String
Private StyleColor As String
Private StyleDisplayName As String
The first few variables deal with the screen resolution settings; for example, the width of the screen as well as the height of the screen. The next few variables will be used with changing of the visual Styles of your screen. I will go into greater detail as this article progresses.
Add the following APIs and their associated System Constants to your project:
Declare Function IsThemeActive Lib "UxTheme.dll" _
() As Boolean
Declare Function EnableTheming Lib "UxTheme.dll" _
(ByVal b As Boolean) As Long
Declare Function IsAppThemed Lib "UxTheme.dll" _
() As Boolean
Private mouse_offset As Point
<DllImport("UxTheme.DLL", BestFitMapping:=False, _
CallingConvention:=CallingConvention.Winapi, _
CharSet:=CharSet.Unicode, EntryPoint:="#65")> _
Shared Function SetSystemVisualStyle(ByVal _
pszFilename As String, _
ByVal pszColor As String, ByVal pszSize As String, _
ByVal dwReserved As Integer) As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function SendMessage(ByVal hwnd As Int32, _
ByVal wMsg As Int32, ByVal wParam As Int32, _
ByVal lParam As Int32) As Int32
End Function
<DllImport("user32", EntryPoint:="SystemParametersInfo", _
CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function SystemParametersInfo(ByVal uAction As Integer, _
ByVal uParam As Integer, ByVal lpvParam As String, _
ByVal fuWinIni As Integer) As Integer
End Function 'API Used for System Settings
Private Const SPI_SETDESKWALLPAPER = 20 'Set WallPaper
Private Const SPIF_UPDATEINIFILE = &H1 'Update The INI File
Private Const WM_SYSCOMMAND As Integer = &H112
Private Const SC_SCREENSAVE As Integer = &HF140
Private key As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Control Panel", True)
IsThemeActive determines whether of not a theme is currently present on your display settings. EnableTheming enables theming capabilities on your screen. IsAppThemed determines whether or not a specific application is allowed to associate itself with a system theme.
SetSystemVisualStyle physically sets the Visual Style you may have selected. SendMessage sends a system message. Read this article to get more information regarding the SendMessage API:
SystemParametersInfo is responsible for system settings. Here is more information regarding this API:
The constants all make these APIs work. Later on, you will see how they are implemented.
Changing the Wallpaper
Double-click the Button labeled ‘Change Wallpaper’ and add the following code behind it:
Private Sub btnWall_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnWall.Click
Dim ImagePath As String = Application.StartupPath & _
"\CurrentWall.bmp"
'Set Parameters To Change The Wallpaper & To Update
'The Windows Setting
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ImagePath, _
SPIF_UPDATEINIFILE)
'Open Wallpaper Registry key
key = key.OpenSubKey("Desktop", True)
'Save New Wallpaper Location
key.SetValue("Wallpaper", ImagePath)
End Sub
As easy as that! First, we determine where our picture that we want to set as the wallpaper is, then we use the SystemParametersInfo API to physically set the wallpaper. Now, this change is not really permanent. If you were to run your app now, you will see the wallpaper change, but tomorrow when you switch on your computer, your old screensaver will appear again. You have to save the associated information in the registry as well; that is what the last two lines of code do. They basically set the Desktop\Wallpaper setting to your specified Image source.
Getting Screen Resolution
Add the following code behind the ‘Get Screen Resolution‘ button:
Private Sub btnGetRes_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnGetRes.Click
'CHECK SCREEN RESOLUTION
XRes = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
YRes = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
MessageBox.Show("Horizontal Resolution = " & XRes.ToString() _
& Environment.NewLine & "Vertical Resolution = " _
& YRes.ToString)
End Sub
No need for APIs here; the Screen object in the .NET Framework contains the capability to determine this. Here, we simply get the X and Y resolution settings and display them inside a picture box.

Figure 2: Current Screen resolution
Changing the Screen Resolution
Before we can change the screen’s resolution, we have to determine what option has been selected inside the Listbox named lstResolution, (Note: Your objects’ names might differ from mine.) Add the following code inside the lstResolution_SelectedIndexChanged event:
Private Sub lstResolution_SelectedIndexChanged(ByVal sender _
As System.Object, ByVal e As System.EventArgs) _
Handles lstResolution.SelectedIndexChanged
Dim ListSel As Integer
If lstResolution.SelectedIndex > -1 Then
ListSel = lstResolution.SelectedIndex
End If
Select Case ListSel
Case 0 '640 x 480
FixWidth = 640
FixHeight = 480
Case 1 '800 x 600
FixWidth = 800
FixHeight = 600
Case 2
FixWidth = 832
FixHeight = 624
Case 3 '1024 x 768
FixWidth = 1024
FixHeight = 768
Case 4 '1152 x 864
FixWidth = 1152
FixHeight = 864
Case 5 '1280 x 600
FixWidth = 1280
FixHeight = 600
Case 6
FixWidth = 1280
FixHeight = 720
Case 7
FixWidth = 1280
FixHeight = 768
Case 8
FixWidth = 1280
FixHeight = 960
Case 9
FixWidth = 1280
FixHeight = 1024
End Select
End Sub
What you do here is simply determine which option has been selected and set the appropriate objects to the selected Height and Width values. Now, add the following code behind the ‘Change Resolution‘ button:
Private Sub btnChangeRes_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnChangeRes.Click
'CHECK SCREEN RESOLUTION
XRes = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width
YRes = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height
If XRes <> 1024 And YRes <> 768 Then
'Me.WindowState = System.Windows.Forms.FormWindowState.Minimized
ChangeRes = New Resolution.CResolution(FixWidth, FixHeight)
'Me.WindowState = System.Windows.Forms.FormWindowState.Maximized
DidResChange = True
End If
End Sub
Again, we do a check on the current resolution. If it isn’t 1024 x 768, call the CResolution class inside the Resolution class, which looks like this:
Imports System
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Public Class Resolution
<StructLayout(LayoutKind.Sequential)> _
Public Structure DEVMODE1
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=32)> _
Public dmDeviceName As String
Public dmSpecVersion As Short
Public dmDriverVersion As Short
Public dmSize As Short
Public dmDriverExtra As Short
Public dmFields As Integer
Public dmOrientation As Short
Public dmPaperSize As Short
Public dmPaperLength As Short
Public dmPaperWidth As Short
Public dmScale As Short
Public dmCopies As Short
Public dmDefaultSource As Short
Public dmPrintQuality As Short
Public dmColor As Short
Public dmDuplex As Short
Public dmYResolution As Short
Public dmTTOption As Short
Public dmCollate As Short
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=32)> _
Public dmFormName As String
Public dmLogPixels As Short
Public dmBitsPerPel As Short
Public dmPelsWidth As Integer
Public dmPelsHeight As Integer
Public dmDisplayFlags As Integer
Public dmDisplayFrequency As Integer
Public dmICMMethod As Integer
Public dmICMIntent As Integer
Public dmMediaType As Integer
Public dmDitherType As Integer
Public dmReserved1 As Integer
Public dmReserved2 As Integer
Public dmPanningWidth As Integer
Public dmPanningHeight As Integer
End Structure
Class User_32
<DllImport("user32.dll")> _
Public Shared Function EnumDisplaySettings(ByVal _
deviceName As String, ByVal modeNum As Integer, _
ByRef devMode As DEVMODE1) As Integer
End Function
<DllImport("user32.dll")> _
Public Shared Function ChangeDisplaySettings(ByRef _
devMode As DEVMODE1, _
ByVal flags As Integer) As Integer
End Function
Public Const ENUM_CURRENT_SETTINGS As Integer = -1
Public Const CDS_UPDATEREGISTRY As Integer = 1
Public Const CDS_TEST As Integer = 2
Public Const DISP_CHANGE_SUCCESSFUL As Integer = 0
Public Const DISP_CHANGE_RESTART As Integer = 1
Public Const DISP_CHANGE_FAILED As Integer = -1
End Class
Class CResolution
Public Sub New(ByVal a As Integer, ByVal b As Integer)
Dim screen As Screen = screen.PrimaryScreen
Dim iWidth As Integer = a
Dim iHeight As Integer = b
Dim dm As DEVMODE1 = New DEVMODE1
dm.dmDeviceName = New String(New Char(32) {})
dm.dmFormName = New String(New Char(32) {})
dm.dmSize = CType(Marshal.SizeOf(dm), Short)
If Not (0 = User_32.EnumDisplaySettings(Nothing, _
User_32.ENUM_CURRENT_SETTINGS, dm)) Then
dm.dmPelsWidth = iWidth
dm.dmPelsHeight = iHeight
Dim iRet As Integer = User_32.ChangeDisplaySettings(dm, _
User_32.CDS_TEST)
If iRet = User_32.DISP_CHANGE_FAILED Then
MessageBox.Show("Unable to process _
your request")
MessageBox.Show("Description: Unable To Process _
Your Request. Sorry For This Inconvenience.", _
"Information", MessageBoxButtons.OK, _
MessageBoxIcon.Information)
Else
iRet = User_32.ChangeDisplaySettings(dm, _
User_32.CDS_UPDATEREGISTRY)
Select Case iRet
Case User_32.DISP_CHANGE_SUCCESSFUL
' break
Case User_32.DISP_CHANGE_RESTART
MessageBox.Show("Description: You Need To _
Reboot For The Change To Happen." & _
Microsoft.VisualBasic.Chr(10) & _
" If You Feel Any Problem After Rebooting _
Your Machine" & Microsoft.VisualBasic.Chr(10) _
& "Then Try To Change Resolution _
In Safe Mode.", _
"Information", MessageBoxButtons.OK, _
MessageBoxIcon.Information)
' break
Case Else
MessageBox.Show("Description: Failed To Change The _
Resolution.", "Information", _
MessageBoxButtons.OK, MessageBoxIcon.Information)
' break
End Select
End If
End If
End Sub
End Class
End Class
Here is more information regarding the DEVMODE1 structure:
More information on EnumDisplaySettings & ChangeDisplaySettings:
Changing Visual Styles
Add the following subs to load all the Style Information into the associated Visual Style comboboxes:
Private Sub LoadStyles()
Dim FilePath As String 'File Path
Dim Xtension As String 'File Extensions
Dim FolderPath As String 'Folder Path
'Dim DisplayName As String
Dim NumFiles As Integer
Dim TruncName As String
'Search Sub Folders In DirName
For Each FolderPath In _
Directory.GetDirectories(StyleDir, "*")
'Search Files Within Sub Folders
For Each FilePath In Directory.GetFiles(FolderPath)
'Identify File Extension
Xtension = IO.Path.GetExtension(FilePath)
If Xtension = ".msstyles" Then
TruncName = FilePath.Substring(FilePath.LastIndexOf _
("\") + 1)
' StyleColorDir = FilePath.Substring(0,
' FilePath.LastIndexOf("\"))
StyleDisplayName = TruncName.Substring(0, _
TruncName.LastIndexOf("."))
cboStyles.Items.Add(StyleDisplayName)
ReDim Preserve StyleNames(NumFiles)
StyleNames(NumFiles) = FilePath
NumFiles = NumFiles + 1 'Increment File Count
End If
Next
Next
End Sub
Private Sub LoadStyleColors()
Dim CurrentStyle As String
cboStyleColor.Items.Clear()
If cboStyles.SelectedIndex > -1 Then
CurrentStyle = cboStyles.SelectedItem.ToString()
StyleColorDir = StyleDir & "\" _
& CurrentStyle & "\Shell"
End If
Dim FolderPath As String 'Folder Path
Dim TruncName As String
'Search Sub Folders In DirName
For Each FolderPath In Directory.GetDirectories(StyleColorDir, _
"*")
TruncName = FolderPath.Substring(FolderPath.LastIndexOf("\") + 1)
cboStyleColor.Items.Add(TruncName)
Next
End Sub
Add the following events when an item has been selected in the associated Visual Styles comboboxes:
Private Sub cboStyleFonts_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cboStyleFonts.SelectedIndexChanged
'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager\SizeName
Dim i As Short
If cboStyleFonts.SelectedIndex > -1 Then i = cboStyleFonts.SelectedIndex
Select Case i
Case 0
StyleFont = "NormalSize"
Case 1
StyleFont = "LargeFonts"
Case 2
StyleFont = "ExtraLargeFonts"
End Select
End Sub
Private Sub cboStyleColor_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cboStyleColor.SelectedIndexChanged
'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager\ColorName
'For example, Homestead = Olive Green, Metallic = Silver etc.
'If not all settings are set for the theme ( Themename, color, font -
'it will show Theme name ( Modified ) in themes of display props
If cboStyleColor.SelectedIndex > -1 Then
StyleColor = cboStyleColor.SelectedItem.ToString()
End If
End Sub
Private Sub cboStyles_SelectedIndexChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles cboStyles.SelectedIndexChanged
'HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ThemeManager\DllName
LoadStyleColors()
End Sub
Finally, add the code to set the Visual Style with the selected settings:
Private Sub btnSetStyle_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnSetStyle.Click
' SetSystemVisualStyle("C:\WINDOWS\resources\Themes\Luna\Luna.msstyles",
' "Metallic", "NormalSize", 0)
SetSystemVisualStyle(StyleNames(cboStyles.SelectedIndex), _
StyleColor, StyleFont, 0)
End Sub
Starting the Default Screensaver
Add the following code to start the default screensaver:
Private Sub btnScreen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnDefScreen.Click
Dim result As Int32
result = SendMessage(Me.Handle.ToInt32, WM_SYSCOMMAND, _
SC_SCREENSAVE, 0)
End Sub
Here, you have to use the SendMessage API to send a system message to start the set screensaver.
Starting a Different Screensaver
Before we can start a screensaver that is not currently in use, we have to load all the installed screensavers into a listview. Do that now:
Private Sub LoadScreenSavers()
Dim FilePath As String 'File Path
Dim Xtension As String 'File Extensions
Dim NumFiles As Integer
Dim TruncName As String
'Search Files Within Sub Folders
For Each FilePath In Directory.GetFiles(DirName)
'Identify File Extension
Xtension = IO.Path.GetExtension(FilePath)
If Xtension = ".scr" Then
TruncName = FilePath.Substring(FilePath.LastIndexOf _
("\") + 1)
lvScreen.Items.Add(TruncName)
lvScreen.Items(NumFiles).SubItems.Add(FileVersionInfo._
GetVersionInfo(FilePath).FileDescription)
ReDim Preserve ScreenNames(NumFiles)
ScreenNames(NumFiles) = FilePath
NumFiles = NumFiles + 1 'Increment File Count
End If
Next
End Sub
This sub is responsible for loading all the files ending with the .scr extension into the listview, as shown in Figure 3:

Figure 3: Installed Screensavers
Now that we have a list of installed screensavers, let’s add the code to change the system’s screensaver to the one that we have selected inside the listview:
Private Sub btnDiffScreen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnDiffScreen.Click
Dim LVSel As Integer
If lvScreen.SelectedItems.Count > 0 Then
LVSel = lvScreen.SelectedIndices(0)
End If
Process.Start(ScreenNames(LVSel))
End Sub
Here, I simply made use of the Process object to start the selected screensaver.
Setting Screensaver Settings
Private Sub btnConfScreen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnConfScreen.Click
Dim LVSel As Integer
If lvScreen.SelectedItems.Count > 0 Then
LVSel = lvScreen.SelectedIndices(0)
End If
Dim ScreenProc As New Process
ScreenProc.StartInfo.FileName = ScreenNames(LVSel)
ScreenProc.StartInfo.Arguments = "/c"
ScreenProc.StartInfo.UseShellExecute = False
ScreenProc.Start()
End Sub
Again, I made use of the Process object, but here I sent the /c argument that allows you to configure the selected screensaver

Figure 4: Screensaver settings
Previewing a Screensaver
Private Sub btnPreviewScreen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnPreviewScreen.Click
Dim LVSel As Integer
If lvScreen.SelectedItems.Count > 0 Then
LVSel = lvScreen.SelectedIndices(0)
End If
Dim ScreenProc As Process
Dim psi As New ProcessStartInfo(ScreenNames(LVSel), _
"/p " & picPreviewScreen.Handle.ToString())
psi.UseShellExecute = False
ScreenProc = Process.Start(psi)
End Sub
Here, I sent the /p argument and the window into which the preview should display, in this case a picturebox:

Figure 5: Preview screensaver
Conclusion
I hope you have enjoyed today’s article on how to set the screen settings with Visual Basic. Until next time, cheers!