Set desktop wallpaper programmatically?

  • Thread starter Marcos Stefanakopolus
  • Start date
M

Marcos Stefanakopolus

Does anyone know if there is a .NET Framework solution for setting the
desktop wallpaper image?

If not, does anyone have any tips or "gotchas" for using the User32.dll
"SystemParametersInfo" function to do it? I found a sample application on
CodeProject that uses the User32 function, but when I borrow the call into
my application it doesn't work. Doesn't crash or throw any exceptions, it
just doesn't do anything. Can't figure out why.
 
M

Mattias Sjögren

Marcos,
Does anyone know if there is a .NET Framework solution for setting the
desktop wallpaper image?

There isn't.

If not, does anyone have any tips or "gotchas" for using the User32.dll
"SystemParametersInfo" function to do it? I found a sample application on
CodeProject that uses the User32 function, but when I borrow the call into
my application it doesn't work. Doesn't crash or throw any exceptions, it
just doesn't do anything. Can't figure out why.

We can't help you unless you post your code.



Mattias
 
M

Marcos Stefanakopolus

Does anyone know if there is a .NET Framework solution for setting the
There isn't.

Bummer. Well, I was hoping.
We can't help you unless you post your code.

Ok. Bear in mind, the interesting parts of this (the dll import line, the
SystemParametersInfo() call, the registry key business) are what I got from
that sample on CodeProject. I altered that code to take an ordinary
filesystem path as input (rather than a URI), and to add a "Zoomed" display
mode which scales an image file up/down to fit the desktop while maintaining
the original aspect ratio (that is, what you always wanted the "stretched"
mode to do, but doesn't).

The rest of my application calls Wallpaper.Set() at various times to attempt
to change the wallpaper. When I step through the code, everything happens
exactly like I expect it to (i.e. temp file gets created if necessary,
correct path gets passed to SystemParametersInfo, etc.), but after the call
to SystemParametersInfo(), the desktop image has not been changed. It has,
however, been un-set from its previous value in such a way that when windows
needs to re-paint portions of the desktop, it repaints them with the solid
desktop color rather than with image data.

=============
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using System.Data;
using Microsoft.Win32;
namespace DesktopSlideshow
{
/// <summary>
/// Class that encapsulates the functionality of putting an image file onto
the desktop.
/// </summary>
public sealed class Wallpaper
{
Wallpaper( ) { }
const int SPI_SETDESKWALLPAPER = 20;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int SystemParametersInfo (int uAction, int uParam, string
lpvParam, int fuWinIni);
public enum Style : int
{
Tiled,
Centered,
Stretched,
Zoomed
}
public static void Set ( string path, Style style )
{
// get registry key for the desktop image settings
RegistryKey key = Registry.CurrentUser.OpenSubKey( @"Control
Panel\Desktop", true ) ;
// Zoomed is not supported natively, so we create a new image file
that is sized to work
// with Centered instead:
if(style == Style.Zoomed)
{
Size DS = SystemInformation.PrimaryMonitorSize;
Point DestPoint;
Size DestSize;
using(Bitmap B = new Bitmap(path)) // temporarily load the
image
using(Bitmap tmp = new Bitmap(DS.Width, DS.Height)) // new
bitmap as big as the desktop
{
double ratio = Math.Min((double)DS.Width /
(double)B.Width,
(double)DS.Height / (double)B.Height);
// Only do the resizing if the image would need to scale
more than 1%. Otherwise,
// just use the file as is.
if(Math.Abs(ratio - 1.0) > 0.01)
{
DestSize = new Size((int)(ratio * (double)B.Width),
(int)(ratio * (double)B.Height));
DestPoint = new Point(Math.Max(0, (DS.Width -
DestSize.Width)/2),
Math.Max(0, (DS.Height - DestSize.Height)/2));
// create the bitmap:
using (Graphics G = Graphics.FromImage(tmp))
{
G.DrawImage(B, new Rectangle(DestPoint.X,
DestPoint.Y, // resize the input image into tmp.
DestSize.Width, DestSize.Height));
}
// save it:
string tempPath = Path.Combine(Path.GetTempPath(),
"wallpaper.png");
tmp.Save(tempPath,
System.Drawing.Imaging.ImageFormat.Png);
// remember where we put it:
path = tempPath;
}
}
// default back to the Centered style.
style = Style.Centered;
}
if ( style == Style.Stretched )
{
key.SetValue(@"WallpaperStyle", 2.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 0.ToString( ) ) ;
}
if ( style == Style.Centered )
{
key.SetValue(@"WallpaperStyle", 1.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 0.ToString( ) ) ;
}
if ( style == Style.Tiled )
{
key.SetValue(@"WallpaperStyle", 1.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 1.ToString( ) ) ;
}
SystemParametersInfo( SPI_SETDESKWALLPAPER,
0,
path,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
}
}
}
=============
 
M

Marcos Stefanakopolus

Nevermind. I figured it out.

The "gotcha" is that when you call SystemParametersInfo() to set the desktop
bitmap, you have to supply a path to a .bmp file. I was suckered into
thinking that you could use any image format because that's allowed when you
set the desktop bitmap via the control panel applet. However, the applet
converts your image to a .bmp file for you and uses that instead. All works
fine now.

--
I may not always have the best answers, but at least I'm not posting
questions in the wrong newsgroups...


Marcos Stefanakopolus said:
There isn't.

Bummer. Well, I was hoping.
We can't help you unless you post your code.

Ok. Bear in mind, the interesting parts of this (the dll import line, the
SystemParametersInfo() call, the registry key business) are what I got
from that sample on CodeProject. I altered that code to take an ordinary
filesystem path as input (rather than a URI), and to add a "Zoomed"
display mode which scales an image file up/down to fit the desktop while
maintaining the original aspect ratio (that is, what you always wanted the
"stretched" mode to do, but doesn't).

The rest of my application calls Wallpaper.Set() at various times to
attempt to change the wallpaper. When I step through the code, everything
happens exactly like I expect it to (i.e. temp file gets created if
necessary, correct path gets passed to SystemParametersInfo, etc.), but
after the call to SystemParametersInfo(), the desktop image has not been
changed. It has, however, been un-set from its previous value in such a
way that when windows needs to re-paint portions of the desktop, it
repaints them with the solid desktop color rather than with image data.

=============
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using System.Data;
using Microsoft.Win32;
namespace DesktopSlideshow
{
/// <summary>
/// Class that encapsulates the functionality of putting an image file
onto the desktop.
/// </summary>
public sealed class Wallpaper
{
Wallpaper( ) { }
const int SPI_SETDESKWALLPAPER = 20;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int SystemParametersInfo (int uAction, int uParam, string
lpvParam, int fuWinIni);
public enum Style : int
{
Tiled,
Centered,
Stretched,
Zoomed
}
public static void Set ( string path, Style style )
{
// get registry key for the desktop image settings
RegistryKey key = Registry.CurrentUser.OpenSubKey( @"Control
Panel\Desktop", true ) ;
// Zoomed is not supported natively, so we create a new image file
that is sized to work
// with Centered instead:
if(style == Style.Zoomed)
{
Size DS = SystemInformation.PrimaryMonitorSize;
Point DestPoint;
Size DestSize;
using(Bitmap B = new Bitmap(path)) // temporarily load the
image
using(Bitmap tmp = new Bitmap(DS.Width, DS.Height)) // new
bitmap as big as the desktop
{
double ratio = Math.Min((double)DS.Width /
(double)B.Width,
(double)DS.Height / (double)B.Height);
// Only do the resizing if the image would need to
scale more than 1%. Otherwise,
// just use the file as is.
if(Math.Abs(ratio - 1.0) > 0.01)
{
DestSize = new Size((int)(ratio * (double)B.Width),
(int)(ratio * (double)B.Height));
DestPoint = new Point(Math.Max(0, (DS.Width -
DestSize.Width)/2),
Math.Max(0, (DS.Height - DestSize.Height)/2));
// create the bitmap:
using (Graphics G = Graphics.FromImage(tmp))
{
G.DrawImage(B, new Rectangle(DestPoint.X,
DestPoint.Y, // resize the input image into tmp.
DestSize.Width, DestSize.Height));
}
// save it:
string tempPath = Path.Combine(Path.GetTempPath(),
"wallpaper.png");
tmp.Save(tempPath,
System.Drawing.Imaging.ImageFormat.Png);
// remember where we put it:
path = tempPath;
}
}
// default back to the Centered style.
style = Style.Centered;
}
if ( style == Style.Stretched )
{
key.SetValue(@"WallpaperStyle", 2.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 0.ToString( ) ) ;
}
if ( style == Style.Centered )
{
key.SetValue(@"WallpaperStyle", 1.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 0.ToString( ) ) ;
}
if ( style == Style.Tiled )
{
key.SetValue(@"WallpaperStyle", 1.ToString( ) ) ;
key.SetValue(@"TileWallpaper", 1.ToString( ) ) ;
}
SystemParametersInfo( SPI_SETDESKWALLPAPER,
0,
path,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
}
}
}
=============
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top