/// <summary> /// Checks whether there has been enough of a change in daylight setting to warrant a wallpaper change, and if there has been, /// returns the WBImage representing the new wallpaper to be changed to /// </summary> /// <returns> /// WBImage representing the new wallpaper, if there has been enough change in daylight setting to warrant a wallpaper change; /// null if there has not been enough change in daylight setting to warrant wallpaper change /// or there are no images in library /// </returns> private WBImage CheckforChange() { // Only update the wall if there is at least one image in library to work with; otherwise return null if (Library.LibraryList.Count > 0) { // First check for (and remove) any missing images Library.CheckMissing(); DateTime now = DateTime.Now; // Find closest image to current time's daylight value CurrentDaylight = GetDaylightValue(now); WBImage checkImage = FindClosestImage(now); // If image is different from current, return it if (checkImage != _currentImage) { return(checkImage); } // If new image is the same then no change will occur; return null else { return(null); } } // If no images in library, just return null return(null); }
/// <summary> /// Higher-level function for checking daylight + updating wallpaper if enough change has been /// detected; checks whether current wallpaper is different from the wallpaper that should be set at /// this time; if it is it sets that wallpaper /// Also updates the next update time and resets it to blank if one cannot be found /// </summary> /// <returns>True if the current wallpaper was changed to another, false if not</returns> public bool CheckAndUpdate() { bool changed = false; // Check for change in wall WBImage image = CheckforChange(); // If there is change, update the wall to the new one if (image != null) { SetWall(image, WallpaperStyle); changed = true; } // Find the next time when wallpaper will change _nextUpdateTime = FindNextUpdateTime(); // Restart the timer if a valid next update time was found if (_nextUpdateTime != new DateTime()) { _updateTimer.Interval = _nextUpdateTime.Subtract(DateTime.Now); _updateTimer.Start(); } // Otherwise reset the timers (sets progress to blank, giving user 'wallpaper will not change' // message in the progress bar) else { ResetTimers(); } return(changed); }
/// <summary> /// Sets the wallpaper to the WBImage represented by the selection sent from the front-end /// (front-end sends a collection representing the selected front-end element, which is converted /// into the relevent WBImage) /// </summary> /// <param name="collection"></param> private void Set(object collection) { // Cast selected image and set it as wall System.Collections.IList items = (System.Collections.IList)collection; WBImage selectedImage = (WBImage)items[0]; SetWall(selectedImage, WallpaperStyle); }
/// <summary> /// Models the next 24-hour day using the current settings and searches for the next time that /// a wallpaper change will occur; returns that time if it is found, returns a "blank" new DateTime() /// if no update will occur in 24 hours (i.e. will not occur at all with current settings); /// Also sets the front-end progress bar string to reflect that wallpaper will not change if this is /// the case /// </summary> /// <returns> /// DateTime representing time that next wallpaper update will occur if it is found, /// "blank" DateTime with value == new DateTime() == DateTime.Min if this time is not found (i.e. /// wallpaper will not update with the current settings /// </returns> private DateTime FindNextUpdateTime() { // Only do checks if there's at least 2 images in library; otherwise wallpaper will not change if (Library.LibraryList.Count > 1) { // Set last update time to now if it has not been set yet if (_lastUpdateTime == new DateTime()) { _lastUpdateTime = DateTime.Now; } // Get first check time DateTime nextCheckTime = _lastUpdateTime.AddMinutes(_checkInterval.TotalMinutes); // Continue looping until intervals have looped around back to the same time on the next day // I.e. the check time has the same date as the timer's start time, or the checktime has looped // over to the next day but is still before the timer's start time on that day // I.e. exits when check time passes the timer's start time but on the following day while (nextCheckTime.Date == _lastUpdateTime.Date || (nextCheckTime.Date == _lastUpdateTime.AddDays(1).Date && nextCheckTime.TimeOfDay.CompareTo(_lastUpdateTime.TimeOfDay) <= 0)) { // Next image that will be set as wall when brightness is checked WBImage nextCheckImage = FindClosestImage(nextCheckTime); // Return if the image will actually be different at this check time (i.e. it will actually // update to a different wall when checked) if (_currentImage != nextCheckImage) { return(nextCheckTime); } // Otherwise start the loop again, checking at the time after the next interval else { nextCheckTime = nextCheckTime.AddMinutes(_checkInterval.TotalMinutes); } } // If looped all the way around with no update, then there won't ever be any actual wall change // with the current library/automation settings // In this case, update progress report to reflect this and return a basic DateTime ProgressReport = "Wallpaper will not change with current settings"; return(new DateTime()); } // If < 2 images in library, wallpaper will not change else { ProgressReport = "Wallpaper will not change with current settings"; return(new DateTime()); } }
/// <summary> /// Sets desktop wallpaper to given WBImage using given style (fill, fit, tiled, etc.) /// </summary> /// <param name="image">WBImage to be set as wallpaper</param> /// <param name="style"> /// Wallpaper style to be used when setting: /// "Tiled", "Centered", "Stretched", "Fit", or "Fill" /// </param> private void SetWall(WBImage image, string style) { // Taken partly from https://stackoverflow.com/questions/1061678/change-desktop-wallpaper-using-code-in-net, // partly from https://stackoverflow.com/questions/19989906/how-to-set-wallpaper-style-fill-stretch-according-to-windows-version // Open registry key used to set wallpaper style RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true); // Set appropriate values on key depending on wallpaper style choice if (style == "Tiled") { key.SetValue(@"WallpaperStyle", "0"); key.SetValue(@"TileWallpaper", "1"); } else if (style == "Centered") { key.SetValue(@"WallpaperStyle", "0"); key.SetValue(@"TileWallpaper", "0"); } else if (style == "Stretched") { key.SetValue(@"WallpaperStyle", "2"); key.SetValue(@"TileWallpaper", "0"); } else if (style == "Fit") { key.SetValue(@"WallpaperStyle", "6"); key.SetValue(@"TileWallpaper", "0"); } else if (style == "Fill") { key.SetValue(@"WallpaperStyle", "10"); key.SetValue(@"TileWallpaper", "0"); } // Set the wallpaper via system parameter SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, image.Path, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); // Update current closest's thumb, background color, and front-end brightness value CurrentWallThumb = image.Thumbnail; CurrentWallBack = image.BackgroundColor; CurrentWallBrightness = image.AverageBrightness; CurrentWallFileName = Path.GetFileName(image.Path); _currentImage = image; _lastUpdateTime = DateTime.Now; }
/// <summary> /// Adds given WBImage at given filePath to the library if it is not already in library /// </summary> /// <param name="image"></param> /// <param name="filePath"></param> private void AddImage(WBImage image) { // Give user message and don't add this image if it is already in library if (LibraryList.Any(checkImage => checkImage.Path.Equals(image.Path))) { _notifier.ShowInformation(string.Format("{0} was not added since it is already in the library", Path.GetFileName(image.Path))); } // Otherwise add the image to the library else { LibraryList.Add(image); } }
/// <summary> /// Returns image in library with brightness value closest to the daylight value at given DateTime time /// with current manager settings; returns null if no images in library to work with /// </summary> /// <param name="time">DateTime to be used to compare daylight value with library images' brightness /// values</param> /// <returns> /// WBImage in library with brightness value closest to the daylight value at given /// DateTime time using current manager settings; /// null if no images in library /// </returns> private WBImage FindClosestImage(DateTime time) { // Only search for closest if there are images in the library if (Library.LibraryList.Count > 0) { // Get current daylight value double daylightAtTime = GetDaylightValue(time); // Find (enabled) image with brightness value closest to current daylight value WBImage closestImage = Library.LibraryList.Aggregate((x, y) => (Math.Abs(x.AverageBrightness - daylightAtTime) < Math.Abs(y.AverageBrightness - daylightAtTime) || !y.IsEnabled) && x.IsEnabled ? x : y); return(closestImage); } // Return null if no images in library else { return(null); } }
/// <summary> /// Generalized function working with both adding files and adding folders; adds image files from /// given filePaths list to the library /// </summary> /// <param name="sender">BackgroundWorker running the task</param> /// <param name="filePaths">List of filepaths for image files to be added to library</param> private void AddWork(object sender, List <string> filePaths) { // For keeping track of progress int numFiles = filePaths.Count; int progress; // Create the WBImage object for each image file and add it to library for (int i = 0; i < filePaths.Count; i++) { // If user cancelled then exit loop and return before adding next file if (_worker.CancellationPending == true) { return; } // Get stream, path, and filename for current file string filePath = filePaths[i]; string fileName = Path.GetFileName(filePath); // Create progress string to be shown in progress bar string progressString = string.Format("{0}|{1}|{2}", fileName, i + 1, numFiles); // Get current progress as percentage of total files progress = Convert.ToInt32((double)i / numFiles * 100); // Report progress and current file being worked on (sender as BackgroundWorker).ReportProgress(progress, progressString); // Try to add current file to the library try { // Create the bitmap in the scope of the background worker (this is the performance intensive // task for this whole process) using (Bitmap bitmap = new Bitmap(File.Open(filePaths[i], FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { // Create the WBImage for this file and add it to the results list (in the main thread // so that it doesn't get upset that UI-relevant objects were created in the background thread) Application.Current.Dispatcher.Invoke(() => { WBImage image = new WBImage(bitmap, filePath); AddImage(image); }); } } // If file fails to open, notify user catch (IOException) { // Show failure toast notif _notifier.ShowError(string.Format("Failed to add {0} to library; file corrupted or in use by another program", fileName)); } // FIXME: find a way to overcome this horrific memory allocation conundrum! // If memory allocation for Bitmap fails, notify user that image file is too big catch (OutOfMemoryException) { // Show failure toast notif _notifier.ShowError(string.Format("Failed to add {0} to library; image file is too big!", fileName)); } } }