在C#可滚动容器

时间:2015-06-10 18:21:53

标签: c# winforms containers snapping

我有一组控件,我在可滚动控件内垂直堆叠。

每个控件都包含文本(如iPhone上的消息气泡),气泡会根据文本的高度调整大小。

我面临的问题是,当我调整父级的大小以使其更小时,气泡开始重叠,当我调整大小以使气泡为一行时,每个气泡之间的空间太大。

我想做的是让每个气泡将气泡顶部从气泡上方的气泡释放到10分钟,这是最快的方式,没有任何闪烁(因为目前调整大小时没有闪烁)

我已经考虑过将每个控件嵌入到另一个父控件中(例如,一个网格控件行),但是之后添加的每个泡泡都将负责调整其自身的父级,然后锚点将不再适用于它们的顶部,左侧,和正确的定位。

如何做到这一点? (对不起,问题的细节在上面,因为由于复杂性和具体细节,它无法真正用于简单的单线问题)

提前致谢:)

AS REQUESTED,SCREENSHOTS和CODE

这是正常观点 enter image description here 调整大小后,向下滚动到不在可见段中的控件 enter image description here 然后重新调整大小,然后向上滚动 enter image description here

现在好东西..... CODE .....

以下是我的自定义控件的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.InteropServices;

public class MessageControl : ScrollableControl {

    public List<Message> Messages { get; private set; }

    private Color _LeftBubbleColor=Color.FromArgb(217,217,217);
    private Color _RightBubbleColor=Color.FromArgb(192,206,215);
    private Color _LeftBubbleTextColor=Color.FromArgb(52,52,52);
    private Color _RightBubbleTextColor=Color.FromArgb( 52, 52, 52 );
    private bool _DrawArrow=true;
    private int _BubbleIndent=40;
    private int _BubbleSpacing=10;
    public enum BubblePositionEnum { Left, Right }

    public Color LeftBubbleColor { get { return _LeftBubbleColor; } set {_LeftBubbleColor = value; } }
    public Color RightBubbleColor { get { return _RightBubbleColor; } set { _RightBubbleColor=value; } }
    public Color LeftBubbleTextColor { get { return _LeftBubbleTextColor; } set { _LeftBubbleTextColor=value; } }
    public Color RightBubbleTextColor { get { return _RightBubbleTextColor; } set { _RightBubbleTextColor=value; } }
    public int BubbleIndent { get { return _BubbleIndent; } set { _BubbleIndent = value; } }
    public int BubbleSpacing { get { return _BubbleSpacing; } set { _BubbleSpacing=value; } }
    public bool DrawArrow { get { return _DrawArrow; } set { _DrawArrow = value; } }

    public MessageControl() {
        Messages = new List<Message>();
        SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
        DoubleBuffered=true;
        BackColor=Color.Orange;
        Anchor=AnchorStyles.Top|AnchorStyles.Left|AnchorStyles.Right|AnchorStyles.Bottom;
        AutoScroll=true;
    }

    public void Remove( Message message ) {
        this.Invalidate();
        Messages.Remove( message );
        RedrawControls();
    }

    public void Remove( Message[] messages ) {
        this.Invalidate();
        foreach ( Message m in messages ) {
            Messages.Remove( m );
        }
        RedrawControls();
    }

    public void Add( string Message, BubblePositionEnum Position ) {
        Message b = new Message(Position);

        if ( Messages.Count>0 ) {
            b.Top = Messages[Messages.Count-1].Top + Messages[Messages.Count-1].Height + _BubbleSpacing+AutoScrollPosition.Y;
        } else {
            b.Top = _BubbleSpacing+AutoScrollPosition.Y;
        }

        b.Text = Message;
        b.DrawBubbleArrow=_DrawArrow;

        if ( VerticalScroll.Visible ) {
            b.Width=Width-( _BubbleIndent+_BubbleSpacing+SystemInformation.VerticalScrollBarWidth );
        } else {
            b.Width=Width-( _BubbleIndent+_BubbleSpacing );
        }
        if ( Position==BubblePositionEnum.Right ) {
            b.Left = _BubbleIndent;
            b.BubbleColor = _RightBubbleColor;
            b.ForeColor = _RightBubbleTextColor;
        } else {
            b.Left = _BubbleSpacing;
            b.BubbleColor=_LeftBubbleColor;
            b.ForeColor=_LeftBubbleTextColor;
        }

        Messages.Add(b);
        this.Controls.Add(b);
    }

    protected override void OnResize( System.EventArgs e ) {
        RedrawControls();
        base.OnResize( e );
    }

    private void RedrawControls() {
        int count=0;
        Message last=null;
        int new_width=this.Width;
        SuspendLayout();
        foreach ( Message m in this.Controls ) {
            if ( count>0 ) {
                m.Top=last.Top+last.Height+_BubbleSpacing+AutoScrollPosition.Y;
                if ( VerticalScroll.Visible ) {
                    m.Width=new_width-( _BubbleIndent+_BubbleSpacing+SystemInformation.VerticalScrollBarWidth );
                } else {
                    m.Width=new_width-( _BubbleIndent+_BubbleSpacing );
                }
            }
            last=m;
            count++;
        }
        ResumeLayout();
        Invalidate();
    }

    public class Message : Control {
        private GraphicsPath Shape;
        private Color _TextColor=Color.FromArgb( 52, 52, 52 );
        private Color _BubbleColor=Color.FromArgb( 217, 217, 217 );
        private bool _DrawBubbleArrow=true;
        private BubblePositionEnum _BubblePosition = BubblePositionEnum.Left;

        public override Color ForeColor { get { return this._TextColor; } set { this._TextColor=value; this.Invalidate(); } }
        public BubblePositionEnum BubblePosition { get { return this._BubblePosition; } set { this._BubblePosition=value; this.Invalidate(); } }
        public Color BubbleColor { get { return this._BubbleColor; } set { this._BubbleColor=value; this.Invalidate(); } }
        public bool DrawBubbleArrow { get { return _DrawBubbleArrow; } set { _DrawBubbleArrow=value; Invalidate(); } }
        public Message(BubblePositionEnum Position) {
            _BubblePosition=Position;
            SetStyle( ControlStyles.AllPaintingInWmPaint|ControlStyles.OptimizedDoubleBuffer|ControlStyles.ResizeRedraw|ControlStyles.SupportsTransparentBackColor|ControlStyles.UserPaint, true );
            DoubleBuffered=true;
            Size=new Size( 152, 38 );
            BackColor=Color.Transparent;
            ForeColor=Color.FromArgb( 52, 52, 52 );
            Font=new Font( "Segoe UI", 10 );
            Anchor=AnchorStyles.Top|AnchorStyles.Left|AnchorStyles.Right;
        }

        protected override void OnResize( System.EventArgs e ) {
            Shape=new GraphicsPath();

            var _Shape=Shape;
            if ( BubblePosition==BubblePositionEnum.Left ) {
                _Shape.AddArc( 9, 0, 10, 10, 180, 90 );
                _Shape.AddArc( Width-11, 0, 10, 10, -90, 90 );
                _Shape.AddArc( Width-11, Height-11, 10, 10, 0, 90 );
                _Shape.AddArc( 9, Height-11, 10, 10, 90, 90 );
            } else {
                _Shape.AddArc( 0, 0, 10, 10, 180, 90 );
                _Shape.AddArc( Width-18, 0, 10, 10, -90, 90 );
                _Shape.AddArc( Width-18, Height-11, 10, 10, 0, 90 );
                _Shape.AddArc( 0, Height-11, 10, 10, 90, 90 );
            }
            _Shape.CloseAllFigures();

            Invalidate();
            base.OnResize( e );
        }

        protected override void OnPaint( PaintEventArgs e ) {
            base.OnPaint( e );
            Bitmap B=new Bitmap( this.Width, this.Height );
            Graphics G=Graphics.FromImage( B );

            SizeF s=G.MeasureString( Text, Font, Width-25 );
            this.Height=(int)( Math.Floor( s.Height )+10 );

            B=new Bitmap( this.Width, this.Height );
            G=Graphics.FromImage( B );
            var _G=G;

            _G.SmoothingMode=SmoothingMode.HighQuality;
            _G.PixelOffsetMode=PixelOffsetMode.HighQuality;
            _G.Clear( BackColor );

            // Fill the body of the bubble with the specified color
            _G.FillPath( new SolidBrush( _BubbleColor ), Shape );
            // Draw the string specified in 'Text' property
            if ( _BubblePosition==BubblePositionEnum.Left ) {
                _G.DrawString( Text, Font, new SolidBrush( ForeColor ), new Rectangle( 13, 4, Width-25, Height-5 ) );
            } else {
                _G.DrawString( Text, Font, new SolidBrush( ForeColor ), new Rectangle( 5, 4, Width-25, Height-5 ) );
            }

            // Draw a polygon on the right side of the bubble
            if ( _DrawBubbleArrow==true ) {
                if(_BubblePosition == BubblePositionEnum.Left) {
                    Point[] p = {
                        new Point(9, 9),
                        new Point(0, 15),
                        new Point(9, 20)
                   };
                    _G.FillPolygon( new SolidBrush( _BubbleColor ), p );
                    _G.DrawPolygon( new Pen( new SolidBrush( _BubbleColor ) ), p );
                } else {
                    Point[] p = {
                        new Point(Width - 8, 9),
                        new Point(Width, 15),
                        new Point(Width - 8, 20)
                    };
                    _G.FillPolygon( new SolidBrush( _BubbleColor ), p );
                    _G.DrawPolygon( new Pen( new SolidBrush( _BubbleColor ) ), p );
                }
            }
            G.Dispose();
            e.Graphics.InterpolationMode=InterpolationMode.HighQualityBicubic;
            e.Graphics.DrawImageUnscaled( B, 0, 0 );
            B.Dispose();
        }
    }
}

对于我的清单:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the 
            requestedExecutionLevel node with one of the following.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            Specifying requestedExecutionLevel node will disable file and registry virtualization.
            If you want to utilize File and Registry Virtualization for backward 
            compatibility then delete the requestedExecutionLevel node.
        -->
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- A list of all Windows versions that this application is designed to work with. 
      Windows will automatically select the most compatible environment.-->

      <!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>

      <!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>

      <!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>

      <!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node-->
      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>

    </application>
  </compatibility>

  <!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
  <!-- <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>-->

  <asmv1:application>
    <asmv1:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv1:windowsSettings>
  </asmv1:application>
</asmv1:assembly>

对于表单本身来演示控件

    int x = 0;
    while ( x<20 ) {
        messageControl1.Add( "Testing", MessageControl.BubblePositionEnum.Right );
        messageControl1.Add( "Testing", MessageControl.BubblePositionEnum.Right );
        messageControl1.Add( "Testing", MessageControl.BubblePositionEnum.Left );
        x++;
    }

表单设置为缩放为DPI(这是正确的,因此在编辑测试时更改,并使用我的清单,因为这是DPI缩放,而不是字体缩放)。

3 个答案:

答案 0 :(得分:1)

我觉得找到了它。

只需在Redraw函数中添加此行,即可实现仅更新的6个对象

Debug.WriteLine(m.Name + "-" + m.Top + "-" + m.Width);
  

-10-234
  -58-217
  -106-217
  -154-217
  -202-217
  -250-217

第一个错误
测试方法中的这一行修复了创建过程

messageControl1.SuspendLayout(); //add
while (x < 20)
{
    messageControl1.Add("Testing", MessageControl.BubblePositionEnum.Right);
    messageControl1.Add("Testing", MessageControl.BubblePositionEnum.Right);
    messageControl1.Add("Testing", MessageControl.BubblePositionEnum.Left);
    x++;
}
messageControl1.ResumeLayout(); //add
messageControl1.Invalidate();   //add

正如您所见,滚动就在最后。 enter image description here

第二个错误
看起来隐藏元素有不同的大小,你可以看到调试结果 所以我只保存firt元素高度并分配给每个人。

Debug.WriteLine("------------------------------------------------");
int firstHeight = 0;
foreach (Message m in this.Controls)
{
    if (count > 0)
    {
        Debug.WriteLine(m.Height);
        m.Height = firstHeight;
        m.Top = last.Top + firstHeight + _BubbleSpacing + AutoScrollPosition.Y;
        if (VerticalScroll.Visible)
        {
           m.Width = new_width - (_BubbleIndent + _BubbleSpacing + SystemInformation.VerticalScrollBarWidth);
        }
        else
        {
            m.Width = new_width - (_BubbleIndent + _BubbleSpacing);
        }
   }
   else
   {
      firstHeight = m.Height;
   }

   Debug.WriteLine(m.Name + "-" + m.Top + "-" + m.Width);
   last = m;
   count++;
}

答案 1 :(得分:1)

我在谈论通过FlowLayoutPanel进行此操作。 仔细查看所有代码,因为我在整个过程中都进行了重大更改。我建议将其粘贴到一个空白项目中进行播放。

最初加载时的表单:

Initial Form

缩小尺寸后的表格:

Resized Smaller

此处的表单现在滚动到底部,以显示FlowLayoutPanel已经为我重新安排了一切:

Scrolled to the bottom

重新编写的代码:

public partial class Form1 : Form
{

    public Form1()
    {
        this.InitializeComponent();
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
        this.UpdateStyles();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        for (int x = 0; x < 20; x++)
        {
            messageControl1.Add(x.ToString("00") + ": Testing testing testing ...", MessageControl.BubblePositionEnum.Right);
            messageControl1.Add(x.ToString("00") + ": Testing with variable length strings.  This one is longer!", MessageControl.BubblePositionEnum.Right);
            messageControl1.Add(x.ToString("00") + ": Testing is fun.", MessageControl.BubblePositionEnum.Left);
        }
    }

}

public class MessageControl : FlowLayoutPanel 
{

    public List<Message> Messages { get; private set; }

    private Color _LeftBubbleColor = Color.FromArgb(217, 217, 217);
    private Color _RightBubbleColor = Color.FromArgb(192, 206, 215);
    private Color _LeftBubbleTextColor = Color.FromArgb(52, 52, 52);
    private Color _RightBubbleTextColor = Color.FromArgb(52, 52, 52);
    private bool _DrawArrow = true;
    private int _BubbleIndent = 40;
    private int _BubbleSpacing = 10;
    public enum BubblePositionEnum { Left, Right }

    public Color LeftBubbleColor { get { return _LeftBubbleColor; } set { _LeftBubbleColor = value; } }
    public Color RightBubbleColor { get { return _RightBubbleColor; } set { _RightBubbleColor = value; } }
    public Color LeftBubbleTextColor { get { return _LeftBubbleTextColor; } set { _LeftBubbleTextColor = value; } }
    public Color RightBubbleTextColor { get { return _RightBubbleTextColor; } set { _RightBubbleTextColor = value; } }
    public int BubbleIndent { get { return _BubbleIndent; } set { _BubbleIndent = value; } }
    public int BubbleSpacing { get { return _BubbleSpacing; } set { _BubbleSpacing = value; } }
    public bool DrawArrow { get { return _DrawArrow; } set { _DrawArrow = value; } }

    public MessageControl()
    {
        this.Messages = new List<Message>();
        this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
        this.UpdateStyles();
        this.BackColor = Color.Orange;
        this.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
        this.AutoScroll = true;
    }

    public void Remove(Message message)
    {
        this.Messages.Remove(message);
        this.Controls.Remove(message);   
        this.Invalidate();
        this.Refresh();
    }

    public void Remove(Message[] messages)
    {
        this.SuspendLayout();
        foreach (Message m in messages)
        {
            Messages.Remove(m);
            this.Controls.Remove(m);
        }
        this.ResumeLayout();
        this.Invalidate();
        this.Refresh();
    }

    public void Add(string Message, BubblePositionEnum Position)
    {
        Message b = new Message(this, Message, Position);
        b.DrawBubbleArrow = _DrawArrow;
        b.Width = this.ClientSize.Width;
        Messages.Add(b);
        this.Controls.Add(b);
    }

    protected override void OnLayout(LayoutEventArgs levent)
    {
        this.ResizeMessages();
        base.OnLayout(levent);
    }

    protected override void OnResize(System.EventArgs e)
    {
        this.ResizeMessages();
        base.OnResize(e);
    }

    private void ResizeMessages()
    {
        this.SuspendLayout();
        foreach (Message m in this.Messages)
        {
            m.Width = this.ClientSize.Width - 9;
        }
        this.ResumeLayout();
    }

    public class Message : Control
    {

        private MessageControl _mc;
        private GraphicsPath Shape;
        private Color _TextColor = Color.FromArgb(52, 52, 52);
        private Color _BubbleColor = Color.FromArgb(217, 217, 217);
        private bool _DrawBubbleArrow = true;
        private BubblePositionEnum _BubblePosition = BubblePositionEnum.Left;

        public override Color ForeColor { get { return this._TextColor; } set { this._TextColor = value; this.Invalidate(); } }
        public BubblePositionEnum BubblePosition { get { return this._BubblePosition; } set { this._BubblePosition = value; this.Invalidate(); } }
        public Color BubbleColor { get { return this._BubbleColor; } set { this._BubbleColor = value; this.Invalidate(); } }
        public bool DrawBubbleArrow { get { return _DrawBubbleArrow; } set { _DrawBubbleArrow = value; Invalidate(); } }

        private Message() { }

        public Message(MessageControl mc, string Message, BubblePositionEnum Position)
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
            this.UpdateStyles();

            this._mc = mc;
            this._BubblePosition = Position;
            this.Text = Message;
            this.BubbleColor = (Position == BubblePositionEnum.Right ? mc.RightBubbleColor : mc.LeftBubbleColor);
            this.BackColor = this.BubbleColor;
            this.ForeColor = (Position == BubblePositionEnum.Right ? mc.RightBubbleTextColor : mc.LeftBubbleTextColor);
            this.Font = new Font("Segoe UI", 10);

            this.Size = new Size(152, 38);
            this.Anchor = AnchorStyles.Left | AnchorStyles.Right;
        }

        protected override void OnResize(System.EventArgs e)
        {
            base.OnResize(e);

            Shape = new GraphicsPath();
            if (BubblePosition == BubblePositionEnum.Left)
            {
                Shape.AddArc(9, 0, 10, 10, 180, 90);
                Shape.AddArc(Width - 10 - this._mc.BubbleIndent, 0, 10, 10, -90, 90);
                Shape.AddArc(Width - 10 - this._mc.BubbleIndent, Height - 11, 10, 10, 0, 90);
                Shape.AddArc(9, Height - 11, 10, 10, 90, 90);
            }
            else
            {
                Shape.AddArc(this._mc._BubbleIndent, 0, 10, 10, 180, 90);
                Shape.AddArc(Width - 18, 0, 10, 10, -90, 90);
                Shape.AddArc(Width - 18, Height - 11, 10, 10, 0, 90);
                Shape.AddArc(this._mc._BubbleIndent, Height - 11, 10, 10, 90, 90);
            }

            if (_DrawBubbleArrow == true)
            {
                Point[] p;
                if (_BubblePosition == BubblePositionEnum.Left)
                {
                    p = new Point[] {
                        new Point(9, 9),
                        new Point(0, 15),
                        new Point(9, 20)
                    };                      
                }
                else
                {
                    p = new Point[] {
                        new Point(Width - 8, 9),
                        new Point(Width, 15),
                        new Point(Width - 8, 20)
                    };
                }
                Shape.AddPolygon(p);
            }

            Shape.CloseAllFigures();
            this.Region = new Region(Shape);

            this.Invalidate();
            this.Refresh();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            var G = e.Graphics;
            int RenderWidth = this.Width - 10 - this._mc.BubbleIndent;
            SizeF s = G.MeasureString(Text, Font, RenderWidth);
            this.Height = (int)(Math.Floor(s.Height) + 10);

            G.SmoothingMode = SmoothingMode.HighQuality;
            G.PixelOffsetMode = PixelOffsetMode.HighQuality;
            G.InterpolationMode = InterpolationMode.HighQualityBicubic;

            // Draw the string specified in 'Text' property
            using (SolidBrush brush = new SolidBrush(this.ForeColor))
            {
                if (_BubblePosition == BubblePositionEnum.Left)
                {
                    G.DrawString(Text, Font, brush, new Rectangle(13, 4, RenderWidth, Height - 5));
                }
                else
                {
                    G.DrawString(Text, Font, brush, new Rectangle(this._mc.BubbleIndent + 5, 4, RenderWidth, Height - 5));
                }
            }
        }

    }

}

答案 2 :(得分:0)

在这种情况下,我创建了一个代表迷宫的网格。

我的表单有一个Panel控件,然后我在计算Top,Left值时创建按钮。对我来说,按钮大小是固定的,你可以使用你的父值。

我为行=&#34; 01&#34;和col =&#34; 02&#34;命名按钮grid0102
然后选择位置,大小和文本属性。
最后是BackColor for walls

int buttonSize = 20;

Panel myPanel = (Panel)this.Controls["panelArea"];
string[] myGrid = getGrid(0);

for (int row = 0; row < r; row++)
{
     char[] rowChar = myGrid[row].ToCharArray();

     for (int col = 0; col < c; col++)
     {
        Button newButton = new Button();
        newButton.Name = "grid" + row.ToString("D3") + col.ToString("D3");
        newButton.Location = new Point { X = buttonSize * col, Y = buttonSize * row };
        newButton.Size = new Size { Width = buttonSize, Height = buttonSize };
        newButton.Text = rowChar[col].ToString();

        if (rowChar[col] == '%') newButton.BackColor = Color.Green;

        myPanel.Controls.Add(newButton);
        Debug.WriteLine(newButton.Location);
     }
  }

注意已添加

但是如果问题是处理调整大小,只需在代码中放入代码,并在调整Resize事件时调用它。

    private void panelArea_Resize(object sender, EventArgs e)
    {
         UI_Resize();
    }

enter image description here