/* * Copyright (c) 2005, FullSpan Software (www.fullspan.com) * * Licensed under the BSD License * OSI Certified Open Source Software (www.opensource.org) * * You may not use this file except in compliance with the License. You should * have received a copy of the License with this distribution, or you can find * it at: http://www.fullspan.com/shared/license.html. * * NO WARRANTY - USE AT YOUR OWN RISK. All software and other materials * distributed under the License are provided on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ using System; using System.Collections.Generic; using System.Configuration; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Text; #region log4netconfig // Configure log4net using the application .config file. This will cause // log4net to look for a configuration file called .exe.config // in the application base directory (i.e., the directory containing // .exe). // // Watch=true tells log4net to watch the config file for changes, so that // settings can be updated while the program is executing. [assembly: log4net.Config.XmlConfigurator(Watch = true)] #endregion namespace FullSpan.RotateWallpaper { /// /// Legacy Windows API interface for setting desktop wallpaper. /// public class WinAPI { /// /// Action: set wallpaper. /// public const int SPI_SETDESKWALLPAPER = 20; /// /// Flag: update system settings (was legacy INI file). /// public const int SPIF_UPDATEINIFILE = 0x01; /// /// Flag: notify applications when system settings (was legacy INI file) change. /// public const int SPIF_SENDWININICHANGE = 0x02; /// /// Stretch wallpaper to fit screen. /// public const int WPSTYLE_STRETCH = 1; /// /// Windows .NET interop API for SystemParametersInfo. /// /// /// /// /// /// [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int SystemParametersInfo( int uAction, int uParam, string lpvParam, int fuWinIni); } /// /// How to rotate wallpaper: at random or in a round-robin cycle. /// public enum RotateMode { /// /// Select the next wallpaper image at random. /// Random, /// /// Select the next wallpaper image in alphabetical order. /// After reaching the last image, cycle back to the first image. /// Cycle } /// /// Application specific exception. /// public class RotateWallpaperException : ApplicationException { /// /// Application specific exception. /// /// /// public RotateWallpaperException(string msg, Exception ex) : base(msg, ex) { } /// /// Application specific exception. /// /// public RotateWallpaperException(string msg) : base(msg) { } } /// /// Changes (rotates) the Windows desktop wallpaper to one of the images /// in a specified directory. /// public class RotateWallpaper { // Constants private static readonly log4net.ILog LOGGER = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string[] IMAGE_FILE_EXTENSIONS = { ".bmp", ".gif", ".jpg" }; /// /// After selecting the wallpaper image, it is converted /// (if necessary) to BMP format, and stored in this file /// in the specified wallpaper image directory. /// public const string WALLPAPER_FILENAME = "_CurrentWallpaper.bmp"; /// /// Usage message. /// public const string USAGE = @" Usage: RotateWallpaper is the rotate mode. Valid modes are: Random: select the next wallpaper image randomly. Cycle: cycle through the wallpaper images alphabetically. is the directory where the wallpaper images are stored. Supported file types are .jpg, .gif, and .bmp. Each time you run RotateWallpaper, it will select a new wallpaper image from and set it as the current wallpaper. A typical usage for RotateWallpaper is to run it as a Scheduled Task to change the wallpaper automatically daily or weekly. "; // Static methods /// /// /// /// public static void Main(string[] args) { LOGGER.Debug("Started"); if (args.Length != 2) { ShowUsage("Error: Improper syntax: " + Environment.CommandLine); return; } RotateMode rotateMode; RotateWallpaper rotator; try { rotateMode = (RotateMode)(Enum.Parse(typeof(RotateMode), args[0], true)); } catch (ArgumentException e) { string errmsg = "Error: Unknown mode: " + args[0]; LOGGER.Fatal(errmsg, e); ShowUsage(errmsg); return; } try { rotator = new RotateWallpaper(rotateMode, args[1]); rotator.Rotate(); } catch (RotateWallpaperException e) { string errmsg = "Error: " + e.Message; LOGGER.Error(errmsg, e); Console.WriteLine(errmsg); return; } } private static void ShowUsage() { ShowUsage(""); } private static void ShowUsage(string usageMsg) { string msg = usageMsg + USAGE; Console.WriteLine(msg); LOGGER.Fatal(msg); } // Instance variables private string m_imageDir; private RotateMode m_rotateMode; private List m_imageFileList; private string m_wpImageSourceFileName; private RotateWallpaperSettings m_settings; // Constructor /// /// Creates a RotateWallpaper instance which will rotate the /// Windows desktop wallpaper based on the specified parameters. /// /// If the rotateMode is Random, /// a random image from the directory is picked. If it is Cycle, /// the next filename (in alphabetical order) is picked; after the /// wallpaper has been set to the last filename, Cycle starts again with /// the first filename. /// The directory from which the next /// wallpaper image will be picked. It must contain at least /// one image file. public RotateWallpaper(RotateMode rotateMode, string imageDir) { m_imageDir = imageDir; m_rotateMode = rotateMode; if (!Directory.Exists(m_imageDir)) { throw new RotateWallpaperException("Directory not found: " + imageDir); } m_settings = new RotateWallpaperSettings(); } // Instance methods /// /// Changes (rotates) the Windows desktop wallpaper based on the /// settings specified when this instance was created. /// public void Rotate() { FindImageFiles(); switch (m_rotateMode) { case RotateMode.Cycle: RotateCycle(); break; case RotateMode.Random: RotateRandom(); break; default: throw new RotateWallpaperException("Unable to handle rotate mode: " + m_rotateMode.ToString()); } m_settings.CurrentWallpaperImageSourceFileName = m_wpImageSourceFileName; m_settings.Save(); } private void FindImageFiles() { List imageFileList = new List(); foreach (string ext in IMAGE_FILE_EXTENSIONS) { string[] imageFiles = Directory.GetFiles(m_imageDir, "*" + ext); foreach (string fullFilename in imageFiles) { string fileName = Path.GetFileName(fullFilename); if (!WALLPAPER_FILENAME.Equals(fileName, StringComparison.CurrentCultureIgnoreCase)) { imageFileList.Add(fileName); } } } imageFileList.Sort(); m_imageFileList = imageFileList; if (m_imageFileList.Count < 1) { throw new RotateWallpaperException( "No image files found in directory: " + m_imageDir); } } private void RotateRandom() { Random random = new Random(); int index = random.Next(m_imageFileList.Count); SetWallpaper(m_imageFileList[index]); } private void RotateCycle() { int index = m_imageFileList.FindIndex(IsCurrentWallpaper); // If the index is -1, the current wallpaper is either not set, or // is not in the list (for example, the user deleted the file or // changed the wallpaper image directory. ++ the index to set it to // 0, which will pick the first file in the list. // // If the index is >= 0, ++ the index to pick the next file in the list. index++; // If the index ran off the end, reset it to 0. if (index >= m_imageFileList.Count) { index = 0; } SetWallpaper(m_imageFileList[index]); } private bool IsCurrentWallpaper(string filename) { if (filename.Equals(m_settings.CurrentWallpaperImageSourceFileName)) { return true; } return false; } private void SetWallpaper(string wpImageSourceFileName) { m_wpImageSourceFileName = wpImageSourceFileName; string wpImageSourcePathAndFileName = Path.Combine(m_imageDir, m_wpImageSourceFileName); Image img = Image.FromFile(wpImageSourcePathAndFileName); string wallpaperPathAndFileName = Path.Combine(m_imageDir, WALLPAPER_FILENAME); img.Save(wallpaperPathAndFileName, System.Drawing.Imaging.ImageFormat.Bmp); img.Dispose(); int ret = WinAPI.SystemParametersInfo(WinAPI.SPI_SETDESKWALLPAPER, WinAPI.WPSTYLE_STRETCH, wallpaperPathAndFileName, WinAPI.SPIF_UPDATEINIFILE | WinAPI.SPIF_SENDWININICHANGE); LOGGER.Info("Set wallpaper: " + Path.GetFullPath(wpImageSourcePathAndFileName)); } } /// /// Settings for RotateWallpaper. /// public class RotateWallpaperSettings : ApplicationSettingsBase { /// /// The name of the original source image (.jpg, .gif, .bmp) that /// was last set as the desktop wallpaper image. This is the /// image that has been converted (if necessary) to .bmp format /// and stored in WALLPAPER_FILENAME. /// [UserScopedSettingAttribute()] public string CurrentWallpaperImageSourceFileName { get { return((string) this["CurrentWallpaperImageSourceFileName"]); } set { this["CurrentWallpaperImageSourceFileName"] = value; } } } }