G
N
I
D
A
O
L

学习备忘-WinForm实现窗体自适应缩放

https://mp.weixin.qq.com/s/E6RRtGzQiRouRP7glapqbw?

如何实现WinForm窗体自适应?

如何实现WinForm窗体自适应。

界面布局

当我们想要实现窗体自适应的时候,优先要通过界面布局设置好窗体和控件的一些属性:

1、Anchor:用于固定控件的边缘到窗体的边缘,当窗体大小改变时,控件的位置也会相应改变。

2、Dock:用于将控件停靠到窗体的边缘,控件的大小会随着窗体边缘的改变而改变。

3、布局控件使用 TableLayoutPanel 或 FlowLayoutPanel 等布局控件可以更好地管理控件的布局,它们可以自动调整大小和位置。

4、Padding:Padding属性定义控件内部的一段空间,用于将控件的内容保持在距控件边框一定的距离。

5、Margin:Margin属性定义控件周围的空间,该空间使其他控件与控件的边框保持指定距离。

 除了以上方法外,在实际应用中,我们更多会使用通过代码来手动调整窗体和控件的大小和位置,这种方法第一次写的时候会麻烦一些,但是封装好之后,后续应用也比较简单。

 

//一、我们创建一个类FormAutoSize,然后创建三个字段,分别是窗体宽度、高度和窗体对象。
public class FormAutoSize
{
    //窗体对象
    private Form form;
    //定义当前窗体的宽度
    private float width; 
    //定义当前窗体的高度
    private float height; 

    //二、在FormAutoSize类的构造方法中,初始化宽度、高度和窗体对象,
    //   同时将各个控件的宽度、高度、左边距、上边距以及字体大小,按照指
    //   定的格式(这里使用分号拼接)存储到AccessibleDescription属性里,
    //   因为AccessibleDescription属性很少使用,所以存储到这个属性里。

    private void SetDescription(Control cons)
    {
        foreach (Control ctl in cons.Controls)
        {
            ctl.AccessibleDescription =   ctl.Width  + ";" 
                                        + ctl.Height + ";" 
                                        + ctl.Left   + ";" 
                                        + ctl.Top    + ";" 
                                        + ctl.Font.Size;
            //递归
            if (ctl.Controls.Count > 0)
            {
                SetDescription(ctl);
            }
        }
    }

    public FormAutoSize(Form form)
    {
        this.form = form;
        width = this.form.Width;
        height = this.form.Height;
        SetDescription(this.form);
    }

    //三、接下来就是如何重置窗体控件布局,这里将当前的宽度高度与初始宽度高度进行相除,    
    //   会得到比例系数scaleX scaleY,然后将这个系数叠加进去,得到新的宽度高度等属性值,
    //   然后重新设置控件属性即可。

    private void SetControls(float scaleX, float scaleY, Control cons)
    {
        //遍历窗体中的控件,重新设置控件的值
        foreach (Control con in cons.Controls)
        {
            //获取控件的AccessibleDescription属性值,并分割后存储字符串数组
            if (con.AccessibleDescription != null)
            {
                var tag = con.AccessibleDescription.ToString().Split(';');
                //根据窗体缩放的比例确定控件的值
                con.Width = Convert.ToInt32(Convert.ToSingle(tag[0]) * scaleX);  //宽度
                con.Height = Convert.ToInt32(Convert.ToSingle(tag[1]) * scaleY); //高度
                con.Left = Convert.ToInt32(Convert.ToSingle(tag[2]) * scaleX);   //左边距
                con.Top = Convert.ToInt32(Convert.ToSingle(tag[3]) * scaleY);    //顶边距
                var currentSize = Convert.ToSingle(tag[4]) * scaleY;             //字体大小                   
                if (currentSize > 0)
                {
                    con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                }
                con.Focus();
                if (con.Controls.Count > 0)
                {
                    SetControls(scaleX, scaleY, con);
                }
            }
        }
    }

    /// <summary>
    /// 重置窗体布局
    /// </summary>
    public void ResumeLayout()
    {
        var scaleX = form.Width / width;
        var scaleY = form.Height / height;
        SetControls(scaleX, scaleY, form);
    }

}

 四、最后一步就是如何进行调用:首先在需要进行缩放的窗体中定义一个FormAutoSize对象,然后在构造方法中实例化该对象,将当前窗体this作为参数传递进去,最后在窗体的SizeChanged事件中调用该对象的ResumeLayout方法。

private FormAutoSize formAutoSize;
public FrmMain()
{
    InitializeComponent();
    formAutoSize = new FormAutoSize(this);
    this.SizeChanged += (sender, e) =>
    {
        formAutoSize.ResumeLayout();
    };
}

 

posted @ 2025-03-23 20:08  firespeed  阅读(24)  评论(0)    收藏  举报