【问题标题】:How to center a bunch of controls programmatically in c#如何在 C# 中以编程方式将一堆控件居中
【发布时间】:2013-05-10 12:17:33
【问题描述】:

我是这个社区的新手,我有这个以编程方式添加控件的应用程序。 我想将所有添加的控件居中,就像选择它们并在 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
        }

提前致谢,

VB理论

【问题讨论】:

  • 这是一个 WinForms 桌面应用程序吗?
  • 如果您提供一个标签,例如 WinForms 或 WPF 或 ASP.Net,它可以帮助您吸引那些可以提供帮助的人的注意力。
  • 这个问题是相关的stackoverflow.com/questions/2855435/…
  • “不,我不想把每一个都放在一边。”所以你想让 Format --> Align --> Centers 和/或 Format --> Align --> Middles 在控件列表上工作?
  • 不,我的意思是选择控件 --> 格式 --> 在表单中居中 --> 水平并选择控件 --> 格式 --> 在表单中居中 --> 在运行时垂直跨度>

标签: c# winforms visual-studio


【解决方案1】:

以下是如何将控件作为 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);
        }
    }

}

【讨论】:

  • 天啊,我永远感激不尽。非常感谢你,兄弟
  • 很高兴为您工作。请随意投票和/或单击复选标记,以便其他人知道问题已解决...
  • 不,对不起,我只是在尝试勾选,我不小心取消了你的答案。它就像一个魅力,非常感谢你:)
【解决方案2】:

“不,我不想把每一个都放在一边。”

所以你想“对齐”控件列表?...如:

格式 --> 对齐 --> 居中

格式 --> 对齐 --> 中间

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

【讨论】:

  • 非常感谢,但这只是将每个控件单独居中,我想要的只是将它们居中以保持彼此之间的距离
【解决方案3】:

获取控件容器(另一个控件或窗体)的宽度和高度。控件的坐标是以像素为单位的距离,相对于其容器的左上角(即 (0,0))。因此,您只需将控件的x 坐标设置为(form width - control width) / 2。身高也是一样。

【讨论】:

  • 能否说的更具体些
  • 容器的左上角是坐标系中的 (0, 0) 点。坐标值向右和向下增长。您可能想查看location 属性。所以你可以做类似m.Location.X = (m.Parent.Width - m.Width) / 2 的事情来水平居中。用Y 代替XHeight 代替Width 你也已经垂直居中了。
【解决方案4】:

您的所有控件都将被添加到一个容器(很可能是表单)中,尽管它们可以很容易地放在一个组框等中。

要将它们在容器内居中对齐,您需要做一些数学运算并自己定位它们:)

在将控件置于容器中心之前,您需要找到容器的中点。这将是容器的宽度/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);
}

【讨论】:

    【解决方案5】:

    所以我就这样做了:

        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);
    
                }
            }
        }
    

    【讨论】:

      【解决方案6】:

      当有多个控件时,上面的代码是将所有控件放在一起。

      我要做的就是将所有控件集中在一个面板中,但将它们彼此相邻放置,而不是将它们放在另一个之上。

      这是我修改后的代码(仅供参考,这会将控件集中在 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);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2020-05-21
        • 1970-01-01
        • 2012-01-23
        • 2012-02-13
        • 1970-01-01
        • 1970-01-01
        • 2019-02-02
        • 1970-01-01
        • 2011-03-25
        相关资源
        最近更新 更多