Dock & Anchor

IronPython & Windows Forms, Part VII

Windows Forms

Note

This is part of a series of tutorials on using IronPython with Windows Forms.

 

 

Introduction

In the past entries in this series we have setup a basic Windows Forms application and laid out the widgets in it manually. Although we have covered the container widget the Panel, we have still positioned widgets by specifying the location using pixels.

This isn't very satisfactory, particularly if your top level form has to cope with being resizeable.

Windows Forms provides two ways of overcoming this problem, using concepts which ought to be familiar to anyone who has programmed using other GUI toolkits. These two techniques use the Dock and Anchor properties of controls. There are also several container widgets which support other layout styles, but for this entry we are looking at Anchor and DockStyle.

The Anchor Property

Most Windows Forms controls have an Anchor Property. This property can be set using the AnchorStyles Enumeration on the child control (not the parent).

Anchor preserves the distance of the control to the edge you anchor it to, even if the form resizes. You can use a bitwise or (| operator) of the various enumeration members to anchor a control to more than one edge. The different values are :

  • AnchorStyles.Bottom
  • AnchorStyles.Left
  • AnchorStyles.None
  • AnchorStyles.Right
  • AnchorStyles.Top

Of note is what happens if AnchorStyles.None is used :

If a control has its Anchor property set to AnchorStyles.None, the control moves half of the distance that the container of the control is resized. For example, if a Button has its Anchor property set to AnchorStyles.None and the Form that the control is located on is resized by 20 pixels in either direction, the button will be moved 10 pixels in both directions.

You may think that None would be the default value for Anchor. This isn't quite the case. In the past we've positioned widgets [1] using the Location Property. This positions the widget relative to the top left origin. Effectively this is the same as anchoring the widget to the left and the top. Resizing the form causes the widget to retain its position relative to the top-left of the form (or its parent container).

There is an alternative way to achieve the same thing. These are the following two properties, again available on most controls :

control.Top = 10
control.Left = 10

is exactly the same as :

control.Location = Point(10, 10)

The advantage of the former is that you don't need to construct a Point. Smile

Ok, enough of the waffle. Time for a simple example that shows what happens if you anchor a widget to all four sides of a form and resize.

import clr
clr.AddReference('System.Windows.Forms')

from System.Windows.Forms import AnchorStyles, Application, Form, Button

class MainForm(Form):
    def __init__(self):
        btn = Button()
        btn.Text = "Dummy Button"
        btn.Width = 100
        btn.Top = 10
        btn.Left = 10
        print btn.Anchor
        btn.Anchor = (AnchorStyles.Left | AnchorStyles.Right |
                      AnchorStyles.Bottom | AnchorStyles.Top)
        self.Controls.Add(btn)


Application.EnableVisualStyles()
form = MainForm()
Application.Run(form)

Hmm... I've cheated here and introduced a new concept. Application.EnableVisualStyles() is a .NET thing. It has no effect if the operating system in use doesn't support visual styles, but if they are available it causes controls to draw themselves using the current style.

Minor digression over, if you run this code you will see a simple form with a button on it. Try reszing the form and see what happens. Additionally you will see Top, Left printed to the console. This is the value of Anchor after we have positioned the button.

For those who are curious, here are screenshots of the form when we run the example above :

Initial Appearance

and after a resize :

After a Resize

On Mono [2] it looks like :

Initial Appearance on Mono

The Dock Property

The Dock property is set using a DockStyle Enumeration. Unlike AnchorStyles the members can't be combined. Additionally you can't use Dock and Anchor, you have to choose one or the other.

Possible values are :

  • Bottom - The control's bottom edge is docked to the bottom of its containing control.
  • Fill - All the control's edges are docked to the all edges of its containing control and sized appropriately.
  • Left - The control's left edge is docked to the left edge of its containing control.
  • None - The control is not docked.
  • Right - The control's right edge is docked to the right edge of its containing control.
  • Top - The control's top edge is docked to the top of its containing control.

If you use the Dock property the control will be located flush against the side you have docked it to.

DockStyle.Fill is obviously useful. Another way to use this property is to line widgets up by repeatedly docking them to the same side. Below is an example of using DockStyle.Top to put several buttons in a vertical line on a form.

import clr
clr.AddReference('System.Windows.Forms')

from System.Windows.Forms import Application, Form, Button, DockStyle

class MainForm(Form):
    def __init__(self):
        for i in range(1, 6):
            btn = Button()
            btn.Text = "Button %s" % i
            btn.Dock = DockStyle.Top
            self.Controls.Add(btn)


Application.EnableVisualStyles()
form = MainForm()
Application.Run(form)

Here's what it looks like :

DockStyle Example

On Mono it looks like :

DockStyle on Mono

The usual way to layout a complex GUI is to group controls using containers. You arrange the controls within the containers using Dock and Anchor and also arrange the containers in your form using Dock and Anchor.

The Z-Order

It's important to remember that when you layout controls using the Dock property, the order you add controls is important. This is called the Z-order. It gets it's name because it corresponds to the z-axis. The controls you add first come first in the Z-order.

If you first dock a control to the left of its parent control and then add a control using DockStyle.Fill, the second control will occupy all the space not taken up by the first. If you add a control with DockStyle.Fill first, then the second control won't be visible.

You can always call the BringToFront method of a control to bring it to the front of the Z-order.

Conclusion

This entry has been short (about time), but hopefully it has shown you how to use the Dock and Anchor properties to layout a simple GUI. A bit of experimentation may be needed to get the look right. Smile

Having covered the basics, including a few standard controls, it's time to use what we know with some more interesting controls and use events to program some more sophisticated behaviour.

[1]Widget is the generic word for what is called a Control terminology. I use them irrationally and interchangeably. Smile
[2]Mono screenshots provided by Mark Rees, under Ubuntu 6.06 with Mono 1.1.16.1.

For buying techie books, science fiction, computer hardware or the latest gadgets: visit The Voidspace Amazon Store.

Hosted by Webfaction

Return to Top

Page rendered with rest2web the Site Builder

Last edited Fri Nov 27 18:32:35 2009.

Counter...