/// <summary> /// Initializes the ScreenConfiguration for a collection of Screens /// with a specified BezelCompensation /// </summary> /// <param name="screens">Screens in the ScreenConfiguration</param> /// <param name="bezelCompensation">The BezelCompensation in pixels as an added margin to screen /// bounds in a VirtualScreen to compensate for the display bezels in a multi-monitor setup</param> public ScreenConfiguration(Screen[] screens, int bezelCompensation) { this.screenDistributor = new ScreenDistributor(this); this.bezelCompensation = bezelCompensation; // private field so we don't trigger UpdateVirtualScreen() twice this.Screens = screens; }
private void DrawScreenPerPixel(Bitmap wallpaper, Bitmap image, Screen screen) { Point screenPosition = new Point(); Point imagePosition = new Point(); Point wallpaperPosition = new Point(); using (FastBitmap wallpaperBitmap = new FastBitmap(wallpaper)) using (FastBitmap imageBitmap = new FastBitmap(image)) { // Loop through all pixel rows for (screenPosition.Y = screen.Bounds.Y; screenPosition.Y < screen.Bounds.Bottom; screenPosition.Y++) { // Determine the vertical components of the image- and wallpaper positions imagePosition.Y = screen.BoundsInVirtualScreen.Y + (screenPosition.Y - screen.Bounds.Y); wallpaperPosition.Y = screenPosition.Y >= 0 ? screenPosition.Y : wallpaper.Height + screenPosition.Y; // Loop through all pixels in the current row for (screenPosition.X = screen.Bounds.X; screenPosition.X < screen.Bounds.Right; screenPosition.X++) { // Determine the horizontal components of the image- and wallpaper positions imagePosition.X = screen.BoundsInVirtualScreen.X + (screenPosition.X - screen.Bounds.X); wallpaperPosition.X = screenPosition.X >= 0 ? screenPosition.X : wallpaper.Width + screenPosition.X; // Assign the pixel data values at the image pixel position to the pixel at // the wallpaper pixel position (copying it over) FastBitmap.Pixel imagePixel = imageBitmap.GetPixel(imagePosition.X, imagePosition.Y); wallpaperBitmap.SetPixel(wallpaperPosition.X, wallpaperPosition.Y, imagePixel); } } } }
private void DrawScreen(Bitmap wallpaper, Bitmap image, Screen screen) { if (screen.Bounds.X >= 0 && screen.Bounds.Y >= 0) // Needs optimization: doesn't cross x=0 or y=0 { this.DrawScreenRectangle(wallpaper, image, screen); } else { this.DrawScreenPerPixel(wallpaper, image, screen); } }
/// <summary> /// Determines the number of neighbor Screens on top /// </summary> /// <param name="screen">The Screen to determine the number of top neighbors for</param> /// <param name="offset">The offset of all screens in the ScreenConfiguration</param> /// <returns>The number of top neighbor Screen of the given Screen</returns> private int DetermineTopNeighborCount(Screen screen, Point offset) { Rectangle topNeighborRegion = new Rectangle( screen.Bounds.X, offset.Y, screen.Bounds.Width, screen.Bounds.Y - offset.Y); return this.screenConfiguration.Screens.Where( s => s.Bounds.IntersectsWith(topNeighborRegion)).Count(); }
/// <summary> /// Determines the number of neighbor Screens on the left /// </summary> /// <param name="screen">The Screen to determine the number of neighbors on the left for</param> /// <param name="offset">The offset of all screens in the ScreenConfiguration</param> /// <returns>The number of neighbor Screens on the left of the given Screen</returns> private int DetermineLeftNeighborCount(Screen screen, Point offset) { Rectangle leftNeighborRegion = new Rectangle( offset.X, screen.Bounds.Y, screen.Bounds.X - offset.X, screen.Bounds.Height); return this.screenConfiguration.Screens.Where( s => s.Bounds.IntersectsWith(leftNeighborRegion)).Count(); }
//private struct PixelData //{ // public byte blue; // public byte green; // public byte red; // public byte alpha; //} //private void DrawScreenPerPixelFast(Bitmap wallpaper, Bitmap image, Screen screen) //{ // Point screenPosition = new Point(); // Point imagePosition = new Point(); // Point wallpaperPosition = new Point(); // BitmapData imageData = image.LockBits(screen.BoundsInImage, ImageLockMode.ReadOnly, image.PixelFormat); // BitmapData wallpaperData = wallpaper.LockBits(new Rectangle(0, 0, wallpaper.Width, wallpaper.Height), // ImageLockMode.WriteOnly, wallpaper.PixelFormat); // unsafe // { // IntPtr imageDataOffset = imageData.Scan0; // IntPtr wallpaperDataOffset = wallpaperData.Scan0; // int wallpaperWidth = wallpaper.Width; // int wallpaperHeight = wallpaper.Height; // for (screenPosition.Y = screen.BoundsInSurface.Y; screenPosition.Y < // screen.BoundsInSurface.Y + screen.BoundsInSurface.Height; screenPosition.Y++) // { // IntPtr imageYPosition = imageDataOffset + imagePosition.Y * imageData.Stride; // wallpaperPosition.Y = screenPosition.Y >= 0 ? // screenPosition.Y : wallpaperHeight + screenPosition.Y; // imagePosition.Y = screen.BoundsInImage.Y + (screenPosition.Y - screen.BoundsInSurface.Y); // for (screenPosition.X = screen.BoundsInSurface.X; screenPosition.X < // screen.BoundsInSurface.X + screen.BoundsInSurface.Width; screenPosition.X++) // { // // Positions in wallpaper (destination) // wallpaperPosition.X = screenPosition.X >= 0 ? // screenPosition.X : wallpaperWidth + screenPosition.X; // // Position in image (source) = BoundsInImage + offset // imagePosition.X = screen.BoundsInImage.X + (screenPosition.X - screen.BoundsInSurface.X); // PixelData imagePixel = *(PixelData*)(imageYPosition + imagePosition.X * sizeof(PixelData)); // PixelData* wallpaperPixel = (PixelData*)(wallpaperDataOffset + wallpaperPosition.Y * wallpaperData.Stride + // wallpaperPosition.X * sizeof(PixelData)); // *wallpaperPixel = imagePixel; // } // } // } // image.UnlockBits(imageData); // wallpaper.UnlockBits(wallpaperData); //} private void DrawScreenRectangle(Bitmap wallpaper, Bitmap image, Screen screen) { System.Drawing.Rectangle destination = screen.Bounds; destination.X = destination.X >= 0 ? destination.X : wallpaper.Width + destination.X; destination.Y = destination.Y >= 0 ? destination.Y : wallpaper.Height + destination.Y; using (Graphics graphics = Graphics.FromImage(wallpaper)) { graphics.DrawImage(image, destination, screen.BoundsInVirtualScreen, GraphicsUnit.Pixel); } }
/// <summary> /// Initializes the ScreenConfiguration for a collection of Screens and /// a default BezelCompensation of 0 /// </summary> /// <param name="screens">Screens in the ScreenConfiguration</param> public ScreenConfiguration(Screen[] screens) : this(screens, 0) { }