C#, Windows Forms, Best/min fit window to contents


I have a form with some controls. (Actually, this is a sort of ongoing problem.) Some of the forms I have had are resizable, some are not. Regardless, when the form is displayed, it would be nice to have it appear in the "minimum" size needed. Other Windowing toolkits, such as wxWidgets (wxWindow::GetMinSize) and Qt (QWidget::minimumSize) have this functionality.

This functionality, if you are not familiar with it, allows a window to resize itself to a minimum size, which is often all the window needs, and looks quite nice. If I have two static texts, and two edit boxes laid out thusly:

[ Edit/text box for user's password]
[ Edit/text box for user's password]
              [  Cancel  ][   OK   ]

I can then tell this form to size itself to it's "minimum size", and it would appear much like above. (Minimum width in a text box is partly subjective – I would have to set that myself in one/both of the text boxes, but the form would query the child controls and learn of that minimum width)
This is usually combined with layouts of some sort. (Which .Net has.)

This has the added benefit that the form is the correct size regardless of font settings, locale, dpi, gui skin, etc. (If done right, at least.)

Does this exist in .Net, and if so, where? If you need any more description, ask, and I'll be glad to provide.

Edit: What I'm looking for is the above example, resizable only in the X direction (I'm willing to accept both) but can't be resized smaller than a certain W/H. The controls should anchor – ie, the text boxes get bigger, the buttons stay right aligned.

Edit: I can do images! Supposedly they're worth a thousand words:
alt text http://www.freeimagehosting.net/uploads/79e9ee10e5.png

Edit: I guess I'm going to start marking answers. Henk's answer has gotten me pretty far with a non-resizable dialog that fits to it's contents. Most of the posts below are valuable, but miss the point (unless I'm really off base here?): I understand how to use Anchor/TableLayout, and to get controls to flow there – it was mostly getting one or both dimensions of the dialog to fit to the contents of the dialog. You essentially have three cases:

  1. The dialog is not resizable – See Henk's answer. Combined with TableLayout and Anchors, you'll get a decent dialog.

  2. The dialog is only resizable in one dimension – Go with 1 or 3 – You can constrain a dimension by using the Resize event, but the dialog flickers horribly. (This seems to be a defect in Win32 as far as I can tell – there is some stuff out there about overriding the background erase, which works for controls, but not windows, as you'll get artifacts in the form's background (because you're not erasing them). The real answer is that this should probably be handled by Win32 itself – I should not have to reinvent the double-buffer wheel just to get a decent look dialog…))

  3. The dialog is fully resizable. Anchors and TableLayout are your friend. Unfortunately, the MinimumSize attribute seems to be bogus (at least, I don't know what it is for…) – for example, if you query the MinimumSize of a textbox, by default the height is 4 pixels. Further, the MinimumSize property doesn't seem to propogate – a control does not query it's children. (I can resize the form smaller than the textbox within the form, and the textbox is then off the form.) If you wonder what I'm babbling about, see wxWidgets and how layouts and minimum size work for it.

I've also since discovered that .Net does not seem to respect the system font, and always uses the same font for Forms, so font changes won't affect my dialog (sadly) which alieviates most of my worries (happily?). Again, refer to how wxWidgets does it – if the system font is 22pt, all wxFrames (forms) respect and resize appropriately. .Net should get onboard this train… (And I know someone who uses 22+pt font day-to-day for their standard GUI font.)

Best Solution

There is something that comes close, try the following: design your Form a bit large and avoid Right and Bottom docked controls. Then some code like this:

private void button1_Click(object sender, EventArgs e)
    this.AutoSize = true;
    this.Size = new Size(10, 10);

The AutoSize will find the extend of the Controls.