Saturday, March 22, 2008

how to have random (and not so random) wallpapers in windows xp

This was on my programming wishlist: a way to randomize wallpapers so that it changes every time I login to Windows XP. There exists programs on the net that does that, but I was looking for a solution that takes a small amount of scripting on my part. Ideally, I'd like to install only the script interpreter and nothing else.

The original idea was to create a shortcut, the equivalent of a UNIX symbolic link, to the picture file I wanted to display. I downloaded Python 2.5, copied a selection of my travel photos into a directory, and wrote a script that creates a shortcut (with a fixed name) to a randomly choosen file from that directory. Then I edited the registry so that this script is run at login. I needed some way to create a shortcut from the command line. This turned out to be non-trivial since XP does not offer a straightforward command line utility that creates shortcuts. I went against my rule and used a freeware shortcut creator that I executed in the script file. From Control Panel -> Display -> Desktop, I set the wallpaper to this shortcut. That didn't work. The .lnk file was opened instead of the file that the shortcut file points to. Apparently, shortcuts sometimes aren't taken to be links to the files they point to, unlike symbolic links in UNIX.

Naturally, one can do away with shortcuts, copy the chosen file over to a fixed filename, and configure this fixed filename to be the wallpaper. I ran the modified script, and then set the wallpaper to point this file in Control Panel -> Display -> Desktop. I had my randomly chosen wallpaper the first time I did this, but it didn't change on subsequent logins! The script did what it was supposed to do --- update wallpaper file by copying over the selected image file. Windows just didn't realize the file was updated!

I did a little surfing on the net and poking around in the registry. Windows XP stores the path to the wallpaper file in the key "HKEY_CURRENT_USER/Control Panel/Desktop/Wallpaper". This file is always a bitmap, even when a jpg or gif file is assigned to be the wallpaper. So it seems like the final format of the file needs to be a bmp. This was the next discovery --- when any other graphics format is chosen as the wallpaper, Windows would convert that into a bmp and then assign the path of the latter to the key. I need a command line graphics file converter! Google didn't turn up any results for command line graphic file converters that comes with Windows, so I used ImageMagick (it might be worthwhile to find out how Windows does it). As for changing the value of the wallpaper key in the registry, the command line program reg.exe that comes bundled with Windows XP does just that.

It was not enough to merely change the key value. One has to tell Windows to load the new value. As described here, one has to run " RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters" to update the system of the changes.

Here's the Python script that does all the work. Edit the necessary lines for your paths.

import os
import random
import os.path

random.seed()

wallpapercurr = r"[PATH-TO-WALLPAPER]\currwall.bmp"
ImageMagickexe = r'[PATH-TO-IMAGEMAGICK]\convert.exe '

wallpaperdir = r"[PATH-TO-WALLPAPER-DIRECTORY]"
filelist = os.listdir(wallpaperdir)
fileindex = random.randrange(0, len(filelist)-1)
if os.path.splitext(filelist[fileindex])[1].lower() == '.bmp':
  execstring = "copy " + wallpaperdir + '\\' + filelist[fileindex] + " " + wallpapercurr
else:
  execstring = ImageMagickexe + wallpaperdir + '\\' + filelist[fileindex] + " " + wallpapercurr
os.system(execstring)

# set registry entry
setregexecstring = r'reg add "hkcu\Control Panel\Desktop" /v Wallpaper /t REG_SZ /d "' + wallpapercurr + r'" /f'
os.system(setregexecstring)

# refresh
os.system("RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters")

Install your favorite Python interpreter, then either through the registry or the Startup folder on the Start Menu, set up the interpreter to execute this script on log in.

For amateur astronomers and people with casual interests in the night sky, this script can be easily modified to display the star map for the day. The basic idea is to have a star charting program generate star charts as graphic files. These files need to have filenames that are labeled according to the date and time they are plotted for. A star charting program that has a command line interface would be extremely useful. Unfortunately, I couldn't find one with that feature, so I went about the laborious way. I manually generated star maps in .gif format using Cartes du Ciel, and stored them in the same directory. The first time I did this, I generated enough star maps for the rest of this month. The .gifs generated have filenames that are of the format [location]-[year]-[month]-[day]-[time].gif. This script does the rest of the work. As before, some lines need to be edited.

import os
import time

wallpaperdir = r"[PATH-TO-STARMAPS]\Starmaps"
timestruct = time.localtime()
y=timestruct[0]
m=timestruct[1]
d=timestruct[2]
mapstring = "[LOCATION]-" + `y` + "-" + `m` + "-" + `d` + "-[TIME].gif"

#execstring that converts/copies file
execstring = ImageMagickexe + wallpaperdir + '\\' + mapstring + wallpapercurr
os.system(execstring)

# set registry entry
setregexecstring = r'reg add "hkcu\Control Panel\Desktop" /v Wallpaper /t REG_SZ /d "' + wallpapercurr + r'" /f'
os.system(setregexecstring)

# refresh
os.system("RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters")

As before, save this script, configure the system to run this at startup, and you're all set!

No comments: