diff --git a/OpenNest.WinForms.Tests/Forms/SavedNestsFormTests.cs b/OpenNest.WinForms.Tests/Forms/SavedNestsFormTests.cs index 9956a1c..bacc76d 100644 --- a/OpenNest.WinForms.Tests/Forms/SavedNestsFormTests.cs +++ b/OpenNest.WinForms.Tests/Forms/SavedNestsFormTests.cs @@ -121,6 +121,30 @@ public class SavedNestsFormTests "The saved-nest dialog test did not complete."); } + [Fact] + public void OpensAsALargeNormalWindowInsideTheOwnersScreen() + { + StaTestThread.Run( + () => + { + using var owner = new Form { StartPosition = FormStartPosition.Manual, Bounds = new(40, 40, 400, 300) }; + owner.Show(); + using var form = new SavedNestsForm(new FakeRepository()); + form.Show(owner); + var area = Screen.FromControl(owner).WorkingArea; + + // A maximized dialog with fixed MaximizedBounds landed off-screen on a secondary + // monitor, hiding the modal dialog behind a disabled main window. + Assert.Equal(FormWindowState.Normal, form.WindowState); + Assert.True(area.Contains(form.Bounds), $"Dialog bounds {form.Bounds} are outside the working area {area}."); + Assert.True( + form.Width >= area.Width * 8 / 10 && form.Height >= area.Height * 8 / 10, + $"Dialog size {form.Size} is small for the working area {area}."); + }, + TestTimeout, + "The saved-nest dialog test did not complete."); + } + private static NestRecord Record(string name) => new() { Id = Guid.NewGuid(), Name = name, SavedAt = DateTime.Now }; diff --git a/OpenNest/Forms/SavedNestsForm.cs b/OpenNest/Forms/SavedNestsForm.cs index b9cba85..9b08684 100644 --- a/OpenNest/Forms/SavedNestsForm.cs +++ b/OpenNest/Forms/SavedNestsForm.cs @@ -69,10 +69,10 @@ public sealed class SavedNestsForm : Form details = new NestDetailsSession(LoadDetailsAsync); Text = WindowTitle; - StartPosition = FormStartPosition.CenterParent; + // Placed on the owner's screen in Load; see FitToScreen. + StartPosition = FormStartPosition.Manual; ClientSize = new Size(1280, 800); MinimumSize = new Size(800, 560); - WindowState = FormWindowState.Maximized; MinimizeBox = false; ShowInTaskbar = false; @@ -278,9 +278,7 @@ public sealed class SavedNestsForm : Form Load += (_, _) => { - // Keep a maximized dialog's bottom row clear of the taskbar. - var area = Screen.FromControl(Owner ?? this).WorkingArea; - MaximizedBounds = new Rectangle(area.Left, area.Top, area.Width, area.Height - 20); + FitToScreen(); // Minimum sizes are applied once the container has its real height; setting them // on the default-sized container throws. @@ -320,6 +318,25 @@ public sealed class SavedNestsForm : Form return base.ProcessCmdKey(ref msg, keyData); } + /// + /// Opens the dialog as a large normal window centered in the working area of the owner's + /// screen, so its bottom row stays clear of the taskbar. It is deliberately not maximized + /// with fixed : Windows reads those relative to the + /// monitor, so bounds taken from a secondary screen moved the modal dialog off-screen there + /// and left the main window unusable. + /// + private void FitToScreen() + { + var area = Screen.FromControl(Owner ?? this).WorkingArea; + var width = System.Math.Max(MinimumSize.Width, area.Width * 9 / 10); + var height = System.Math.Max(MinimumSize.Height, area.Height * 9 / 10); + Bounds = new Rectangle( + System.Math.Max(area.Left, area.Left + (area.Width - width) / 2), + System.Math.Max(area.Top, area.Top + (area.Height - height) / 2), + width, + height); + } + private static DataGridView CreateGrid() { var grid = new DataGridView