简体   繁体   中英

Resizing User Control - anchor controls to center of form

I have a user control which consists of two controls and four buttons, arranged on a Form: the two controls are on the sides and the buttons in the middle in a vertical row.

When using the control in an app, I place it on a form.

Now, when re-sizing the form horizontally, the two controls just move left or right w/o changing their size.

What I need is that the controls stay anchored to the middle of the form and grow to the sides (sorry about the lack of clarity, I prepared screenshots but the site wouldn't let me attach them).

Is there a way to accomplish this without overriding the Resize event?

Use a TableLayoutPanel as base for your user control.
You need 3 columns and one row. The middle column needs to have a fixed size, and the other 2 you set to 50%. Not to worry, .Net is smart enough to calculate the percent they actually take.
Inside the right and left columns you put your controls and set the Dock property of both to fill . In the middle column you put a panel and set it's Dock property to fill as wall, and In that panel you put the buttons in the middle.
Set your table layout panel Dock to fill as well, and when adding the user control to the form use Dock top , bottom or fill as well.

It seems indeed that it cannot be done in the Designer, but here is the solution using overrides. It works ok, except for some control flickering which I haven't been able to overcome.

public partial class SB : UserControl
{
    //variables to remember sizes and locations
    Size parentSize = new Size(0,0);
    Point parentLocation = new Point (0,0);
    ......
    // we care only for horizontal changes by dragging the left border;
    // all others take care of themselves by Designer code
    public void SB_Resize(object sender, EventArgs e)
    {
        if (this.Parent == null)
            return;//we are still in the load process

        // get former values
        int fcsw = this.parentSize.Width;//former width
        int fclx = this.parentLocation.X;//former location

        Control control = (Control)sender;//this is our custom control

        // get present values
        int csw = control.Parent.Size.Width;//present width
        int clx = control.Parent.Location.X;//present location

        // both parent width and parent location have changed: it means we 
        // dragged the left border or one of the left corners
        if (csw != fcsw && clx != fclx)
        {
            int delta = clx - fclx;
            int lw = (int)this.tableLayoutPanel1.ColumnStyles[0].Width;
            int nlw = lw - delta;
            if (nlw > 0)
            {
                this.tableLayoutPanel1.ColumnStyles[0].Width -= delta;
            }
        }
        this.parentSize = control.Parent.Size;//always update it
        this.parentLocation = control.Parent.Location;
    }

    //contrary to documentation, the Resize event is not raised by moving
    //the form, so we have to override the Move event too, to update the
    //saved location
    private void SB_Move(object sender, EventArgs e)
    {
        if (this.Parent == null)
            return;//we are still in the load process
        this.parentSize = this.Parent.Size;//always update it
        this.parentLocation = this.Parent.Location;
    }
}

The above code works most of the time, but it fails for certain Move-Resize sequences. The solution is to respond to the Move and Resize events of the parent form (the consumer of the control), not of the control itself.

One more thing: due to the event firing order (Move first followed by Resize, had to move the working code from Resize() to Move(), which seems counterintuitive but it seems the right way nevertheless.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM