Welcome, guest | Sign In | My Account | Store | Cart

Change the current wallpaper under Windows

Python, 5 lines
1
2
3
4
5
import ctypes

SPI_SETDESKWALLPAPER = 20 # According to http://support.microsoft.com/default.aspx?scid=97142

ctypes.windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, "myimage.jpg" , 0)

This recipe requires the ctypes module (http://starship.python.net/crew/theller/ctypes/)

The wallpaper is kept until the user logs off or the computer is rebooted. The image does not need to be kept on disk.

4 comments

Chris Somerlot 15 years, 10 months ago  # | flag

only BMPs on Windows XP. I can only get this to work with windows bitmap files

etatS evictA 14 years, 6 months ago  # | flag

use ActiveDesktop functions for non-BMP images. To use anything besides BMP files, you'll need to use ActiveDesktop functions. I don't know if that can be done via Python -- is there any way to get a pointer to the IActiveDesktop interface (CLSID_ActiveDesktop, IID_IActiveDesktop)? In C++ you'd use the CoCreateInstance function.

tim martin 14 years, 2 months ago  # | flag

I think all windows desktops are converted to bmps first. After some registry searching, I think Windows (XP) will only take BMPs as wallpapers. I wasn't quite sure which entry referred to the current desktop image, but they were all BMP's. Apparently, even browsers will convert to BMP, and store the image somewhere. For instance, Firefox put it in %APPDATA%. Therefore, you'll need a conversion technique if the user wishes to have a JPEG-image (or any format for that matter) wallpaper. The Python Imaging Library seems to do the job fine. Make sure PIL supports parsing of the format you wish to convert from. I only tested with JPEG (which works).

I wrote a little script for changing my wallpaper to random images in a certain folder of mine every so often. Here is an excerpt of that script where my BMP conversion takes place. I also included a resize function because sometimes the image resolution is bigger than my screen res. Please comment if you could because I know its not very elegant.

def convertToBMP(imagePath):

    def resize(imagePath,maxh=1024,maxw=1280,method=Image.BILINEAR): #bilinear offers decent quality and low processing time
        im = Image.open(imagePath)
        w,h = im.size

        if w > maxw:    #width conformity
            whRatio = float(w)/h
            im = im.resize((maxw,int(float(maxw)/whRatio)),method)
        if im.size[1] > maxh:   #height conformity
            im = im.resize(int(maxh*whRatio),maxh)

        im.save(imagePath)
        return imagePath

    f = open(imagePath,'rb')
    p = ImageFile.Parser()
    p.feed(f.read())
    newPath = os.path.join(os.getcwd(),'d.bmp') #automatically infers image format from extension name, and writes as such.
    p.close().save(newPath)
    return resize(newPath)

Later the script uses the "ctypes.windll.user32.SystemParametersInfoA" method explained above. If used the parameters like above your wallpaper will be centered, which I like. If you'd like to mess around, check out: http://blogs.msdn.com/coding4fun/archive/2006/10/31/912569.aspx for the comprehensive use of the method. Of course, you'll have to translate what he does into python, but its not very hard to understand. Good luck!

tim martin 14 years, 2 months ago  # | flag

whoops. Actually, in response to my last comment, the wallpaper's style will match your currently selected one. By this, I mean, if you have 'Stretch' set in your Desktop Properties, and you change your wallpaper with SystemsParameterInfoA, your wallpaper will stretch, regardless if you resized or what not.

Wallpaper properties such as the 'stretch', 'tiled' and 'center' are stored in the registry. Read up that one blog i posted in my last comment for more info.

I wrote a method to register that wallpaper is set to centered. That way, upon the SystemsParameterInfoA call, your wallpaper will be centered. Note that registering these properties will not change your wallpaper immediately. It seems windows only references these registry value upon a wallpaper change. so first register the values, then change wallpaper. Here is my method:

def registerCentered():
    #changes the registry to center wallpaper
    wallpaperStyle = '0'
    tileWallpaper = '0'
    try:
        desktopKey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
                                     'Control Panel\\Desktop',
                                     0,
                                     _winreg.KEY_SET_VALUE)
        _winreg.SetValueEx(desktopKey,
                           'WallpaperStyle',
                           0,
                           _winreg.REG_SZ,
                           wallpaperStyle)
        _winreg.SetValueEx(desktopKey,
                           'TileWallpaper',
                           0,
                           _winreg.REG_SZ,
                           tileWallpaper)
        return 1
    except:
        return 0