Platform Invoke Sample - Changing the Desktop Wallpaper

In this example we will see how to change the Desktop wallpaper by invoking a Windows API function from C#. The Platform Invoke mechanism allows you to access unmanaged functions implemented in dlls. You can invoke Windows API functions using Platform Invoke. This functionality is provided under the System.Runtime.InteropServices namespace. We will add a reference to that namespace in our code. 

The first step to start using Platform Invoke is to identify the dll which contains your functions. The most commonly used Windows APIs are available in the following dlls. User32.dll, GDI32.dll and Kernel32.dll.

The Windows API function to change the Desktop Wallpaper is available in user32.dll.

To conveniently invoke the Win API function, the dll functionality that we would need to invoke from managed code is wrapped in a class as shown below. 

Public class WinAPI
{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SystemParametersInfo (int uAction , int uParam , string lpvParam , int fuWinIni) ;
}

Code : Prototype class for accessing the unmanaged Windows API function. 

Note that you have to convert the types appropriately in the class definition. In the class defined above, we have provided the managed definition for an unmanaged function which is available in a Windows DLL. 

Now we can access the prototyped Windows API function from our managed code. We will design the user interface for allowing the user to select the image that should be set as the WallPaper.  

ChangeDtWp1.gif

Figure : Windows Form Layout 

Control Control name
TextBox textBox1
Button button1
Button button2
OpenFileDialog openFileDialog1

Now we will add the code to allow the user to select the Image File to be selected using the OpenFileDialog when the selection button is clicked. 

private void button1_Click(object sender, System.EventArgs e)
{
openFileDialog1.InitialDirectory = @"C:\winnt";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
textBox1.Text = openFileDialog1.FileName;
}
}

Code : Allow the user to select the new wallpaper file. 

We have not set any filter on the file dialog. You can modify the sample to add that functionality. 

private void button2_Click(object sender, System.EventArgs e)
{
int nResult ;
if (File.Exists(textBox1.Text))
{
nResult = AC.SystemParametersInfo(20, 0, textBox1.Text, 0x1 | 0x2 );
MessageBox.Show("Wallpaper has been changed");
}
}

Code : Modify the wallpaper. 

Complete Code Listing
  

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
namespace WallPaper
{
public class WinAPI
{
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SystemParametersInfo (int uAction , int uParam , string lpvParam , int fuWinIni) ;
}
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
public Form1()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.SuspendLayout();
this.textBox1.Location = new System.Drawing.Point(16, 16);
this.textBox1.Name = "textBox1";
this.textBox1.TabIndex = 0;
this.textBox1.Text = "";
this.button1.Location = new System.Drawing.Point(120, 16);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(24, 23);
this.button1.TabIndex = 1;
this.button1.Text = "...";
this.button1.Click += new System.EventHandler(this.button1_Click);
this.button2.Location = new System.Drawing.Point(16, 48);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(128, 23);
this.button2.TabIndex = 2;
this.button2.Text = "Change Wallpaper";
this.button2.Click += new System.EventHandler(this.button2_Click);
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(232, 93);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.button2,
this.button1,
this.textBox1});
this.Name = "Form1";
this.Text = "Change Desktop Wallpaper";
this.ResumeLayout(false);
}
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
[STAThread]
static void Main()
{
Application.Run(
new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
//change the initial directory if required.
openFileDialog1.InitialDirectory = @"C:\winnt";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
textBox1.Text = openFileDialog1.FileName;
}
}
private void button2_Click(object sender, System.EventArgs e)
{
int nResult ;
if (File.Exists(textBox1.Text))
{
nResult = WinAPI.SystemParametersInfo(20, 0, textBox1.Text, 0x1 | 0x2 );
MessageBox.Show("Wallpaper has been changed");
}
}
}


NOTE:  This article is purely for demonstration. This article should not be construed as a best practices white paper. This article is entirely original, unless specified. Any resemblance to other material is an un-intentional coincidence and should not be misconstrued as malicious, slanderous, or any anything else hereof. 

Conclusion

In this example we learnt how to invoke Windows API functions using Platform Invoke. Many of the Windows API functions have corresponding implementation in the .Net framework namespaces and it is recommended to use the managed functions wherever possible.