如何在c#中以编程方式居中一堆控件

本文关键字:控件 一堆 编程 方式居 | 更新日期: 2023-09-27 18:12:55

我对这个社区很陌生,我有这个应用程序,以编程方式添加控件。我想把所有添加的控件居中,就像在Visual Studio上选择它们并按居中键一样。不,我不想把它们都放在一边。下面是我用来获取所有控件的代码:

    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

如何在c#中以编程方式居中一堆控件

如何将控件居中作为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);
        }
    }
}

"不,我不想把它们放在中间。"

所以你想"对齐"控件列表?如:

Format -> Align ->居中

Format -> Align ->居中

如果是,那么计算每个控件的中心并将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);
        }
    }
}

获取控件的容器(可以是另一个控件或窗体)的宽度和高度。控件的坐标是以像素为单位的距离,相对于其容器的左上角(即(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);
        }
    }