/// <summary> /// Creates a multiscreen wallpaper from multiple <see cref="Wallpaper" /> objects (from multiple images). /// </summary> /// <remarks> /// <para> /// Use a low <paramref name="scaleFactor" /> to create preview images. /// </para> /// <para> /// Only set <paramref name="useWindowsFix" /> to <c>true</c> if you are planning to apply the generated /// image on the Windows Desktop. /// </para> /// </remarks> /// <param name="wallpapers"> /// A collection containing the <see cref="Wallpaper" /> objects to use. /// </param> /// <param name="scaleFactor"> /// Defines the factor to scale the created image. Decrease this value to speed up the drawing process of preview images. /// </param> /// <param name="useWindowsFix"> /// A <see cref="bool" /> indicating whether the image is drawn in a special way to fix problems that occur when /// Windows applies tiled images for extended desktops. Set to <c>true</c> if you are planning to apply the generated /// image on the Windows Desktop. /// </param> /// <returns> /// A <see cref="Image" /> instance containing drawn the multiscreen wallpaper image. /// </returns> /// <exception cref="ArgumentException"> /// <paramref name="wallpapers" /> a <c>null</c> item. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="wallpapers" /> is empty. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="wallpapers" /> is <c>null</c>. /// </exception> /// <exception cref="FileNotFoundException"> /// The image file where on of the <see cref="Wallpaper" /> objects refers to could not be found. /// </exception> protected Image CreateMultiscreenFromMultipleInternal(IList <Wallpaper> wallpapers, float scaleFactor, bool useWindowsFix) { if (wallpapers == null) { throw new ArgumentNullException(); } if (wallpapers.Count == 0) { throw new ArgumentException(); } if (wallpapers.Contains(null)) { throw new ArgumentException(); } Rectangle fullScreenBounds = WallpaperBuilderBase.FullScreenBounds; int screenCount = Screen.AllScreens.Length; Bitmap wallpaperImage = new Bitmap((int)(fullScreenBounds.Width * scaleFactor), (int)(fullScreenBounds.Height * scaleFactor)); using (Graphics graphics = Graphics.FromImage(wallpaperImage)) { Graphics destinationGraphics = graphics; Bitmap preWallpaperImage = null; try { // If the fullscreenbounds rectangle has a negative x or y values, we normalize them by using 0,0 as origin and adding // the difference to each drawn wallpaper later. int xOriginAdd; if (fullScreenBounds.X < 0) { xOriginAdd = Math.Abs(WallpaperBuilderBase.FullScreenBounds.X); } else { xOriginAdd = 0; } int yOriginAdd; if (fullScreenBounds.Y < 0) { yOriginAdd = Math.Abs(WallpaperBuilderBase.FullScreenBounds.Y); } else { yOriginAdd = 0; } // Check if we have to redraw the end-wallpaper to fix it for Windows' strange way of applyment. bool requiresWindowsFix = ((useWindowsFix) && ((fullScreenBounds.Left < 0) || (fullScreenBounds.Top < 0))); if (requiresWindowsFix) { // We have to redraw it, we need another temporary image and draw on this one instead. preWallpaperImage = new Bitmap(wallpaperImage.Width, wallpaperImage.Height); destinationGraphics = Graphics.FromImage(preWallpaperImage); } // Draw the full wallpaper. destinationGraphics.ScaleTransform(scaleFactor, scaleFactor); for (int i = 0; i < screenCount; i++) { Rectangle screenBounds = this.ScreensSettings[i].BoundsWithMargin; screenBounds.X += xOriginAdd; screenBounds.Y += yOriginAdd; destinationGraphics.SetClip(screenBounds, CombineMode.Replace); WallpaperBuilderBase.DrawWallpaper(destinationGraphics, screenBounds, wallpapers[i], wallpapers[i].Placement); WallpaperBuilderBase.DrawOverlayTexts(destinationGraphics, screenBounds, wallpapers, this.ScreensSettings[i].TextOverlays); destinationGraphics.ResetClip(); } if (requiresWindowsFix) { // Now redraw the wallpaper but fixed. WallpaperBuilderBase.DrawFullWallpaperFixed(graphics, preWallpaperImage); } } finally { destinationGraphics.Dispose(); preWallpaperImage?.Dispose(); } } return(wallpaperImage); }
/// <summary> /// Creates a multiscreen wallpaper from one <see cref="Wallpaper" /> object (from one image). /// </summary> /// <inheritdoc cref="CreateMultiscreenFromMultipleInternal" select='remarks|param|returns' /> /// <param name="multiscreenWallpaper"> /// The <see cref="Wallpaper" /> object to use. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="multiscreenWallpaper" /> is <c>null</c>. /// </exception> /// <exception cref="FileNotFoundException"> /// The image file where the <paramref name="multiscreenWallpaper" /> object refers to could not be found. /// </exception> /// <seealso cref="Wallpaper">Wallpaper Class</seealso> public Image CreateMultiscreenFromSingle(Wallpaper multiscreenWallpaper, float scaleFactor, bool useWindowsFix) { if (multiscreenWallpaper == null) { throw new ArgumentNullException(); } Rectangle fullScreenBounds = WallpaperBuilderBase.FullScreenBounds; Bitmap wallpaperImage = new Bitmap((int)(fullScreenBounds.Width * scaleFactor), (int)(fullScreenBounds.Height * scaleFactor)); using (Graphics graphics = Graphics.FromImage(wallpaperImage)) { Graphics destinationGraphics = graphics; Bitmap preWallpaperImage = null; try { // If the fullscreenbounds rectangle has a negative x or y values, we normalize them by using 0,0 as origin and adding // the difference to each drawn wallpaper later. int xOriginAdd; if (fullScreenBounds.X < 0) { xOriginAdd = Math.Abs(WallpaperBuilderBase.FullScreenBounds.X); } else { xOriginAdd = 0; } int yOriginAdd; if (fullScreenBounds.Y < 0) { yOriginAdd = Math.Abs(WallpaperBuilderBase.FullScreenBounds.Y); } else { yOriginAdd = 0; } // Check if we have to redraw the end-wallpaper to fix it for Windows. bool requiresWindowsFix = ((useWindowsFix) && ((fullScreenBounds.Left < 0) || (fullScreenBounds.Top < 0))); if (requiresWindowsFix) { // We have to redraw it, we need another temporary image and draw on this one instead. preWallpaperImage = new Bitmap(wallpaperImage.Width, wallpaperImage.Height); destinationGraphics = Graphics.FromImage(preWallpaperImage); } destinationGraphics.ScaleTransform(scaleFactor, scaleFactor); // The rectangle of the multiscreen wallpaper should span across all screens except the ones which should display // a statical wallpaper. Rectangle?multiscreenWallpaperRect = null; for (int i = 0; i < this.ScreensSettings.Count; i++) { if (this.ScreensSettings[i].CycleRandomly || !this.ScreensSettings[i].StaticWallpaper.EvaluateCycleConditions()) { if (multiscreenWallpaperRect == null) { multiscreenWallpaperRect = this.ScreensSettings[i].BoundsWithMargin; } else { multiscreenWallpaperRect = Rectangle.Union(multiscreenWallpaperRect.Value, this.ScreensSettings[i].BoundsWithMargin); } } } // null would mean that all screens should display static wallpapers. if (multiscreenWallpaperRect != null) { Rectangle multiscreenWallpaperRectValue = multiscreenWallpaperRect.Value; multiscreenWallpaperRectValue.X += xOriginAdd; multiscreenWallpaperRectValue.Y += yOriginAdd; destinationGraphics.SetClip(multiscreenWallpaperRectValue); WallpaperBuilderBase.DrawWallpaper(destinationGraphics, multiscreenWallpaperRectValue, multiscreenWallpaper, multiscreenWallpaper.Placement); destinationGraphics.ResetClip(); } // Draw or overdraw all static wallpapers and draw the Overlay Texts for all screens. for (int i = 0; i < this.ScreensSettings.Count; i++) { destinationGraphics.SetClip(this.ScreensSettings[i].BoundsWithMargin); if (!this.ScreensSettings[i].CycleRandomly && this.ScreensSettings[i].StaticWallpaper.EvaluateCycleConditions()) { WallpaperBuilderBase.DrawWallpaper( destinationGraphics, this.ScreensSettings[i].BoundsWithMargin, this.ScreensSettings[i].StaticWallpaper, this.ScreensSettings[i].StaticWallpaper.Placement); } WallpaperBuilderBase.DrawOverlayTexts( destinationGraphics, this.ScreensSettings[i].BoundsWithMargin, new[] { multiscreenWallpaper }, this.ScreensSettings[i].TextOverlays); destinationGraphics.ResetClip(); } if (requiresWindowsFix) { // Now redraw the wallpaper but fixed. WallpaperBuilderBase.DrawFullWallpaperFixed(graphics, preWallpaperImage); } } finally { destinationGraphics.Dispose(); preWallpaperImage?.Dispose(); } } return(wallpaperImage); }