// Note: this algorithm is not bulletproof, but will always work when the workspace is completely visible // on any combination of monitors. More specifically, where it starts to fail is when the center of the (default positioned) // image box falls off of all of the screens. In those rare/extreme cases, we don't try to do any optimization // and use the simple rectangle calculation. private bool OptimizeImageBoxGrid() { Rectangle usableWorkspaceArea = GetUsableArea(); if (usableWorkspaceArea.IsEmpty || usableWorkspaceArea.Width < 20 || usableWorkspaceArea.Height < 20) { return(false); } float rectangleWidth = usableWorkspaceArea.Width / (float)_columns; float rectangleHeight = usableWorkspaceArea.Height / (float)_rows; var imageBoxesSet = new List <IImageBox>(); foreach (Screen screen in Screen.AllScreens) { int firstRow = -1; int lastRow = -1; int firstColumn = -1; int lastColumn = -1; //Find the first and last row/column defining a sub-grid that will be kept on this screen. //We use the center of each image box in the non-optimized case to determine what screen //a particular image box should be on. for (int row = 0; row < _rows; ++row) { for (int column = 0; column < _columns; ++column) { int rectangleCentreX = usableWorkspaceArea.Left + (int)(rectangleWidth * (column + 0.5F)); int rectangleCentreY = usableWorkspaceArea.Top + (int)(rectangleHeight * (row + 0.5F)); if (screen.Bounds.Contains(rectangleCentreX, rectangleCentreY)) { if (firstRow < 0) { firstRow = row; } lastRow = row; if (firstColumn < 0) { firstColumn = column; } lastColumn = column; } } } Rectangle workspaceArea = ScreenRectangle; Rectangle screenUsableArea = Rectangle.Intersect(workspaceArea, screen.WorkingArea); //Subdivide the occupied screen area into a grid based on the start/end row/column determined above. if (!screenUsableArea.IsEmpty && firstRow >= 0 && firstColumn >= 0) { RectangleF normalizedScreenUsableArea = RectangleUtilities.CalculateNormalizedSubRectangle(workspaceArea, screenUsableArea); int screenRows = lastRow - firstRow + 1; int screenColumns = lastColumn - firstColumn + 1; float adjustedWidth = normalizedScreenUsableArea.Width / screenColumns; float adjustedHeight = normalizedScreenUsableArea.Height / screenRows; for (int screenRow = 0; screenRow < screenRows; ++screenRow) { for (int screenColumn = 0; screenColumn < screenColumns; ++screenColumn) { IImageBox imageBox = this[firstRow + screenRow, firstColumn + screenColumn]; //same one was already set; fail. if (imageBoxesSet.Contains(imageBox)) { return(false); } imageBoxesSet.Add(imageBox); float x = normalizedScreenUsableArea.Left + screenColumn * adjustedWidth; float y = normalizedScreenUsableArea.Top + screenRow * adjustedHeight; imageBox.NormalizedRectangle = new RectangleF(x, y, adjustedWidth, adjustedHeight); } } } } //Success only if every image box's rectangle was set exactly once. return(imageBoxesSet.Count == ImageBoxes.Count); }