Search This Blog

Control Anchoring Class

Controls in Windows Forms are arranged on main form using a couple of properties, and one of them is Location property which is described on msdn as "Gets or sets the coordinates of the upper-left corner of the control relative to the upper-left corner of its container."


This means that Location property is used to position a control within its direct parent container.
So if we have two controls [let's say buttons] in a groupbox control which in it turn is hosted in a Windows Form, setting the location of one button in relation to the other will be simply by updating the location of the control we want to position in relation to the location of the button considered as a target.


Things will get difficult if we want to set the position of a Form in relation to a control within another form, for example positioning a new Form in relation to our previous buttons will not be a simple location calculation in relation to the button Location property. We have to set the new Form position in relation to the outermost control that contains the button.


Let's consider the following diagram:




If we want to position a new Form in relation to button1 than we follow this process:


Calculate the position [Location ] of button1 in relation to the containing form [Main Form].
Button1 Location in relation to GroupBox is [X=70, Y=150],
Groupbox location in relation to Main Form is: [X=40, Y=50]
Summing both locations will give:
Button1 location in relation to Main Form : [X= 110, Y= 200]


But the new form is not contained in Main Form than is has to be positioned against computer screen coordinates.


Main Form has the following position: [X=110, Y= 200].
If we want to Set the new Form position at the same point to button1 than we have to Sum up the Main Form coordinates and those of Button1 in relation to Main Form.


the finale position for the new Form will be: 
Location = [X=110+110 , Y = 200+200] or [X=220,400]


Here after is the a utility Class that I wrote which can be used to position controls within a form or position a new form against any control in a Form.


public enum AnchorPoint
{
    TopLeft,

    TopRight,
    BottomLeft,
    BottomRight
}









public class ControlAnchorer
{
    /// Summary: Anchors a control to a reference control.
    /// controlToAnchorControl to anchor

    /// controlReference: Reference control
    /// anchorPoint: the corner of the reference control to which the 
    /// controlToAnchor will be positioned
    public static void AnchorControl(Control controlToAnchor, Control controlReference,
        AnchorPoint anchorPoint)
    {
        if (controlToAnchor == null)
            throw new ArgumentNullException("controlToAnchor");

        if (controlReference == null)
            throw new ArgumentNullException("controlReference");

        if (controlToAnchor is Form)
        {
            // Make sure to set start postion to manual to be able to set the form location.
            ((Form)controlToAnchor).StartPosition = FormStartPosition.Manual;
        }

        Point location = Point.Empty;


        // A top level control will be positioned related to Screen coordinates.
        if (IsTopLevelCotrol(controlToAnchor))
        {
            Control topLevelControl = controlReference.TopLevelControl;
            if (topLevelControl == null)
                topLevelControl = controlReference;

            Point LocationToTopLevelControl = GetPositionInForm(controlReference);
            location = topLevelControl.PointToScreen(LocationToTopLevelControl);
        }
        else
        {
            if (controlToAnchor.Parent != controlReference.Parent)
            {
                throw new InvalidOperationException("Can't anchor controls belonging to different containers");
            }
            else
            {
                location = controlReference.Location;
            }
        }

        if (location != Point.Empty)
        {
            switch (anchorPoint)
            {
                case AnchorPoint.TopLeft:
                    break;

                case AnchorPoint.TopRight:
                    location.X += controlReference.Width;
                    break;

                case AnchorPoint.BottomLeft:
                    location.Y += controlReference.Height;
                    break;

                case AnchorPoint.BottomRight:
                    location.X += controlReference.Width;
                    location.Y += controlReference.Height;
                    break;

                default:
                    break;
            }

            controlToAnchor.Location = location;
        }

    }

    Returns the coordonates of a control in reference to the outermost control. 
    Example if a main form contains a group box, and the groupbox contains a button, calling this 
    method will return the coordinate of the button in reference to the main form.
    private static Point GetPositionInForm(Control control)
    {
        Point p = control.Location;
        Control parent = control.Parent;
        while ((parent != control.TopLevelControl))
        {
            p.Offset(parent.Location.X, parent.Location.Y);
            parent = parent.Parent;
        }
        return p;
    }


    
    Returns a boolean indicating if this is a Top level control such as a main Form control
    private static bool IsTopLevelCotrol(Control control)
    {
        bool isTopLevel = true;

        if (control == null)
        {
            isTopLevel = false;
        }
        else if (control.TopLevelControl != control)
        {
            isTopLevel = false;
        }
        return isTopLevel;
    }
}


No comments:

Post a Comment