How to set a minimum Size of a Form's Client Area.
The Form.MinimumSize
property sets the minimum size of the Form as a whole, including the current borders, the Caption and the subtle internal padding that is applied when the Form is resized and a new Layout is performed (many factors determine this activity).
It may be imperceptible, because it's fast (and, usually, nobody cares), but the relation between the Form Size and the Client Size is not constant. It can change when the Form is resized, dragging its borders. Or a System event causes this to happen.
Plus, changing the System settings, in many departments (the properties of the Windows, the Theme, Dpi, Font size etc.), can determine a change in the relations between the Form size and the size of its client area.
The good thing is that the Form is aware of these changes and, when notified of a System event that alters the aspect of Windows in some way, re-performs its layout.
When this happens (and it can happen frequently, always when a Form is resized), the OnLayout method is called.
Overriding OnLayout, allows to update values that rely on the Window/Client area measures.
? It can be interesting to see what happens when System settings,
affecting the aspect of the Windows, are changed while the application
is running. In this specific context, how many times the OnLayout
method is called and what the LayoutEventArgs properties are set
to.
This all considered, we can create a public MinimumClientSize
Property.
We override OnLayout
and reset the Form.MinimumSize
to the new Form.MinimumClientSize
plus the difference between the Form.Size
and the Form.ClientSize
.
For example, if we need to keep the Client Area size to a minimum of (500, 500)
:
private Size m_MinimumClientSize = new Size(500, 500);
public Size MinimumClientSize {
get => m_MinimumClientSize;
set { m_MinimumClientSize = value;
PerformLayout();
}
}
protected override void OnLayout(LayoutEventArgs e) {
base.OnLayout(e);
MinimumSize = m_MinimumClientSize + (Size - ClientSize);
}
If we add to the OnLayout
method:
Console.WriteLine($"ClientSize: {ClientSize}");
Console.WriteLine($"MinimumSize: {MinimumSize}");
Console.WriteLine($"Size: {Size}");
it becomes clear that the relation between Form.Size
and Form.ClientSize
is not always the same.
We could also calculate the difference between Size and ClientSize this way:
var borderSize = new Size(
(SystemInformation.FrameBorderSize.Width * SystemInformation.BorderMultiplierFactor
+ (SystemInformation.Border3DSize.Width * 2)) * 2,
(SystemInformation.FrameBorderSize.Height * SystemInformation.BorderMultiplierFactor
+ (SystemInformation.Border3DSize.Height * 2)) * 2);
var captionSize = new Size(0, SystemInformation.CaptionHeight);
MinimumSize = MinimumClientSize + borderSize + captionSize;
These fixed measures are correct. In normal situations, they provides the same values.
Not always, though. Never, when a Form is resized to its MinimumSize.
Plus, we're only considering a Form with a 3d Border.
Well, we could also override WndProc
...