protected override void OnLayout(LayoutEventArgs levent) { var clientSize = ClientSize; currentMetrics.TotalWidth = clientSize.Width; currentMetrics.TotalHeight = clientSize.Height; // If maximized, Windows will make a Form bigger than the screen to hide the drop shadow used for resizing. // If a Form such as this one is drawn without that drop shadow, we need to compensate for that. if (WindowState == FormWindowState.Maximized) { currentMetrics.IsMaximized = true; currentMetrics.HorizontalResizeBorderThickness = SystemInformation.HorizontalResizeBorderThickness * 2; currentMetrics.VerticalResizeBorderThickness = SystemInformation.VerticalResizeBorderThickness * 2; } else { currentMetrics.IsMaximized = false; currentMetrics.HorizontalResizeBorderThickness = SystemInformation.HorizontalResizeBorderThickness; currentMetrics.VerticalResizeBorderThickness = SystemInformation.VerticalResizeBorderThickness; } currentMetrics.CaptionHeight = CaptionHeight; if (MainMenuStrip != null && MainMenuStrip.Visible) { currentMetrics.MainMenuWidth = MainMenuHorizontalMargin + MainMenuStrip.Items .OfType <ToolStripItem>() .Where(x => x.Visible) .Select(x => x.Width) .Sum(); } else { currentMetrics.MainMenuWidth = 0; } if (currentMetrics.MainMenuWidth > 0) { MainMenuStrip.SetBounds( currentMetrics.MainMenuLeft, currentMetrics.MainMenuTop, currentMetrics.MainMenuWidth, currentMetrics.MainMenuHeight); } maximizeButton.Visible = MaximizeBox; minimizeButton.Visible = MinimizeBox; currentMetrics.UpdateSystemButtonMetrics(saveButton.Visible, MaximizeBox, MinimizeBox); closeButton.SetBounds( currentMetrics.CloseButtonLeft, currentMetrics.SystemButtonTop, currentMetrics.SystemButtonWidth, currentMetrics.SystemButtonHeight); if (saveButton.Visible) { saveButton.SetBounds( currentMetrics.SaveButtonLeft, currentMetrics.SystemButtonTop, currentMetrics.SystemButtonWidth, currentMetrics.SystemButtonHeight); } if (maximizeButton.Visible) { maximizeButton.SetBounds( currentMetrics.MaximizeButtonLeft, currentMetrics.SystemButtonTop, currentMetrics.SystemButtonWidth, currentMetrics.SystemButtonHeight); } if (minimizeButton.Visible) { minimizeButton.SetBounds( currentMetrics.MinimizeButtonLeft, currentMetrics.SystemButtonTop, currentMetrics.SystemButtonWidth, currentMetrics.SystemButtonHeight); } // Do a null-check in case this is called from our constructor, it may not yet been set. DockedAsControl?.SetBounds( currentMetrics.ClientAreaLeft, currentMetrics.ClientAreaTop, currentMetrics.ClientAreaWidth, currentMetrics.ClientAreaHeight); // Setting MinimumSize on an inactive Form will activate it. // To work around this issue, I tried delaying updates to MinimumSize until the window is active. // However, this prevents a window from being restored to a maximized state from an auto-save file, // even if e.g. a nonce is used. // // See also: // https://github.com/dotnet/winforms/issues/3020 // https://social.msdn.microsoft.com/Forums/en-US/9625570d-4bd7-48f2-b158-15dcbd96c60b/bug-in-form-class-setting-formminimumsize-triggers-an-activated-event-even-when-the-form-is // https://social.msdn.microsoft.com/Forums/en-US/31f9d493-f8d6-4b39-92c9-912399ed3964/why-parentformdeactivate-event-getting-triggered-when-try-to-set-the-minimum-size-for-child-form // // An appopriate MinimumSize is a size which allows the entire menu and the system buttons to be displayed, // taking border thickness into account. Using the current metrics: // // MinimumWidth = MainMenuLeft + MainMenuWidth + TotalWidth - MinimizeButtonLeft // MinimumHeight = CaptionHeight + VerticalResizeBorderThickness * 2 // MinimumSize = new Size(MinimumWidth, MinimumHeight) // // Setting MinimumSize to a fixed size for the time being, since a likely fix is going to be to trap // the property getters and setters, and reimplementing what they do by hand. MinimumSize = new Size(500, 80); // Update maximize button because Aero snap changes the client size directly and updates // the window state, but does not seem to call WndProc with e.g. a WM_SYSCOMMAND. UpdateMaximizeButtonIcon(); }