Windows 7 comes with the option of a Desktop Slideshow, point out a folder of images and then tell the OS how often to cycle through them. Fantastic I thought, I can have a day time and a night time desktop, colourful and cheery by day, more subdued and less bright for night work. Hmm, doesn’t work like that, you can sertainly cycle though images every hour, but if you put your somputer to sleep or turn it off then the day/night images soon get out of sync.

Simple (I thought), name the images systematically then write a little VBScript that gets the system time then loads the appropriate image. This is well documented on the web, the following example is from the TechRepublic website:
dim wshShell
dim sUserName

Set wshShell = WScript.CreateObject("WScript.Shell")
sUserName = wshShell.ExpandEnvironmentStrings("%USERNAME%")
Set oShell = CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
sWinDir = oFSO.GetSpecialFolder(0)
sWallPaper = "c:\IMGP0816.bmp"

' update in registry
oShell.RegWrite "HKCU\Control Panel\Desktop\Wallpaper", sWallPaper
' let the system know about the change
oShell.Run "%windir%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters", 1, True

Unfortunately the user32.dll call does not work in Windows 7, the advice is to use the Win32 API instead.

So I wrote a little C++ app (my first) that uses the SystemParametersInfo API for Control Panel Settings, specifically SPI_SETDESKWALLPAPER. The source is below;


#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <iostream>
#include <string>
#include <sstream>

int main()
{
SYSTEMTIME lt;
GetLocalTime(&lt);

//concatenate
std::string path = "C:\\wallpaper\\";
std::string filename;
std::stringstream sstm;
sstm << path << lt.wMonth << "_" << lt.wHour << ".jpg";
filename = sstm.str();

//Generate a null-terminated sequence of characters (c-string)
char * cstrfilename;
cstrfilename =
new char [filename.size()+1];
strcpy (cstrfilename, filename.c_str());

// cstr now contains a c-string copy of str
std::cout << "built string: " << sstm.str() << std::endl;
SystemParametersInfo( SPI_SETDESKWALLPAPER,
0, (PVOID)cstrfilename, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE );
return
0;
}

Compile this using MinGW and a command line like:
g++ wallpaper.cpp -o wallpaper.exe -mwindows
note -mwindows is depreacted, you should probably use “-Wl,–subsystem,windows“. This compiles the code so that no window pops up each time the litle program is run. Without this, the code is compiled as a console command and the command window will flash up each time the program is exectuted.

I have set this to run every 10 minutes, it works fine, the desktop slideshow has a smooth transition from one image to the next whereas this method simply swaps the images, but for the series of images I am using this works OK. I now have a time accurate view of the earth from space. Delighted with my fist C++ attempts, I would welcome any suggestions for tidying the code which I am sure is horrid. 2 examples from the series of desktop background images are below. I hope to write more on how I assembled these images.

The European continent around 9AM in April

sunset accross Europe, 4PM

TODO:

  • Pass the image directory as a parameter
  • Format the time string returned eg currently 4_1 to 04_01 strftime (timestamp_buf, 10,"%m_%H", localtime(&now));
Advertisements