簡體   English   中英

如何在C#中以編程方式使一堆控件居中

[英]How to center a bunch of controls programmatically in c#

我是這個社區的新手,並且我有這個應用程序可以通過編程添加控件。 我想將所有添加的控件居中,就像選擇它們並在Visual Studio上按center一樣。 不,我不想將每個人都放在一旁。 這是我用來獲取所有控件的代碼:

    private void GetAllControl(Control c, List<Control> list)
    {
        //gets all controls and saves them to a list
        foreach (Control control in c.Controls)
        {
            list.Add(control);
        }
    }

    //And then call it like this

        List<Control> list = new List<Control>();
        GetAllControl(PNL_custom, list);
        foreach (Play_panel m in list)
        {
            //And here I want to insert that center code
        }

提前致謝,

VBTheory

“而且不,我不想將每個人都放在一邊。”

因此,您想“對齊”控件列表嗎?...如下所示:

格式->對齊->居中

格式->對齊->中線

如果是,則計算每個控件的中心並求和X,Y坐標,以便您可以計算“平均”點(質心)。 現在,您可以遍歷控件並將其用作對齊的X或Y值,具體取決於所需的方向。 只需減去寬度或高度的一半,並保持其他值即可。

就像是:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        List<Control> list = new List<Control>();
        GetAllControl(PNL_custom, list);
        CenterControls(list, Direction.Vertical);
    }

    public enum Direction
    {
        Vertical,
        Horizontal
    }

    private void CenterControls(List<Control> controls, Direction direction)
    {
        if (controls.Count > 1)
        {
            int xSum = 0;
            int ySum = 0;
            Point center;
            foreach (Control ctl in controls)
            {
                center = new Point(ctl.Location.X + ctl.Width / 2, ctl.Location.Y + ctl.Height / 2);
                xSum = xSum + center.X;
                ySum = ySum + center.Y;
            }
            Point average = new Point(xSum / controls.Count, ySum / controls.Count);
            foreach (Control ctl in controls)
            {
                switch (direction)
                {
                    case Direction.Vertical:
                        ctl.Location = new Point(average.X - ctl.Width / 2, ctl.Location.Y);
                        break;

                    case Direction.Horizontal:
                        ctl.Location = new Point(ctl.Location.X, average.Y - ctl.Height / 2);
                        break;
                }
            }
        }
    }

    private void GetAllControl(Control c, List<Control> list)
    {
        //gets all controls and saves them to a list
        foreach (Control control in c.Controls)
        {
            list.Add(control);
        }
    }
}

這是將控件作為GROUP居中的方法。 它與以前幾乎相同,只是我們計算出該組的質心必須移動多遠才能成為父控件的中心。 然后,我們遍歷所有控件,並將它們的位置偏移那么多。 這使它們全部居中,同時保持彼此之間的相對位置:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        List<Control> list = new List<Control>();
        GetAllControl(PNL_custom, list);
        CenterControlsAsGroup(list, Direction.Both); // center group in the center of the parent
    }

    public enum Direction
    {
        Vertical,
        Horizontal,
        Both
    }

    private void CenterControlsAsGroup(List<Control> controls, Direction direction)
    {
        if (controls.Count > 1)
        {
            int xSum = 0;
            int ySum = 0;
            Point center;
            foreach (Control ctl in controls)
            {
                center = new Point(ctl.Location.X + ctl.Width / 2, ctl.Location.Y + ctl.Height / 2);
                xSum = xSum + center.X;
                ySum = ySum + center.Y;
            }
            Point average = new Point(xSum / controls.Count, ySum / controls.Count);

            center = new Point(controls[0].Parent.Width / 2, controls[0].Parent.Height / 2);
            int xOffset = center.X - average.X;
            int yOffset = center.Y - average.Y;

            foreach (Control ctl in controls)
            {
                switch (direction)
                {
                    case Direction.Vertical:
                        ctl.Location = new Point(ctl.Location.X + xOffset, ctl.Location.Y);
                        break;

                    case Direction.Horizontal:
                        ctl.Location = new Point(ctl.Location.X, ctl.Location.Y + yOffset);
                        break;

                    case Direction.Both:
                        ctl.Location = new Point(ctl.Location.X + xOffset, ctl.Location.Y + yOffset);
                        break;
                }
            }
        }
    }

    private void GetAllControl(Control c, List<Control> list)
    {
        //gets all controls and saves them to a list
        foreach (Control control in c.Controls)
        {
            list.Add(control);
        }
    }

}

獲取控件的容器的寬度和高度(可以是另一個控件或窗體)。 控件的坐標是以像素為單位的相對於其容器左上角的距離(即(0,0))。 因此,您要做的就是將控件的x坐標設置為(form width - control width) / 2 高度也一樣。

盡管所有控件都可以輕松地放在組框等中,但它們將被添加到容器(最有可能是窗體)中。

為了使它們在容器內居中對齊,您需要做一些數學運算並自己放置它們:)

在將控件置於容器中心之前,您需要找到容器的中點。 這將是容器的寬度/ 2:容器的高度/ 2。

我將使用一個名為cmdButton1的控件來突出顯示-您將要遍歷控件列表,然后依次對所有控件進行此操作。

int midParentX = cmdButton1.Parent.width / 2;
int midParentX = cmdButton1.Parent.height / 2;

然后,您可以將控件放置在此中點:

cmdButton1.Location.X = midParentX;
cmdButton1.Location.Y = midParentY;

但是,您的控件(在我的示例中為cmdButton)固定在控件的左上角(0,0)上,因此我們需要將其上下移動一半的寬度和高度

cmdButton1.Location.X -= (cmdButton1.width / 2);
cmdButton1.Location.Y -= (cmdButton1.height / 2);

更加相關:

foreach (Play_panel m in list)
{
    int pX = m.Parent.width;
    int pY = m.Parent.height;

    m.Location.X = (pX / 2) - (m.width / 2);
    m.Location.Y = (pY / 2) - (m.height / 2);
}

所以我以這種方式做到了:

    public enum ArrangeOrientation : int {
        None,
        Horizonatal,
        Vertical,
        HorizontalGrid,
        VerticalGrid,
        TopLeftGrid,
        TopRightGrid,
        BottomLeftGrid,
        BottomRightGrid
    }

    private void ArrangeButtons(List<Control> controls, List<Control> parents, ArrangeOrientation orientation, double shrinkFactor = 1d) {
        if(controls == null) return;
        if(parents == null) parents = new List<Control>();
        List<Control> childs = new List<Control>();
        Control parent = null;

        foreach(Control ctrl in controls) {
            if(parent == null && !parents.Contains(ctrl.Parent)) {
                parents.Add(ctrl.Parent);
                parent = ctrl.Parent;
            }
            if(parent == ctrl.Parent)
                childs.Add(ctrl);
        }
        if(parent != null && childs.Count > 0) {
            ArrangeControlsToGridLayout(childs, orientation, shrinkFactor);
            ArrangeButtons(controls, parents, orientation, shrinkFactor);
        }
    }

    private void ArrangeControlsToGridLayout(List<Control> controls, ArrangeOrientation orientation, double shrinkFactor = 1d) {
        // do nothing if nothing set
        if(orientation == ArrangeOrientation.None) return;
        if(shrinkFactor == 0d|| shrinkFactor > 1d) shrinkFactor = 1d;

        // buffer controls in separate list to avoid manipulating parameter
        List<Control> ctrl = new List<Control>(controls.ToArray());
        // remove invisible controls
        int j = 0;
        while(j < ctrl.Count) {
            if(!ctrl[j].Visible) ctrl.RemoveAt(j);
            else j++;
        }

        // loop arrangement
        int count = ctrl.Count;
        int xDelta, yDelta, xOffs, yOffs, y, x, columns, rows, parentWidth, parentHeight, xShrinkOffs, yShrinkOffs;
        if(count >= 1) {

            // parents size
            parentWidth = ctrl[0].Parent.Width;
            parentHeight = ctrl[0].Parent.Height;
            // shrink factor offset
            parentWidth = Convert.ToInt32(parentWidth * shrinkFactor);
            parentHeight = Convert.ToInt32(parentHeight * shrinkFactor);
            // shrink factor offset
            xShrinkOffs = Convert.ToInt32((ctrl[0].Parent.Width - parentWidth) / 2d);
            yShrinkOffs = Convert.ToInt32((ctrl[0].Parent.Height - parentHeight) / 2d);

            // calculate columns rows grid layout                            
            if(orientation == ArrangeOrientation.Horizonatal) {
                rows = 1;
                columns = count;
            }
            else if(orientation == ArrangeOrientation.Vertical) {
                rows = count;
                columns = 1;
            }
            else if(orientation == ArrangeOrientation.TopLeftGrid
                || orientation == ArrangeOrientation.TopRightGrid
                || orientation == ArrangeOrientation.BottomLeftGrid
                || orientation == ArrangeOrientation.BottomRightGrid) {
                rows = 1;
                columns = count;
            }
            else {
                rows = Convert.ToInt32(Math.Floor(Math.Sqrt(count)));
                if(Math.Sqrt(count) % 1d != 0d) rows++;
                columns = count / rows + (count % rows != 0 ? 1 : 0);
            }
            if(orientation == ArrangeOrientation.HorizontalGrid) {
                int swap = columns;
                columns = rows;
                rows = columns;
            }

            // calculate position offsets, grid distance
            xDelta = parentWidth / count;
            yDelta = parentHeight / count;
            xOffs = xDelta / 2;
            yOffs = yDelta / 2;                
            if(orientation == ArrangeOrientation.TopLeftGrid) {                                                     
            }
            else if(orientation == ArrangeOrientation.TopRightGrid) {
                xOffs = parentWidth - xOffs;
                xDelta = -xDelta;
            }
            else if(orientation == ArrangeOrientation.BottomLeftGrid) {
                yOffs = parentHeight - yOffs;
                yDelta = -yDelta;
            }
            else if(orientation == ArrangeOrientation.BottomRightGrid) {
                xOffs = parentWidth - xOffs;
                yOffs = parentHeight - yOffs;
                xDelta = -xDelta;
                yDelta = -yDelta;
            }
            else {
                xDelta = parentWidth / columns;
                yDelta = parentHeight / rows;
                xOffs = xDelta / 2;
                yOffs = yDelta / 2;
            }

            // fit controls in grid layout               
            Point pRoot = new Point(/*ctrl[0].Parent.Location.X + */xOffs, /*ctrl[0].Parent.Location.Y + */yOffs);
            y = 0; x = 0;
            for(int i = 0; i < count; i++) {

                if(orientation == ArrangeOrientation.VerticalGrid) {
                    // actual x/y - points zero based index
                    y = Convert.ToInt32(Math.Floor((double)i % rows));
                    // next row? zero based index
                    if(i % rows == 0 && i != 0) x++;
                }
                else {
                    // actual x/y - points zero based index
                    x = Convert.ToInt32(Math.Floor((double)i % columns));
                    // next row? zero based index
                    if(i % columns == 0 && i != 0) y++;
                    if(orientation == ArrangeOrientation.TopLeftGrid
                        || orientation == ArrangeOrientation.TopRightGrid
                        || orientation == ArrangeOrientation.BottomLeftGrid
                        || orientation == ArrangeOrientation.BottomRightGrid)
                        y = x;
                }                   // assign controls to grid
                ctrl[i].Location = new Point(pRoot.X + x * xDelta - ctrl[i].Size.Width / 2 + xShrinkOffs, pRoot.Y + y * yDelta - ctrl[i].Size.Height / 2 + yShrinkOffs);

            }
        }
    }

當有多個控件時,上面的代碼將所有控件都放在另一個控件上。

我要做的就是將所有控件居中放置在面板中,但是將它們並排放置而不是一個放置在另一個放置上。

這是我修改的代碼(僅供參考,這會將控件集中在1行而不是多行中):

   public enum Direction
    {
        Vertical,
        Horizontal,
        Both
    }

    public void CenterControls(List<Control> controls, Direction direction)
    {
        if (controls.Count > 1)
        {
             int controls_sum_width = 0;
            int controls_seperation = 20;
            int parentwidth = 0;               

            Point center;
            foreach (Control ctl in controls)
            {
                 controls_sum_width = controls_sum_width + ctl.Width + controls_seperation;
            }

            Point Container_center = new Point(controls[0].Parent.Width / 2, controls[0].Parent.Height / 2);
            parentwidth = controls[0].Parent.Width;
            int xoffset = (parentwidth - controls_sum_width) / 2;


            int Location_X = 0;
            foreach (Control ctl in controls)
            {
                center = new Point( ctl.Width / 2,  ctl.Height / 2);
                int yOffset = Container_center.Y - center.Y;
                switch (direction)
                {
                    case Direction.Vertical:
                        ctl.Location = new Point(ctl.Location.X + xoffset, ctl.Location.Y);
                        break;

                    case Direction.Horizontal:
                        ctl.Location = new Point(ctl.Location.X, yOffset);
                        break;

                    case Direction.Both:
                        ctl.Location = new Point(Location_X + xoffset,  yOffset);
                        break;
                }
                Location_X = Location_X + ctl.Width+ controls_seperation;
            }
        }
        else
        {
            Point parent_center;
            Point center;
            parent_center = new Point(controls[0].Parent.Width / 2, controls[0].Parent.Height / 2);
            center = new Point(controls[0].Location.X + controls[0].Width / 2, controls[0].Location.Y + controls[0].Height / 2);
            int xOffset = parent_center.X - center.X;
            int yOffset = parent_center.Y - center.Y;
            switch (direction)
            {
                case Direction.Vertical:
                    controls[0].Location = new Point(controls[0].Location.X + xOffset, controls[0].Location.Y);
                    break;

                case Direction.Horizontal:
                    controls[0].Location = new Point(controls[0].Location.X, controls[0].Location.Y + yOffset);
                    break;

                case Direction.Both:
                    controls[0].Location = new Point(controls[0].Location.X + xOffset, controls[0].Location.Y + yOffset);
                    break;
            }
        }
    }

    public void GetAllControl(Control c, List<Control> list)
    {
        //gets all controls and saves them to a list
        foreach (Control control in c.Controls)
        {
            list.Add(control);
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM