ActiveState Code

Recipe 435877: Change the wallpaper under Windows


Change the current wallpaper under Windows

Python
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)

Discussion

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.

Comments

  1. 1. At 10:16 a.m. on 25 jan 2006, Chris Somerlot said:

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

  2. 2. At 8:21 a.m. on 14 may 2007, etatS evictA said:

    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.

  3. 3. At 1:24 p.m. on 2 sep 2007, tim martin said:

    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!

  4. 4. At 3:01 p.m. on 2 sep 2007, tim martin said:

    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
    

Sign in to comment